| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.hardware.cts.helpers.sensoroperations; |
| |
| import junit.framework.TestCase; |
| |
| import android.hardware.cts.helpers.SensorStats; |
| import android.hardware.cts.helpers.SensorTestPlatformException; |
| import android.hardware.cts.helpers.reporting.ISensorTestNode; |
| |
| import java.util.Set; |
| import java.util.concurrent.TimeUnit; |
| |
| /** |
| * Tests for the primitive {@link SensorOperation}s including {@link DelaySensorOperation}, |
| * {@link ParallelSensorOperation}, {@link RepeatingSensorOperation} and |
| * {@link SequentialSensorOperation}. |
| */ |
| public class SensorOperationTest extends TestCase { |
| private static final long TEST_DURATION_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(5); |
| |
| private final ISensorTestNode mTestNode = new ISensorTestNode() { |
| @Override |
| public String getName() throws SensorTestPlatformException { |
| return "SensorOperationUnitTest"; |
| } |
| }; |
| |
| /** |
| * Test that the {@link FakeSensorOperation} functions correctly. Other tests in this class |
| * rely on this operation. |
| */ |
| public void testFakeSensorOperation() throws InterruptedException { |
| final int opDurationMs = 100; |
| |
| SensorOperation op = new FakeSensorOperation(opDurationMs, TimeUnit.MILLISECONDS); |
| |
| assertFalse(op.getStats().flatten().containsKey("executed")); |
| long start = System.currentTimeMillis(); |
| op.execute(mTestNode); |
| long duration = System.currentTimeMillis() - start; |
| assertTrue(Math.abs(opDurationMs - duration) < TEST_DURATION_THRESHOLD_MS); |
| assertTrue(op.getStats().flatten().containsKey("executed")); |
| |
| op = new FakeSensorOperation(true, 0, TimeUnit.MILLISECONDS); |
| try { |
| op.execute(mTestNode); |
| fail("AssertionError expected"); |
| } catch (AssertionError e) { |
| // Expected |
| } |
| assertTrue(op.getStats().flatten().keySet().contains(SensorStats.ERROR)); |
| } |
| |
| /** |
| * Test that the {@link DelaySensorOperation} functions correctly. |
| */ |
| public void testDelaySensorOperation() throws InterruptedException { |
| final int opDurationMs = 500; |
| final int subOpDurationMs = 100; |
| |
| FakeSensorOperation subOp = new FakeSensorOperation(subOpDurationMs, TimeUnit.MILLISECONDS); |
| SensorOperation op = new DelaySensorOperation(subOp, opDurationMs, TimeUnit.MILLISECONDS); |
| |
| long startMs = System.currentTimeMillis(); |
| op.execute(mTestNode); |
| long durationMs = System.currentTimeMillis() - startMs; |
| long durationDeltaMs = Math.abs(opDurationMs + subOpDurationMs - durationMs); |
| assertTrue(durationDeltaMs < TEST_DURATION_THRESHOLD_MS); |
| } |
| |
| /** |
| * Test that the {@link ParallelSensorOperation} functions correctly. |
| */ |
| public void testParallelSensorOperation() throws InterruptedException { |
| final int subOpCount = 100; |
| final int subOpDurationMs = 500; |
| |
| ParallelSensorOperation op = new ParallelSensorOperation(); |
| for (int i = 0; i < subOpCount; i++) { |
| SensorOperation subOp = new FakeSensorOperation(subOpDurationMs, |
| TimeUnit.MILLISECONDS); |
| op.add(subOp); |
| } |
| |
| Set<String> statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(0, statsKeys.size()); |
| |
| long start = System.currentTimeMillis(); |
| op.execute(mTestNode); |
| long durationMs = System.currentTimeMillis() - start; |
| long durationDeltaMs = Math.abs(subOpDurationMs - durationMs); |
| String message = String.format( |
| "Expected duration=%sms, observed=%sms, delta=%sms, thresold=%sms", |
| subOpDurationMs, |
| durationMs, |
| durationDeltaMs, |
| TEST_DURATION_THRESHOLD_MS); |
| // starting threads might have an impact in the order of 100s ms, depending on the load of |
| // the system, so we relax the benchmark part of the test, and we just expect all operations |
| // to complete |
| assertTrue(message, durationDeltaMs < TEST_DURATION_THRESHOLD_MS); |
| |
| statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(subOpCount, statsKeys.size()); |
| for (int i = 0; i < subOpCount; i++) { |
| assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", |
| ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); |
| } |
| } |
| |
| /** |
| * Test that the {@link ParallelSensorOperation} functions correctly if there is a failure in |
| * a child operation. |
| */ |
| public void testParallelSensorOperation_fail() throws InterruptedException { |
| final int subOpCount = 100; |
| |
| ParallelSensorOperation op = new ParallelSensorOperation(); |
| for (int i = 0; i < subOpCount; i++) { |
| // Trigger failures in the 5th, 55th operations at t=5ms, t=55ms |
| SensorOperation subOp = new FakeSensorOperation(i % 50 == 5, i, TimeUnit.MILLISECONDS); |
| op.add(subOp); |
| } |
| |
| Set<String> statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(0, statsKeys.size()); |
| |
| try { |
| op.execute(mTestNode); |
| fail("AssertionError expected"); |
| } catch (AssertionError e) { |
| // Expected |
| System.out.println(e.getMessage()); |
| } |
| |
| statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(subOpCount + 3, statsKeys.size()); |
| for (int i = 0; i < subOpCount; i++) { |
| assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", |
| ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); |
| if (i % 50 == 5) { |
| assertTrue(statsKeys.contains(String.format("%s_%03d%s%s", |
| ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER, |
| SensorStats.ERROR))); |
| } |
| |
| } |
| assertTrue(statsKeys.contains(SensorStats.ERROR)); |
| } |
| |
| /** |
| * Test that the {@link ParallelSensorOperation} functions correctly if a child exceeds the |
| * timeout. |
| */ |
| public void testParallelSensorOperation_timeout() throws InterruptedException { |
| final int subOpCount = 100; |
| |
| ParallelSensorOperation op = new ParallelSensorOperation(1, TimeUnit.SECONDS); |
| for (int i = 0; i < subOpCount; i++) { |
| // Trigger timeouts in the 5th, 55th operations (5 seconds vs 1 seconds) |
| SensorOperation subOp = new FakeSensorOperation(i % 50 == 5 ? 5 : 0, TimeUnit.SECONDS); |
| op.add(subOp); |
| } |
| |
| Set<String> statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(0, statsKeys.size()); |
| |
| try { |
| op.execute(mTestNode); |
| fail("AssertionError expected"); |
| } catch (AssertionError e) { |
| // Expected |
| System.out.println(e.getMessage()); |
| } |
| |
| statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(subOpCount - 2, statsKeys.size()); |
| for (int i = 0; i < subOpCount; i++) { |
| if (i % 50 != 5) { |
| assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", |
| ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); |
| } |
| } |
| } |
| |
| /** |
| * Test that the {@link RepeatingSensorOperation} functions correctly. |
| */ |
| public void testRepeatingSensorOperation() throws InterruptedException { |
| final int iterations = 10; |
| final int subOpDurationMs = 100; |
| |
| SensorOperation subOp = new FakeSensorOperation(subOpDurationMs, TimeUnit.MILLISECONDS); |
| SensorOperation op = new RepeatingSensorOperation(subOp, iterations); |
| |
| Set<String> statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(0, statsKeys.size()); |
| |
| long start = System.currentTimeMillis(); |
| op.execute(mTestNode); |
| long duration = System.currentTimeMillis() - start; |
| assertTrue(Math.abs(subOpDurationMs * iterations - duration) < TEST_DURATION_THRESHOLD_MS); |
| |
| statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(iterations, statsKeys.size()); |
| for (int i = 0; i < iterations; i++) { |
| assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", |
| RepeatingSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); |
| } |
| } |
| |
| /** |
| * Test that the {@link RepeatingSensorOperation} functions correctly if there is a failure in |
| * a child operation. |
| */ |
| public void testRepeatingSensorOperation_fail() throws InterruptedException { |
| final int iterations = 100; |
| final int failCount = 75; |
| |
| SensorOperation subOp = new FakeSensorOperation(0, TimeUnit.MILLISECONDS) { |
| private int mExecutedCount = 0; |
| private SensorStats mFakeStats = new SensorStats(); |
| |
| @Override |
| public void execute(ISensorTestNode parent) { |
| super.execute(parent); |
| mExecutedCount++; |
| |
| if (failCount == mExecutedCount) { |
| doFail(); |
| } |
| } |
| |
| @Override |
| public FakeSensorOperation clone() { |
| // Don't clone |
| mFakeStats = new SensorStats(); |
| return this; |
| } |
| |
| @Override |
| public SensorStats getStats() { |
| return mFakeStats; |
| } |
| }; |
| SensorOperation op = new RepeatingSensorOperation(subOp, iterations); |
| |
| Set<String> statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(0, statsKeys.size()); |
| |
| try { |
| op.execute(mTestNode); |
| fail("AssertionError expected"); |
| } catch (AssertionError e) { |
| // Expected |
| System.out.println(e.getMessage()); |
| } |
| |
| statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(failCount + 2, statsKeys.size()); |
| for (int i = 0; i < failCount; i++) { |
| assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", |
| RepeatingSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); |
| } |
| assertTrue(statsKeys.contains(String.format("%s_%03d%s%s", |
| RepeatingSensorOperation.STATS_TAG, failCount - 1, SensorStats.DELIMITER, |
| SensorStats.ERROR))); |
| assertTrue(statsKeys.contains(SensorStats.ERROR)); |
| } |
| |
| /** |
| * Test that the {@link SequentialSensorOperation} functions correctly. |
| */ |
| public void testSequentialSensorOperation() throws InterruptedException { |
| final int subOpCount = 10; |
| final int subOpDurationMs = 100; |
| |
| SequentialSensorOperation op = new SequentialSensorOperation(); |
| for (int i = 0; i < subOpCount; i++) { |
| SensorOperation subOp = new FakeSensorOperation(subOpDurationMs, |
| TimeUnit.MILLISECONDS); |
| op.add(subOp); |
| } |
| |
| Set<String> statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(0, statsKeys.size()); |
| |
| long start = System.currentTimeMillis(); |
| op.execute(mTestNode); |
| long duration = System.currentTimeMillis() - start; |
| assertTrue(Math.abs(subOpDurationMs * subOpCount - duration) < TEST_DURATION_THRESHOLD_MS); |
| |
| statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(subOpCount, statsKeys.size()); |
| for (int i = 0; i < subOpCount; i++) { |
| assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", |
| SequentialSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); |
| } |
| } |
| |
| /** |
| * Test that the {@link SequentialSensorOperation} functions correctly if there is a failure in |
| * a child operation. |
| */ |
| public void testSequentialSensorOperation_fail() throws InterruptedException { |
| final int subOpCount = 100; |
| final int failCount = 75; |
| |
| SequentialSensorOperation op = new SequentialSensorOperation(); |
| for (int i = 0; i < subOpCount; i++) { |
| // Trigger a failure in the 75th operation only |
| SensorOperation subOp = new FakeSensorOperation(i + 1 == failCount, 0, |
| TimeUnit.MILLISECONDS); |
| op.add(subOp); |
| } |
| |
| Set<String> statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(0, statsKeys.size()); |
| |
| try { |
| op.execute(mTestNode); |
| fail("AssertionError expected"); |
| } catch (AssertionError e) { |
| // Expected |
| System.out.println(e.getMessage()); |
| } |
| |
| statsKeys = op.getStats().flatten().keySet(); |
| assertEquals(failCount + 2, statsKeys.size()); |
| for (int i = 0; i < failCount; i++) { |
| assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", |
| SequentialSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); |
| } |
| assertTrue(statsKeys.contains(String.format("%s_%03d%s%s", |
| SequentialSensorOperation.STATS_TAG, failCount - 1, SensorStats.DELIMITER, |
| SensorStats.ERROR))); |
| assertTrue(statsKeys.contains(SensorStats.ERROR)); |
| } |
| } |