1 /* 2 3 * Copyright (C) 2014 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.cts.verifier.sensors.base; 19 20 import com.android.cts.verifier.sensors.reporting.SensorTestDetails; 21 22 import android.hardware.cts.helpers.reporting.ISensorTestNode; 23 24 import java.lang.reflect.InvocationTargetException; 25 import java.lang.reflect.Method; 26 import java.lang.reflect.Modifier; 27 import java.util.ArrayList; 28 import java.util.List; 29 30 /** 31 * An Activity that provides a test execution engine for Sensor CtsVerifier tests. The tests are 32 * able to interact with an operator. 33 * 34 * Sub-classes reuse its own class definition to 'load' tests at runtime through reflection. 35 */ 36 public abstract class SensorCtsVerifierTestActivity extends BaseSensorTestActivity { 37 private volatile int mTestPassedCounter; 38 private volatile int mTestSkippedCounter; 39 private volatile int mTestFailedCounter; 40 private volatile ISensorTestNode mCurrentTestNode; 41 42 /** 43 * {@inheritDoc} 44 */ 45 protected SensorCtsVerifierTestActivity( 46 Class<? extends SensorCtsVerifierTestActivity> testClass) { 47 super(testClass); 48 } 49 50 /** 51 * Executes Semi-automated Sensor tests. 52 * Execution is driven by this class, and allows discovery of tests using reflection. 53 */ 54 @Override 55 protected SensorTestDetails executeTests() throws InterruptedException { 56 // TODO: use reporting to log individual test results 57 for (Method testMethod : findTestMethods()) { 58 SensorTestDetails testDetails = executeTest(testMethod); 59 getTestLogger().logTestDetails(testDetails); 60 } 61 return new SensorTestDetails( 62 getApplicationContext(), 63 getTestClassName(), 64 mTestPassedCounter, 65 mTestSkippedCounter, 66 mTestFailedCounter); 67 } 68 69 protected ISensorTestNode getCurrentTestNode() { 70 return mCurrentTestNode; 71 } 72 73 private List<Method> findTestMethods() { 74 ArrayList<Method> testMethods = new ArrayList<>(); 75 for (Method method : mTestClass.getDeclaredMethods()) { 76 if (Modifier.isPublic(method.getModifiers()) 77 && method.getParameterTypes().length == 0 78 && method.getName().startsWith("test") 79 && method.getReturnType().equals(String.class)) { 80 testMethods.add(method); 81 } 82 } 83 return testMethods; 84 } 85 86 private SensorTestDetails executeTest(Method testMethod) throws InterruptedException { 87 String testMethodName = testMethod.getName(); 88 String testName = String.format("%s#%s", getTestClassName(), testMethodName); 89 mCurrentTestNode = new TestNode(testMethod); 90 91 SensorTestDetails testDetails; 92 try { 93 getTestLogger().logTestStart(testMethodName); 94 String testSummary = (String) testMethod.invoke(this); 95 testDetails = 96 new SensorTestDetails(testName, SensorTestDetails.ResultCode.PASS, testSummary); 97 } catch (InvocationTargetException e) { 98 // get the inner exception, because we use reflection APIs to execute the test 99 testDetails = new SensorTestDetails(testName, "TestExecution", e.getCause()); 100 } catch (Throwable e) { 101 testDetails = new SensorTestDetails(testName, "TestInfrastructure", e); 102 } 103 104 SensorTestDetails.ResultCode resultCode = testDetails.getResultCode(); 105 switch(resultCode) { 106 case PASS: 107 ++mTestPassedCounter; 108 break; 109 case SKIPPED: 110 ++mTestSkippedCounter; 111 break; 112 case INTERRUPTED: 113 throw new InterruptedException(); 114 case FAIL: 115 ++mTestFailedCounter; 116 break; 117 default: 118 throw new IllegalStateException("Unknown ResultCode: " + resultCode); 119 } 120 121 return testDetails; 122 } 123 124 private class TestNode implements ISensorTestNode { 125 private final Method mTestMethod; 126 127 public TestNode(Method testMethod) { 128 mTestMethod = testMethod; 129 } 130 131 @Override 132 public String getName() { 133 return mTestClass.getSimpleName() + "_" + mTestMethod.getName(); 134 } 135 } 136 } 137