Home | History | Annotate | Download | only in TestPhase
      1 /*
      2  * Copyright (C) 2016 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 com.android.cts.verifier.sensors.sixdof.Utils.TestPhase;
     18 
     19 import com.android.cts.verifier.sensors.sixdof.Dialogs.BaseResultsDialog;
     20 import com.android.cts.verifier.sensors.sixdof.Utils.Manager;
     21 import com.android.cts.verifier.sensors.sixdof.Utils.MathsUtils;
     22 import com.android.cts.verifier.sensors.sixdof.Utils.TestReport;
     23 import com.android.cts.verifier.sensors.sixdof.Utils.Exceptions.WaypointAreaCoveredException;
     24 import com.android.cts.verifier.sensors.sixdof.Utils.Exceptions.WaypointDistanceException;
     25 import com.android.cts.verifier.sensors.sixdof.Utils.Exceptions.WaypointRingNotEnteredException;
     26 import com.android.cts.verifier.sensors.sixdof.Utils.Exceptions.WaypointStartPointException;
     27 import com.android.cts.verifier.sensors.sixdof.Utils.Path.AccuracyPath;
     28 import com.android.cts.verifier.sensors.sixdof.Utils.Path.Path;
     29 import com.android.cts.verifier.sensors.sixdof.Utils.Path.ReferencePath;
     30 import com.android.cts.verifier.sensors.sixdof.Utils.Path.PathUtilityClasses.Waypoint;
     31 
     32 import android.util.Log;
     33 
     34 import java.util.ArrayList;
     35 import java.util.HashMap;
     36 
     37 /**
     38  * TestPhase generic class will be inherited by the other tests.
     39  */
     40 public abstract class Test {
     41     public static final int MAX_MARKER_NUMBER = 5;
     42     private static final float FAILURE_TOLERANCE_PERCENTAGE = 0.025f; // 2.5%
     43     private String mTestPhaseName;
     44 
     45     protected ArrayList<Float> mMarkerAccuracy = new ArrayList<>();
     46     protected ArrayList<Float> mPathAccuracy = new ArrayList<>();
     47     protected ArrayList<Float> mReferencePathDistances = new ArrayList<>();
     48     private ArrayList<Float> mTestPathDistances = new ArrayList<>();
     49 
     50     protected ReferencePath mReferencePath;
     51     protected Path mTestPath;
     52     protected TestReport mTestReport;
     53     protected Manager mManager;
     54 
     55     /**
     56      * Constructor for this class.
     57      *
     58      * @param referencePath Reference the the reference path.
     59      * @param testReport    The test report object to record the tests.
     60      * @param manager       The manager to call when the test is done.
     61      */
     62     public Test(ReferencePath referencePath, TestReport testReport, Manager manager, String testPhase) {
     63         if (referencePath != null) {
     64             mReferencePath = referencePath;
     65         } else {
     66             throw new AssertionError("TestPhase received a null referencePath", null);
     67         }
     68         mTestPhaseName = testPhase;
     69         mTestReport = testReport;
     70         mManager = manager;
     71         mTestPath = new AccuracyPath();
     72         mReferencePathDistances = calculatePathDistance(mReferencePath.getCurrentPath(), mReferencePath.getPathMarkers());
     73     }
     74 
     75     /**
     76      * Adds the current waypoint to the test path.
     77      *
     78      * @param coordinates   the coordinates to use for the waypoint.
     79      * @param userGenerated indicates whether the data was user created or system created.
     80      * @param currentLap    the lap the data was created in.
     81      * @throws WaypointDistanceException    if the location is too close to another.
     82      * @throws WaypointAreaCoveredException if the area covered by the user is too little.
     83      * @throws WaypointStartPointException  if the location is not close enough to the start.
     84      */
     85     public void addWaypointDataToPath(
     86             float[] coordinates, boolean userGenerated, Manager.Lap currentLap)
     87             throws WaypointAreaCoveredException, WaypointDistanceException,
     88             WaypointStartPointException, WaypointRingNotEnteredException {
     89         mTestPath.createWaypointAndAddToPath(coordinates, userGenerated, currentLap);
     90         runAdditionalMethods();
     91     }
     92 
     93     /**
     94      * Abstract method that is used but subclasses.
     95      */
     96     protected abstract void runAdditionalMethods();
     97 
     98     /**
     99      * Removes the last marker from the chosen lap.
    100      *
    101      * @return true of the first marker false if any other marker
    102      */
    103     public boolean removeLastAddedMarker() {
    104         return mTestPath.removeLastMarker();
    105     }
    106 
    107     /**
    108      * Performs the tests for this test phase.
    109      *
    110      * @return the state of the tests, true if they pass false if they fail.
    111      */
    112     protected HashMap<BaseResultsDialog.ResultType, Boolean> executeTests(boolean includeMarkerTest, boolean includePathTest) {
    113         HashMap<BaseResultsDialog.ResultType, Boolean> testResults = new HashMap<>();
    114         if (includePathTest) {
    115             testResults.put(BaseResultsDialog.ResultType.PATH, pathTest());
    116         }
    117         if (includeMarkerTest) {
    118             testResults.put(BaseResultsDialog.ResultType.WAYPOINT, markerTest());
    119         }
    120         return testResults;
    121     }
    122 
    123     /**
    124      * Calculates the difference between the markers of the laps and executes the marker related
    125      * test.
    126      *
    127      * @return true if the test passes and false if the rest fails.
    128      */
    129     private boolean markerTest() {
    130         float distance;
    131         for (int i = 0; i < mReferencePath.getPathMarkersSize(); i++) {
    132             distance = MathsUtils.distanceCalculationInXYZSpace(
    133                     mReferencePath.getPathMarkers().get(i).getCoordinates(),
    134                     mTestPath.getPathMarkers().get(i).getCoordinates());
    135             mMarkerAccuracy.add(distance);
    136         }
    137         return markerAccuracyTest();
    138     }
    139 
    140     /**
    141      * Runs a check to find any markers that have failed the test and adds them to the test report.
    142      *
    143      * @return true if the test passes and false if the rest fails
    144      */
    145     private boolean markerAccuracyTest() {
    146         boolean testState = true;
    147         for (float markerDifference : mMarkerAccuracy) {
    148             if (markerDifference > mReferencePath.getFailureTolerance()) {
    149                 recordMarkerTestResults(markerDifference);
    150                 testState = false;
    151             }
    152         }
    153         return testState;
    154     }
    155 
    156     /**
    157      * Formats the failed markers into a string to add it to the test report.
    158      *
    159      * @param markerDifference the difference which caused the marker to fail
    160      */
    161     private void recordMarkerTestResults(float markerDifference) {
    162         int markerNumber = mMarkerAccuracy.indexOf(markerDifference);
    163         String referenceMarker = MathsUtils.coordinatesToString(
    164                 mReferencePath.getPathMarkers().get(markerNumber).getCoordinates());
    165         String testMarker = MathsUtils.coordinatesToString(
    166                 mTestPath.getPathMarkers().get(markerNumber).getCoordinates());
    167         String testDetails = mTestPhaseName +
    168                 " Marker Accuracy: Distance between the markers too great. Marker: " + markerNumber +
    169                 " Difference: " + markerDifference +
    170                 " Coordinates " + referenceMarker + " " + testMarker + "\n";
    171         Log.e("Marker Result", testDetails);
    172         mTestReport.setFailDetails(testDetails);
    173     }
    174 
    175     /**
    176      * Executes the the path related tests.
    177      *
    178      * @return true if the test passes, false if the test fails
    179      */
    180     private boolean pathTest() {
    181         mTestPathDistances = calculatePathDistance(mTestPath.getCurrentPath(), mTestPath.getPathMarkers());
    182         calculatePathDifferences();
    183         return pathAccuracyTest();
    184     }
    185 
    186     /**
    187      * Calculates the distance between the markers for the given path.
    188      *
    189      * @param pathToCalculate The path that we want to calculate the distances for
    190      * @param markers         The locations of the user generated markers in that path
    191      * @return the list of distances for that path
    192      */
    193     protected ArrayList<Float> calculatePathDistance(ArrayList<Waypoint> pathToCalculate,
    194                                                      ArrayList<Waypoint> markers) {
    195         ArrayList<Float> pathDistances = new ArrayList<>();
    196         float totalDistance, distance;
    197         int currentLocation = pathToCalculate.indexOf(markers.get(0));
    198 
    199         while (currentLocation < pathToCalculate.size() - 1) {
    200             totalDistance = 0;
    201             do {
    202                 distance = MathsUtils.distanceCalculationOnXYPlane(
    203                         pathToCalculate.get(currentLocation).getCoordinates(),
    204                         pathToCalculate.get(currentLocation + 1).getCoordinates());
    205                 totalDistance += distance;
    206                 currentLocation++;
    207             } while (!pathToCalculate.get(currentLocation).isUserGenerated());
    208             pathDistances.add(Math.abs(totalDistance));
    209             if (currentLocation == markers.size() - 1) {
    210                 break;
    211             }
    212         }
    213         return pathDistances;
    214     }
    215 
    216     /**
    217      * Calculates the difference between paths on different laps.
    218      */
    219     private void calculatePathDifferences() {
    220         float difference;
    221 
    222         if (!mReferencePathDistances.isEmpty() && !mTestPathDistances.isEmpty()) {
    223             for (int i = 0; i < mReferencePathDistances.size(); i++) {
    224                 difference = mReferencePathDistances.get(i) - mTestPathDistances.get(i);
    225                 mPathAccuracy.add(Math.abs(difference));
    226             }
    227         } else {
    228             throw new AssertionError("calculatePathDifference has one of the arrays empty", null);
    229         }
    230     }
    231 
    232     /**
    233      * Checks to see if any of the path differences have failed the test and adds them to the test
    234      * report.
    235      *
    236      * @return True if the test passes and false if there is a fail
    237      */
    238     private boolean pathAccuracyTest() {
    239         boolean testState = true;
    240         for (float path : mPathAccuracy) {
    241             if (path > mReferencePath.getFailureTolerance()) {
    242                 recordPathTestResults(path);
    243                 testState = false;
    244             }
    245         }
    246         return testState;
    247     }
    248 
    249     /**
    250      * Formats the failed paths into a string to add it to the test report.
    251      *
    252      * @param difference The distance that failed the test
    253      */
    254     private void recordPathTestResults(float difference) {
    255         int pathNumber = mPathAccuracy.indexOf(difference);
    256         String referencePath = String.valueOf(mReferencePathDistances.get(pathNumber));
    257         String testPath = String.valueOf(mTestPathDistances.get(pathNumber));
    258         String testDetails = mTestPhaseName +
    259                 " Path Length: Path length difference was too great. Path: " + pathNumber +
    260                 " Difference: " + difference +
    261                 " Paths: " + referencePath + " " + testPath + "\n";
    262         Log.e("Path Result", testDetails);
    263         mTestReport.setFailDetails(testDetails);
    264     }
    265 
    266     /**
    267      * Returns the makers in the test path.
    268      */
    269     public ArrayList<Waypoint> getTestPathMarkers() {
    270         return mTestPath.getPathMarkers();
    271     }
    272 
    273     /**
    274      * Returns the size of the current path.
    275      */
    276     public int getTestPathMarkersSize() {
    277         return mTestPath.getPathMarkers().size();
    278     }
    279 }
    280