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.Log;
     21 import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
     22 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
     23 import com.android.tradefed.device.DeviceNotAvailableException;
     24 import com.android.tradefed.device.ITestDevice;
     25 import com.android.tradefed.result.BugreportCollector;
     26 import com.android.tradefed.result.BugreportCollector.Freq;
     27 import com.android.tradefed.result.BugreportCollector.Noun;
     28 import com.android.tradefed.result.BugreportCollector.Relation;
     29 import com.android.tradefed.result.FileInputStreamSource;
     30 import com.android.tradefed.result.ITestInvocationListener;
     31 import com.android.tradefed.result.InputStreamSource;
     32 import com.android.tradefed.result.LogDataType;
     33 import com.android.tradefed.testtype.IDeviceTest;
     34 import com.android.tradefed.testtype.IRemoteTest;
     35 import com.android.tradefed.util.FileUtil;
     36 import com.android.tradefed.util.RegexTrie;
     37 import com.android.tradefed.util.StreamUtil;
     38 
     39 import org.junit.Assert;
     40 
     41 import java.io.File;
     42 import java.io.FileInputStream;
     43 import java.io.IOException;
     44 import java.io.InputStream;
     45 import java.util.ArrayList;
     46 import java.util.Arrays;
     47 import java.util.HashMap;
     48 import java.util.List;
     49 import java.util.ListIterator;
     50 import java.util.Map;
     51 import java.util.concurrent.TimeUnit;
     52 
     53 /**
     54  * Runs the Video Editing Framework Performance Test.The performance test result
     55  * is saved in /sdcard/VideoEditorPerformance.txt
     56  * <p/>
     57  * Note that this test will not run properly unless /sdcard is mounted and
     58  * writable.
     59  */
     60 public class VideoEditingPerformanceTest implements IDeviceTest, IRemoteTest {
     61     private static final String LOG_TAG = "VideoEditingPerformanceTest";
     62 
     63     ITestDevice mTestDevice = null;
     64 
     65     private static final String METRICS_RUN_NAME = "VideoEditor";
     66 
     67     //Max test timeout - 3 hrs
     68     private static final int MAX_TEST_TIMEOUT = 3 * 60 * 60 * 1000;
     69 
     70     // Constants for running the tests
     71     private static final String TEST_CLASS_NAME =
     72         "com.android.mediaframeworktest.performance.VideoEditorPerformance";
     73     private static final String TEST_PACKAGE_NAME = "com.android.mediaframeworktest";
     74     private static final String TEST_RUNNER_NAME = ".MediaFrameworkPerfTestRunner";
     75 
     76     private static final String OUTPUT_PATH = "VideoEditorPerformance.txt";
     77 
     78     private final RegexTrie<String> mPatternMap = new RegexTrie<>();
     79 
     80     public VideoEditingPerformanceTest() {
     81         mPatternMap.put("ImageItemCreate",
     82                 "^.*Time taken to Create  Media Image Item :(\\d+)");
     83         mPatternMap.put("mageItemAdd",
     84                 "^.*Time taken to add  Media Image Item :(\\d+)");
     85         mPatternMap.put("ImageItemRemove",
     86                 "^.*Time taken to remove  Media Image Item :(\\d+)");
     87         mPatternMap.put("ImageItemCreate640x480",
     88                 "^.*Time taken to Create  Media Image Item.*640x480.*:(\\d+)");
     89         mPatternMap.put("ImageItemAdd640x480",
     90                 "^.*Time taken to add  Media Image Item.*640x480.*:(\\d+)");
     91         mPatternMap.put("ImageItemRemove640x480",
     92                 "^.*Time taken to remove  Media Image Item.*640x480.*:(\\d+)");
     93         mPatternMap.put("CrossFadeTransitionCreate",
     94                 "^.*Time taken to Create CrossFade Transition :(\\d+)");
     95         mPatternMap.put("CrossFadeTransitionAdd",
     96                 "^.*Time taken to add CrossFade Transition :(\\d+)");
     97         mPatternMap.put("CrossFadeTransitionRemove",
     98                 "^.*Time taken to remove CrossFade Transition :(\\d+)");
     99         mPatternMap.put("VideoItemCreate",
    100                 "^.*Time taken to Create Media Video Item :(\\d+)");
    101         mPatternMap.put("VideoItemAdd",
    102                 "^.*Time taken to Add  Media Video Item :(\\d+)");
    103         mPatternMap.put("VideoItemRemove",
    104                 "^.*Time taken to remove  Media Video Item :(\\d+)");
    105         mPatternMap.put("EffectOverlappingTransition",
    106                 "^.*Time taken to testPerformanceEffectOverlappingTransition :(\\d+.\\d+)");
    107         mPatternMap.put("ExportStoryboard",
    108                 "^.*Time taken to do ONE export of storyboard duration 69000 is :(\\d+)");
    109         mPatternMap.put("PreviewWithTransition",
    110                 "^.*Time taken to Generate Preview with transition :(\\d+.\\d+)");
    111         mPatternMap.put("OverlayCreate",
    112                 "^.*Time taken to add & create Overlay :(\\d+)");
    113         mPatternMap.put("OverlayRemove",
    114                 "^.*Time taken to remove  Overlay :(\\d+)");
    115         mPatternMap.put("GetVideoThumbnails",
    116                 "^.*Duration taken to get Video Thumbnails :(\\d+)");
    117         mPatternMap.put("TransitionWithEffectOverlapping",
    118                 "^.*Time taken to TransitionWithEffectOverlapping :(\\d+.\\d+)");
    119         mPatternMap.put("MediaPropertiesGet",
    120                 "^.*Time taken to get Media Properties :(\\d+)");
    121         mPatternMap.put("AACLCAdd",
    122                 "^.*Time taken for 1st Audio Track.*AACLC.*:(\\d+)");
    123         mPatternMap.put("AMRNBAdd",
    124                 "^.*Time taken for 2nd Audio Track.*AMRNB.*:(\\d+)");
    125         mPatternMap.put("KenBurnGeneration",
    126                 "^.*Time taken to Generate KenBurn Effect :(\\d+.\\d+)");
    127         mPatternMap.put("ThumbnailsGeneration",
    128                 "^.*Time taken Thumbnail generation :(\\d+.\\d+)");
    129         mPatternMap.put("H264ThumbnailGeneration",
    130                 "^.*Time taken for Thumbnail generation :(\\d+.\\d+)");
    131     }
    132 
    133     @Override
    134     public void run(ITestInvocationListener listener)
    135             throws DeviceNotAvailableException {
    136         Assert.assertNotNull(mTestDevice);
    137 
    138         IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(
    139                 TEST_PACKAGE_NAME, TEST_RUNNER_NAME, mTestDevice.getIDevice());
    140         runner.setClassName(TEST_CLASS_NAME);
    141         runner.setMaxTimeToOutputResponse(MAX_TEST_TIMEOUT, TimeUnit.MILLISECONDS);
    142 
    143         BugreportCollector bugListener = new BugreportCollector(listener,
    144                 mTestDevice);
    145         bugListener.addPredicate(new BugreportCollector.Predicate(
    146                 Relation.AFTER, Freq.EACH, Noun.TESTRUN));
    147 
    148         mTestDevice.runInstrumentationTests(runner, bugListener);
    149 
    150         logOutputFiles(listener);
    151         cleanResultFile();
    152     }
    153 
    154     /**
    155      * Clean up the test result file from test run
    156      */
    157     private void cleanResultFile() throws DeviceNotAvailableException {
    158         String extStore =
    159             mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
    160         mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore, OUTPUT_PATH));
    161     }
    162 
    163     /**
    164      * Pull the output files from the device, add it to the logs, and also parse
    165      * out the relevant test metrics and report them.
    166      */
    167     private void logOutputFiles(ITestInvocationListener listener)
    168             throws DeviceNotAvailableException {
    169         File outputFile = null;
    170         InputStreamSource outputSource = null;
    171         try {
    172             outputFile = mTestDevice.pullFileFromExternal(OUTPUT_PATH);
    173 
    174             if (outputFile == null) {
    175                 return;
    176             }
    177 
    178             // Upload a verbatim copy of the output file
    179             Log.d(LOG_TAG, String.format(
    180                     "Sending %d byte file %s into the logosphere!",
    181                     outputFile.length(), outputFile));
    182             outputSource = new FileInputStreamSource(outputFile);
    183             listener.testLog(OUTPUT_PATH, LogDataType.TEXT, outputSource);
    184 
    185             // Parse the output file to upload aggregated metrics
    186             parseOutputFile(new FileInputStream(outputFile), listener);
    187         } catch (IOException e) {
    188             Log.e(LOG_TAG, String.format(
    189                     "IOException while reading or parsing output file: %s", e));
    190         } finally {
    191             FileUtil.deleteFile(outputFile);
    192             StreamUtil.cancel(outputSource);
    193         }
    194     }
    195 
    196     /**
    197      * Parse the relevant metrics from the Instrumentation test output file
    198      */
    199     private void parseOutputFile(InputStream dataStream,
    200             ITestInvocationListener listener) {
    201 
    202         Map<String, String> runMetrics = new HashMap<>();
    203 
    204         // try to parse it
    205         String contents;
    206         try {
    207             contents = StreamUtil.getStringFromStream(dataStream);
    208         } catch (IOException e) {
    209             Log.e(LOG_TAG, String.format(
    210                     "Got IOException during test processing: %s", e));
    211             return;
    212         }
    213 
    214         List<String> lines = Arrays.asList(contents.split("\n"));
    215         ListIterator<String> lineIter = lines.listIterator();
    216         String line;
    217         while (lineIter.hasNext()) {
    218             line = lineIter.next();
    219             List<List<String>> capture = new ArrayList<>(1);
    220             String key = mPatternMap.retrieve(capture, line);
    221             if (key != null) {
    222                 Log.d(LOG_TAG, String.format("Got '%s' and captures '%s'", key,
    223                         capture.toString()));
    224             } else if (line.isEmpty()) {
    225                 // ignore
    226                 continue;
    227             } else {
    228                 Log.e(LOG_TAG, String.format("Got unmatched line: %s", line));
    229                 continue;
    230             }
    231             runMetrics.put(key, capture.get(0).get(0));
    232         }
    233         reportMetrics(listener, runMetrics);
    234     }
    235 
    236     /**
    237      * Report run metrics by creating an empty test run to stick them in
    238      * <p />
    239      * Exposed for unit testing
    240      */
    241     void reportMetrics(ITestInvocationListener listener,
    242             Map<String, String> metrics) {
    243         Log.d(LOG_TAG, String.format("About to report metrics: %s", metrics));
    244         listener.testRunStarted(METRICS_RUN_NAME, 0);
    245         listener.testRunEnded(0, metrics);
    246     }
    247 
    248     @Override
    249     public void setDevice(ITestDevice device) {
    250         mTestDevice = device;
    251     }
    252 
    253     @Override
    254     public ITestDevice getDevice() {
    255         return mTestDevice;
    256     }
    257 }
    258