Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2013 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.performance.tests;
     18 
     19 import com.android.ddmlib.CollectingOutputReceiver;
     20 import com.android.tradefed.device.DeviceNotAvailableException;
     21 import com.android.tradefed.device.ITestDevice;
     22 import com.android.tradefed.log.LogUtil.CLog;
     23 import com.android.tradefed.result.ITestInvocationListener;
     24 import com.android.tradefed.result.TestDescription;
     25 import com.android.tradefed.testtype.IDeviceTest;
     26 import com.android.tradefed.testtype.IRemoteTest;
     27 import com.android.tradefed.util.proto.TfMetricProtoUtil;
     28 
     29 import org.json.JSONArray;
     30 import org.json.JSONException;
     31 import org.json.JSONObject;
     32 import org.json.JSONTokener;
     33 import org.junit.Assert;
     34 
     35 import java.io.BufferedReader;
     36 import java.io.File;
     37 import java.io.FileReader;
     38 import java.io.IOException;
     39 import java.util.Collections;
     40 import java.util.HashMap;
     41 import java.util.Map;
     42 import java.util.concurrent.TimeUnit;
     43 
     44 /**
     45  * A harness that launches Geekbench and reports result.
     46  * Requires Geekbench binary and plar file in device temporary directory.
     47  */
     48 public class GeekbenchTest implements IDeviceTest, IRemoteTest {
     49 
     50     private static final String RUN_KEY = "geekbench3";
     51     private static final int MAX_ATTEMPTS = 3;
     52     private static final int TIMEOUT_MS = 10 * 60 * 1000;
     53 
     54     private static final String DEVICE_TEMPORARY_DIR_PATH = "/data/local/tmp/";
     55     private static final String GEEKBENCH_BINARY_FILENAME = "geekbench_armeabi-v7a_32";
     56     private static final String GEEKBENCH_BINARY_DEVICE_PATH =
     57             DEVICE_TEMPORARY_DIR_PATH + GEEKBENCH_BINARY_FILENAME;
     58     private static final String GEEKBENCH_PLAR_DEVICE_PATH =
     59             DEVICE_TEMPORARY_DIR_PATH + "geekbench.plar";
     60     private static final String GEEKBENCH_RESULT_DEVICE_PATH =
     61             DEVICE_TEMPORARY_DIR_PATH + "result.txt";
     62 
     63     private static final String OVERALL_SCORE_NAME = "Overall Score";
     64     private static final Map<String, String> METRICS_KEY_MAP = createMetricsKeyMap();
     65 
     66     private ITestDevice mDevice;
     67 
     68     private static Map<String, String> createMetricsKeyMap() {
     69         Map<String, String> result = new HashMap<String, String>();
     70         result.put(OVERALL_SCORE_NAME, "overall");
     71         result.put("Integer", "integer");
     72         result.put("Floating Point", "floating-point");
     73         result.put("Memory", "memory");
     74         return Collections.unmodifiableMap(result);
     75     }
     76 
     77     /**
     78      * {@inheritDoc}
     79      */
     80     @Override
     81     public void setDevice(ITestDevice device) {
     82         mDevice = device;
     83     }
     84 
     85     /**
     86      * {@inheritDoc}
     87      */
     88     @Override
     89     public ITestDevice getDevice() {
     90         return mDevice;
     91     }
     92 
     93     /**
     94      * {@inheritDoc}
     95      */
     96     @Override
     97     public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
     98         TestDescription testId = new TestDescription(getClass().getCanonicalName(), RUN_KEY);
     99         ITestDevice device = getDevice();
    100 
    101         // delete old results
    102         device.executeShellCommand(String.format("rm %s", GEEKBENCH_RESULT_DEVICE_PATH));
    103 
    104         Assert.assertTrue(String.format("Geekbench binary not found on device: %s",
    105                 GEEKBENCH_BINARY_DEVICE_PATH), device.doesFileExist(GEEKBENCH_BINARY_DEVICE_PATH));
    106         Assert.assertTrue(String.format("Geekbench binary not found on device: %s",
    107                 GEEKBENCH_PLAR_DEVICE_PATH), device.doesFileExist(GEEKBENCH_PLAR_DEVICE_PATH));
    108 
    109         listener.testRunStarted(RUN_KEY, 0);
    110         listener.testStarted(testId);
    111 
    112         long testStartTime = System.currentTimeMillis();
    113         Map<String, String> metrics = new HashMap<String, String>();
    114         String errMsg = null;
    115 
    116         // start geekbench and wait for test to complete
    117         CollectingOutputReceiver receiver = new CollectingOutputReceiver();
    118         device.executeShellCommand(String.format("%s --no-upload --export-json %s",
    119                 GEEKBENCH_BINARY_DEVICE_PATH, GEEKBENCH_RESULT_DEVICE_PATH), receiver,
    120                 TIMEOUT_MS, TimeUnit.MILLISECONDS, MAX_ATTEMPTS);
    121         CLog.v(receiver.getOutput());
    122 
    123         // pull result from device
    124         File benchmarkReport = device.pullFile(GEEKBENCH_RESULT_DEVICE_PATH);
    125         if (benchmarkReport != null) {
    126             // parse result
    127             CLog.i("== Geekbench 3 result ==");
    128             Map<String, String> benchmarkResult = parseResultJSON(benchmarkReport);
    129             if (benchmarkResult == null) {
    130                 errMsg = "Failed to parse Geekbench result JSON.";
    131             } else {
    132                 metrics = benchmarkResult;
    133             }
    134 
    135             // delete results from device and host
    136             benchmarkReport.delete();
    137             device.executeShellCommand("rm " + GEEKBENCH_RESULT_DEVICE_PATH);
    138         } else {
    139             errMsg = "Geekbench report not found.";
    140         }
    141 
    142         if (errMsg != null) {
    143             CLog.e(errMsg);
    144             listener.testFailed(testId, errMsg);
    145             listener.testEnded(testId, TfMetricProtoUtil.upgradeConvert(metrics));
    146             listener.testRunFailed(errMsg);
    147         } else {
    148             long durationMs = System.currentTimeMillis() - testStartTime;
    149             listener.testEnded(testId, TfMetricProtoUtil.upgradeConvert(metrics));
    150             listener.testRunEnded(durationMs, TfMetricProtoUtil.upgradeConvert(metrics));
    151         }
    152     }
    153 
    154     private Map<String, String> parseResultJSON(File resultJson) {
    155         Map<String, String> benchmarkResult = new HashMap<String, String>();
    156         try {
    157             BufferedReader bufferedReader = new BufferedReader(new FileReader(resultJson));
    158             String line = bufferedReader.readLine();
    159             bufferedReader.close();
    160             if (line != null) {
    161                 JSONTokener tokener = new JSONTokener(line);
    162                 JSONObject root = new JSONObject(tokener);
    163                 String overallScore = root.getString("score");
    164                 benchmarkResult.put(METRICS_KEY_MAP.get(OVERALL_SCORE_NAME), overallScore);
    165                 CLog.i(String.format("Overall: %s", overallScore));
    166                 String overallScoreMulticore = root.getString("multicore_score");
    167                 benchmarkResult.put(METRICS_KEY_MAP.get(OVERALL_SCORE_NAME) + "-multi",
    168                         overallScoreMulticore);
    169                 CLog.i(String.format("Overall-multicore: %s", overallScore));
    170                 JSONArray arr = root.getJSONArray("sections");
    171                 for (int i = 0; i < arr.length(); i++) {
    172                     JSONObject section = arr.getJSONObject(i);
    173                     String sectionName = section.getString("name");
    174                     String sectionScore = section.getString("score");
    175                     String sectionScoreMulticore = section.getString("multicore_score");
    176                     if (METRICS_KEY_MAP.containsKey(sectionName)) {
    177                         CLog.i(String.format("%s: %s", sectionName, sectionScore));
    178                         CLog.i(String.format("%s-multicore: %s", sectionName,
    179                                 sectionScoreMulticore));
    180                         benchmarkResult.put(METRICS_KEY_MAP.get(sectionName), sectionScore);
    181                         CLog.i(String.format("%s-multicore: %s", sectionName,
    182                                 sectionScoreMulticore));
    183                         benchmarkResult.put(METRICS_KEY_MAP.get(sectionName) + "-multi",
    184                                 sectionScoreMulticore);
    185                     }
    186                 }
    187             }
    188         } catch (IOException e) {
    189             CLog.e("Geekbench3 result file not found.");
    190             return null;
    191         } catch (JSONException e) {
    192             CLog.e("Error parsing Geekbench3 JSON result.");
    193             return null;
    194         }
    195         return benchmarkResult;
    196     }
    197 }
    198