Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2011 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.media.tests;
     18 
     19 import com.android.ddmlib.IDevice;
     20 import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
     21 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
     22 import com.android.tradefed.device.DeviceNotAvailableException;
     23 import com.android.tradefed.device.ITestDevice;
     24 import com.android.tradefed.log.LogUtil.CLog;
     25 import com.android.tradefed.result.FileInputStreamSource;
     26 import com.android.tradefed.result.ITestInvocationListener;
     27 import com.android.tradefed.result.InputStreamSource;
     28 import com.android.tradefed.result.LogDataType;
     29 import com.android.tradefed.testtype.IDeviceTest;
     30 import com.android.tradefed.testtype.IRemoteTest;
     31 import com.android.tradefed.util.FileUtil;
     32 import com.android.tradefed.util.StreamUtil;
     33 
     34 import org.junit.Assert;
     35 
     36 import java.io.File;
     37 import java.io.FileInputStream;
     38 import java.io.IOException;
     39 import java.io.InputStream;
     40 import java.util.Arrays;
     41 import java.util.HashMap;
     42 import java.util.List;
     43 import java.util.ListIterator;
     44 import java.util.Map;
     45 import java.util.concurrent.TimeUnit;
     46 import java.util.regex.Matcher;
     47 import java.util.regex.Pattern;
     48 
     49 /**
     50  * Runs the Media stress testcases.
     51  * FIXME: more details
     52  * <p/>
     53  * Note that this test will not run properly unless /sdcard is mounted and writable.
     54  */
     55 public class MediaStressTest implements IDeviceTest, IRemoteTest {
     56 
     57     ITestDevice mTestDevice = null;
     58     private static final String METRICS_RUN_NAME = "VideoRecordingStress";
     59 
     60     //Max test timeout - 2 hrs
     61     private static final int MAX_TEST_TIMEOUT = 2 * 60 * 60 * 1000;
     62 
     63     // Constants for running the tests
     64     private static final String TEST_CLASS_NAME =
     65             "com.android.mediaframeworktest.stress.MediaRecorderStressTest";
     66     private static final String TEST_PACKAGE_NAME = "com.android.mediaframeworktest";
     67     private static final String TEST_RUNNER_NAME = ".MediaRecorderStressTestRunner";
     68 
     69     // Constants for parsing the output file
     70     private static final Pattern EXPECTED_LOOP_COUNT_PATTERN =
     71             Pattern.compile("Total number of loops:\\s*(\\d+)");
     72     private static final Pattern ACTUAL_LOOP_COUNT_PATTERN =
     73             Pattern.compile("No of loop:.*,\\s*(\\d+)\\s*");
     74     private static final String OUTPUT_PATH = "mediaStressOutput.txt";
     75 
     76     @Override
     77     public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
     78         Assert.assertNotNull(mTestDevice);
     79 
     80         IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(TEST_PACKAGE_NAME,
     81                 TEST_RUNNER_NAME, mTestDevice.getIDevice());
     82         runner.setClassName(TEST_CLASS_NAME);
     83         runner.setMaxTimeToOutputResponse(MAX_TEST_TIMEOUT, TimeUnit.MILLISECONDS);
     84 
     85         cleanTmpFiles();
     86         mTestDevice.runInstrumentationTests(runner, listener);
     87         logOutputFile(listener);
     88         cleanTmpFiles();
     89     }
     90 
     91     /**
     92      * Clean up temp files from test runs
     93      */
     94     private void cleanTmpFiles() throws DeviceNotAvailableException {
     95         String extStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
     96         mTestDevice.executeShellCommand(String.format("rm %s/temp*.3gp", extStore));
     97         mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore, OUTPUT_PATH));
     98     }
     99 
    100     /**
    101      * Pull the output file from the device, add it to the logs, and also parse out the relevant
    102      * test metrics and report them.
    103      */
    104     private void logOutputFile(ITestInvocationListener listener)
    105             throws DeviceNotAvailableException {
    106         File outputFile = null;
    107         InputStreamSource outputSource = null;
    108         try {
    109             outputFile = mTestDevice.pullFileFromExternal(OUTPUT_PATH);
    110 
    111             if (outputFile == null) {
    112                 return;
    113             }
    114 
    115             CLog.d("Sending %d byte file %s into the logosphere!", outputFile.length(), outputFile);
    116             outputSource = new FileInputStreamSource(outputFile);
    117             listener.testLog(OUTPUT_PATH, LogDataType.TEXT, outputSource);
    118             parseOutputFile(outputFile, listener);
    119         } finally {
    120             FileUtil.deleteFile(outputFile);
    121             StreamUtil.cancel(outputSource);
    122         }
    123     }
    124 
    125     /**
    126      * Parse the relevant metrics from the Instrumentation test output file
    127      */
    128     private void parseOutputFile(File outputFile, ITestInvocationListener listener) {
    129         Map<String, String> runMetrics = new HashMap<>();
    130         Map<String, String> stanzaKeyMap = new HashMap<>();
    131         stanzaKeyMap.put("testStressRecordVideoAndPlayback1080P", "VideoRecordPlayback1080P");
    132         stanzaKeyMap.put("testStressRecordVideoAndPlayback720P", "VideoRecordPlayback720P");
    133         stanzaKeyMap.put("testStressRecordVideoAndPlayback480P", "VideoRecordPlayback480P");
    134         stanzaKeyMap.put("testStressTimeLapse", "TimeLapseRecord");
    135 
    136         // try to parse it
    137         String contents;
    138         try {
    139             InputStream dataStream = new FileInputStream(outputFile);
    140             contents = StreamUtil.getStringFromStream(dataStream);
    141         } catch (IOException e) {
    142             CLog.e("IOException while parsing the output file:");
    143             CLog.e(e);
    144             return;
    145         }
    146 
    147         List<String> lines = Arrays.asList(contents.split("\n"));
    148         ListIterator<String> lineIter = lines.listIterator();
    149         String line;
    150         while (lineIter.hasNext()) {
    151             line = lineIter.next();
    152             String key = null;
    153 
    154             if (stanzaKeyMap.containsKey(line)) {
    155                 key = stanzaKeyMap.get(line);
    156             } else {
    157                 CLog.d("Got unexpected line: %s", line);
    158                 continue;
    159             }
    160 
    161             Integer countExpected = getIntFromOutput(lineIter, EXPECTED_LOOP_COUNT_PATTERN);
    162             Integer countActual = getIntFromOutput(lineIter, ACTUAL_LOOP_COUNT_PATTERN);
    163             int value = coalesceLoopCounts(countActual, countExpected);
    164             runMetrics.put(key, Integer.toString(value));
    165         }
    166 
    167         reportMetrics(listener, runMetrics);
    168     }
    169 
    170     /**
    171      * Report run metrics by creating an empty test run to stick them in
    172      * <p />
    173      * Exposed for unit testing
    174      */
    175     void reportMetrics(ITestInvocationListener listener, Map<String, String> metrics) {
    176         // Create an empty testRun to report the parsed runMetrics
    177         CLog.d("About to report metrics: %s", metrics);
    178         listener.testRunStarted(METRICS_RUN_NAME, 0);
    179         listener.testRunEnded(0, metrics);
    180     }
    181 
    182     /**
    183      * Use the provided {@link Pattern} to parse a number out of the output file
    184      */
    185     private Integer getIntFromOutput(ListIterator<String> lineIter, Pattern numPattern) {
    186         Integer retval = null;
    187         String line = null;
    188         if (lineIter.hasNext()) {
    189             line = lineIter.next();
    190             Matcher m = numPattern.matcher(line);
    191             if (m.matches()) {
    192                 retval = Integer.parseInt(m.group(1));
    193             } else {
    194                 CLog.e("Couldn't match pattern %s against line '%s'", numPattern, line);
    195             }
    196         } else {
    197             CLog.e("Encounted EOF while trying to match pattern %s", numPattern);
    198         }
    199 
    200         return retval;
    201     }
    202 
    203     /**
    204      * Given an actual and an expected iteration count, determine a single metric to report.
    205      */
    206     private int coalesceLoopCounts(Integer actual, Integer expected) {
    207         if (expected == null || expected <= 0) {
    208             return -1;
    209         } else if (actual == null) {
    210             return expected;
    211         } else {
    212             return actual;
    213         }
    214     }
    215 
    216     @Override
    217     public void setDevice(ITestDevice device) {
    218         mTestDevice = device;
    219     }
    220 
    221     @Override
    222     public ITestDevice getDevice() {
    223         return mTestDevice;
    224     }
    225 }
    226