Home | History | Annotate | Download | only in base
      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