1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.hardware.cts.helpers.sensoroperations; 18 19 import junit.framework.TestCase; 20 21 import android.hardware.cts.helpers.SensorStats; 22 import android.hardware.cts.helpers.SensorTestPlatformException; 23 import android.hardware.cts.helpers.reporting.ISensorTestNode; 24 25 import java.util.Set; 26 import java.util.concurrent.TimeUnit; 27 28 /** 29 * Tests for the primitive {@link SensorOperation}s including {@link DelaySensorOperation}, 30 * {@link ParallelSensorOperation}, {@link RepeatingSensorOperation} and 31 * {@link SequentialSensorOperation}. 32 */ 33 public class SensorOperationTest extends TestCase { 34 private static final long TEST_DURATION_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(5); 35 36 private final ISensorTestNode mTestNode = new ISensorTestNode() { 37 @Override 38 public String getName() throws SensorTestPlatformException { 39 return "SensorOperationUnitTest"; 40 } 41 }; 42 43 /** 44 * Test that the {@link FakeSensorOperation} functions correctly. Other tests in this class 45 * rely on this operation. 46 */ 47 public void testFakeSensorOperation() throws Exception { 48 final int opDurationMs = 100; 49 50 SensorOperation op = new FakeSensorOperation(opDurationMs, TimeUnit.MILLISECONDS); 51 52 assertFalse(op.getStats().flatten().containsKey("executed")); 53 long start = System.currentTimeMillis(); 54 op.execute(mTestNode); 55 long duration = System.currentTimeMillis() - start; 56 assertTrue(Math.abs(opDurationMs - duration) < TEST_DURATION_THRESHOLD_MS); 57 assertTrue(op.getStats().flatten().containsKey("executed")); 58 59 op = new FakeSensorOperation(true, 0, TimeUnit.MILLISECONDS); 60 try { 61 op.execute(mTestNode); 62 throw new Error("AssertionError expected"); 63 } catch (AssertionError e) { 64 // Expected 65 } 66 assertTrue(op.getStats().flatten().keySet().contains(SensorStats.ERROR)); 67 } 68 69 /** 70 * Test that the {@link DelaySensorOperation} functions correctly. 71 */ 72 public void testDelaySensorOperation() throws Exception { 73 final int opDurationMs = 500; 74 final int subOpDurationMs = 100; 75 76 FakeSensorOperation subOp = new FakeSensorOperation(subOpDurationMs, TimeUnit.MILLISECONDS); 77 SensorOperation op = new DelaySensorOperation(subOp, opDurationMs, TimeUnit.MILLISECONDS); 78 79 long startMs = System.currentTimeMillis(); 80 op.execute(mTestNode); 81 long durationMs = System.currentTimeMillis() - startMs; 82 long durationDeltaMs = Math.abs(opDurationMs + subOpDurationMs - durationMs); 83 assertTrue(durationDeltaMs < TEST_DURATION_THRESHOLD_MS); 84 } 85 86 /** 87 * Test that the {@link ParallelSensorOperation} functions correctly. 88 */ 89 public void testParallelSensorOperation() throws Exception { 90 final int subOpCount = 100; 91 final int subOpDurationMs = 500; 92 93 ParallelSensorOperation op = new ParallelSensorOperation(); 94 for (int i = 0; i < subOpCount; i++) { 95 SensorOperation subOp = new FakeSensorOperation(subOpDurationMs, 96 TimeUnit.MILLISECONDS); 97 op.add(subOp); 98 } 99 100 Set<String> statsKeys = op.getStats().flatten().keySet(); 101 assertEquals(0, statsKeys.size()); 102 103 long start = System.currentTimeMillis(); 104 op.execute(mTestNode); 105 long durationMs = System.currentTimeMillis() - start; 106 long durationDeltaMs = Math.abs(subOpDurationMs - durationMs); 107 String message = String.format( 108 "Expected duration=%sms, observed=%sms, delta=%sms, thresold=%sms", 109 subOpDurationMs, 110 durationMs, 111 durationDeltaMs, 112 TEST_DURATION_THRESHOLD_MS); 113 // starting threads might have an impact in the order of 100s ms, depending on the load of 114 // the system, so we relax the benchmark part of the test, and we just expect all operations 115 // to complete 116 assertTrue(message, durationDeltaMs < TEST_DURATION_THRESHOLD_MS); 117 118 statsKeys = op.getStats().flatten().keySet(); 119 assertEquals(subOpCount, statsKeys.size()); 120 for (int i = 0; i < subOpCount; i++) { 121 assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", 122 ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); 123 } 124 } 125 126 /** 127 * Test that the {@link ParallelSensorOperation} functions correctly if there is a failure in 128 * a child operation. 129 */ 130 public void testParallelSensorOperation_fail() throws Exception { 131 final int subOpCount = 100; 132 133 ParallelSensorOperation op = new ParallelSensorOperation(); 134 for (int i = 0; i < subOpCount; i++) { 135 // Trigger failures in the 5th, 55th operations at t=5ms, t=55ms 136 SensorOperation subOp = new FakeSensorOperation(i % 50 == 5, i, TimeUnit.MILLISECONDS); 137 op.add(subOp); 138 } 139 140 Set<String> statsKeys = op.getStats().flatten().keySet(); 141 assertEquals(0, statsKeys.size()); 142 143 try { 144 op.execute(mTestNode); 145 fail("AssertionError expected"); 146 } catch (AssertionError e) { 147 // Expected 148 System.out.println(e.getMessage()); 149 } 150 151 statsKeys = op.getStats().flatten().keySet(); 152 assertEquals(subOpCount + 3, statsKeys.size()); 153 for (int i = 0; i < subOpCount; i++) { 154 assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", 155 ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); 156 if (i % 50 == 5) { 157 assertTrue(statsKeys.contains(String.format("%s_%03d%s%s", 158 ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER, 159 SensorStats.ERROR))); 160 } 161 162 } 163 assertTrue(statsKeys.contains(SensorStats.ERROR)); 164 } 165 166 /** 167 * Test that the {@link ParallelSensorOperation} functions correctly if a child exceeds the 168 * timeout. 169 */ 170 public void testParallelSensorOperation_timeout() throws Exception { 171 final int subOpCount = 100; 172 173 ParallelSensorOperation op = new ParallelSensorOperation(1, TimeUnit.SECONDS); 174 for (int i = 0; i < subOpCount; i++) { 175 // Trigger timeouts in the 5th, 55th operations (5 seconds vs 1 seconds) 176 SensorOperation subOp = new FakeSensorOperation(i % 50 == 5 ? 5 : 0, TimeUnit.SECONDS); 177 op.add(subOp); 178 } 179 180 Set<String> statsKeys = op.getStats().flatten().keySet(); 181 assertEquals(0, statsKeys.size()); 182 183 try { 184 op.execute(mTestNode); 185 fail("AssertionError expected"); 186 } catch (AssertionError e) { 187 // Expected 188 System.out.println(e.getMessage()); 189 } 190 191 statsKeys = op.getStats().flatten().keySet(); 192 assertEquals(subOpCount - 2, statsKeys.size()); 193 for (int i = 0; i < subOpCount; i++) { 194 if (i % 50 != 5) { 195 assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", 196 ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); 197 } 198 } 199 } 200 201 /** 202 * Test that the {@link RepeatingSensorOperation} functions correctly. 203 */ 204 public void testRepeatingSensorOperation() throws Exception { 205 final int iterations = 10; 206 final int subOpDurationMs = 100; 207 208 SensorOperation subOp = new FakeSensorOperation(subOpDurationMs, TimeUnit.MILLISECONDS); 209 SensorOperation op = new RepeatingSensorOperation(subOp, iterations); 210 211 Set<String> statsKeys = op.getStats().flatten().keySet(); 212 assertEquals(0, statsKeys.size()); 213 214 long start = System.currentTimeMillis(); 215 op.execute(mTestNode); 216 long duration = System.currentTimeMillis() - start; 217 assertTrue(Math.abs(subOpDurationMs * iterations - duration) < TEST_DURATION_THRESHOLD_MS); 218 219 statsKeys = op.getStats().flatten().keySet(); 220 assertEquals(iterations, statsKeys.size()); 221 for (int i = 0; i < iterations; i++) { 222 assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", 223 RepeatingSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); 224 } 225 } 226 227 /** 228 * Test that the {@link RepeatingSensorOperation} functions correctly if there is a failure in 229 * a child operation. 230 */ 231 public void testRepeatingSensorOperation_fail() throws Exception { 232 final int iterations = 100; 233 final int failCount = 75; 234 235 SensorOperation subOp = new FakeSensorOperation(0, TimeUnit.MILLISECONDS) { 236 private int mExecutedCount = 0; 237 private SensorStats mFakeStats = new SensorStats(); 238 239 @Override 240 public void execute(ISensorTestNode parent) { 241 super.execute(parent); 242 mExecutedCount++; 243 244 if (failCount == mExecutedCount) { 245 doFail(); 246 } 247 } 248 249 @Override 250 public FakeSensorOperation clone() { 251 // Don't clone 252 mFakeStats = new SensorStats(); 253 return this; 254 } 255 256 @Override 257 public SensorStats getStats() { 258 return mFakeStats; 259 } 260 }; 261 SensorOperation op = new RepeatingSensorOperation(subOp, iterations); 262 263 Set<String> statsKeys = op.getStats().flatten().keySet(); 264 assertEquals(0, statsKeys.size()); 265 266 try { 267 op.execute(mTestNode); 268 fail("AssertionError expected"); 269 } catch (AssertionError e) { 270 // Expected 271 System.out.println(e.getMessage()); 272 } 273 274 statsKeys = op.getStats().flatten().keySet(); 275 assertEquals(failCount + 2, statsKeys.size()); 276 for (int i = 0; i < failCount; i++) { 277 assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", 278 RepeatingSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); 279 } 280 assertTrue(statsKeys.contains(String.format("%s_%03d%s%s", 281 RepeatingSensorOperation.STATS_TAG, failCount - 1, SensorStats.DELIMITER, 282 SensorStats.ERROR))); 283 assertTrue(statsKeys.contains(SensorStats.ERROR)); 284 } 285 286 /** 287 * Test that the {@link SequentialSensorOperation} functions correctly. 288 */ 289 public void testSequentialSensorOperation() throws Exception { 290 final int subOpCount = 10; 291 final int subOpDurationMs = 100; 292 293 SequentialSensorOperation op = new SequentialSensorOperation(); 294 for (int i = 0; i < subOpCount; i++) { 295 SensorOperation subOp = new FakeSensorOperation(subOpDurationMs, 296 TimeUnit.MILLISECONDS); 297 op.add(subOp); 298 } 299 300 Set<String> statsKeys = op.getStats().flatten().keySet(); 301 assertEquals(0, statsKeys.size()); 302 303 long start = System.currentTimeMillis(); 304 op.execute(mTestNode); 305 long duration = System.currentTimeMillis() - start; 306 assertTrue(Math.abs(subOpDurationMs * subOpCount - duration) < TEST_DURATION_THRESHOLD_MS); 307 308 statsKeys = op.getStats().flatten().keySet(); 309 assertEquals(subOpCount, statsKeys.size()); 310 for (int i = 0; i < subOpCount; i++) { 311 assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", 312 SequentialSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); 313 } 314 } 315 316 /** 317 * Test that the {@link SequentialSensorOperation} functions correctly if there is a failure in 318 * a child operation. 319 */ 320 public void testSequentialSensorOperation_fail() throws Exception { 321 final int subOpCount = 100; 322 final int failCount = 75; 323 324 SequentialSensorOperation op = new SequentialSensorOperation(); 325 for (int i = 0; i < subOpCount; i++) { 326 // Trigger a failure in the 75th operation only 327 SensorOperation subOp = new FakeSensorOperation(i + 1 == failCount, 0, 328 TimeUnit.MILLISECONDS); 329 op.add(subOp); 330 } 331 332 Set<String> statsKeys = op.getStats().flatten().keySet(); 333 assertEquals(0, statsKeys.size()); 334 335 try { 336 op.execute(mTestNode); 337 fail("AssertionError expected"); 338 } catch (AssertionError e) { 339 // Expected 340 System.out.println(e.getMessage()); 341 } 342 343 statsKeys = op.getStats().flatten().keySet(); 344 assertEquals(failCount + 2, statsKeys.size()); 345 for (int i = 0; i < failCount; i++) { 346 assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted", 347 SequentialSensorOperation.STATS_TAG, i, SensorStats.DELIMITER))); 348 } 349 assertTrue(statsKeys.contains(String.format("%s_%03d%s%s", 350 SequentialSensorOperation.STATS_TAG, failCount - 1, SensorStats.DELIMITER, 351 SensorStats.ERROR))); 352 assertTrue(statsKeys.contains(SensorStats.ERROR)); 353 } 354 } 355