Home | History | Annotate | Download | only in util
      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.compatibility.common.tradefed.util;
     18 
     19 import com.android.compatibility.common.tradefed.targetprep.DeviceInfoCollector;
     20 import com.android.compatibility.common.tradefed.targetprep.ReportLogCollector;
     21 import com.android.tradefed.device.DeviceNotAvailableException;
     22 import com.android.tradefed.device.ITestDevice;
     23 import com.android.tradefed.log.LogUtil.CLog;
     24 import com.android.tradefed.util.FileUtil;
     25 
     26 import java.io.BufferedReader;
     27 import java.io.BufferedWriter;
     28 import java.io.File;
     29 import java.io.FileReader;
     30 import java.io.FileWriter;
     31 import java.io.IOException;
     32 import java.util.ArrayList;
     33 import java.util.HashMap;
     34 import java.util.List;
     35 import java.util.regex.Matcher;
     36 import java.util.regex.Pattern;
     37 
     38 /**
     39  * Utility class for {@link ReportLogCollector} and {@link DeviceInfoCollector}.
     40  */
     41 public class CollectorUtil {
     42 
     43     private CollectorUtil() {
     44     }
     45 
     46     private static final String ADB_LS_PATTERN = "([^\\s]+)\\s*";
     47     private static final String TEST_METRICS_PATTERN = "\\\"([a-z0-9_]*)\\\":(\\{[^{}]*\\})";
     48 
     49     /**
     50      * Copy files from device to host.
     51      * @param device The device reference.
     52      * @param src The source directory on the device.
     53      * @param dest The destination directory.
     54      */
     55     public static void pullFromDevice(ITestDevice device, String src, String dest) {
     56         try {
     57             if (device.doesFileExist(src)) {
     58                 String listCommand = String.format("ls %s", src);
     59                 String fileList = device.executeShellCommand(listCommand);
     60                 Pattern p = Pattern.compile(ADB_LS_PATTERN);
     61                 Matcher m = p.matcher(fileList);
     62                 while (m.find()) {
     63                     String fileName = m.group(1);
     64                     String srcPath = String.format("%s%s", src, fileName);
     65                     File destFile = new File(String.format("%s/%s", dest, fileName));
     66                     device.pullFile(srcPath, destFile);
     67                 }
     68             }
     69         } catch (DeviceNotAvailableException e) {
     70             CLog.e("Caught exception during pull.");
     71             CLog.e(e);
     72         }
     73     }
     74 
     75     /**
     76      * Copy files from host and delete from source.
     77      * @param src The source directory.
     78      * @param dest The destination directory.
     79      */
     80     public static void pullFromHost(File src, File dest) {
     81         try {
     82             if (src.listFiles() != null) {
     83                 FileUtil.recursiveCopy(src, dest);
     84             }
     85             FileUtil.recursiveDelete(src);
     86         } catch (IOException e) {
     87             CLog.e("Caught exception during pull.");
     88             CLog.e(e);
     89         }
     90     }
     91 
     92     /**
     93      * Reformat test metrics jsons to convert multiple json objects with identical stream names into
     94      * arrays of objects (b/28790467).
     95      *
     96      * @param resultDir The directory containing test metrics.
     97      */
     98     public static void reformatRepeatedStreams(File resultDir) {
     99         try {
    100             File[] reportLogs = resultDir.listFiles();
    101             for (File reportLog : reportLogs) {
    102                 writeFile(reportLog, reformatJsonString(readFile(reportLog)));
    103             }
    104         } catch (IOException e) {
    105             CLog.e("Caught exception during reformatting.");
    106             CLog.e(e);
    107         }
    108     }
    109 
    110     /**
    111      * Helper function to read a file.
    112      *
    113      * @throws IOException
    114      */
    115     private static String readFile(File file) throws IOException {
    116         StringBuilder stringBuilder = new StringBuilder();
    117         try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
    118             String line;
    119             while ((line = reader.readLine()) != null) {
    120                 stringBuilder.append(line);
    121             }
    122         }
    123         return stringBuilder.toString();
    124     }
    125 
    126     /**
    127      * Helper function to write to a file.
    128      *
    129      * @param file {@link File} to write to.
    130      * @param jsonString String to be written.
    131      * @throws IOException
    132      */
    133     private static void writeFile(File file, String jsonString) throws IOException {
    134         file.createNewFile();
    135         try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
    136             writer.write(jsonString, 0, jsonString.length());
    137         }
    138     }
    139 
    140     /**
    141      * Helper function to reformat JSON string.
    142      *
    143      * @param jsonString
    144      * @return the reformatted JSON string.
    145      */
    146     public static String reformatJsonString(String jsonString) {
    147         StringBuilder newJsonBuilder = new StringBuilder();
    148         // Create map of stream names and json objects.
    149         HashMap<String, List<String>> jsonMap = new HashMap<>();
    150         Pattern p = Pattern.compile(TEST_METRICS_PATTERN);
    151         Matcher m = p.matcher(jsonString);
    152         if (!m.find()) {
    153             return jsonString;
    154         }
    155         do {
    156             String key = m.group(1);
    157             String value = m.group(2);
    158             if (!jsonMap.containsKey(key)) {
    159                 jsonMap.put(key, new ArrayList<String>());
    160             }
    161             jsonMap.get(key).add(value);
    162         } while (m.find());
    163         // Rewrite json string as arrays.
    164         newJsonBuilder.append("{");
    165         boolean firstLine = true;
    166         for (String key : jsonMap.keySet()) {
    167             if (!firstLine) {
    168                 newJsonBuilder.append(",");
    169             } else {
    170                 firstLine = false;
    171             }
    172             newJsonBuilder.append("\"").append(key).append("\":[");
    173             boolean firstValue = true;
    174             for (String stream : jsonMap.get(key)) {
    175                 if (!firstValue) {
    176                     newJsonBuilder.append(",");
    177                 } else {
    178                     firstValue = false;
    179                 }
    180                 newJsonBuilder.append(stream);
    181             }
    182             newJsonBuilder.append("]");
    183         }
    184         newJsonBuilder.append("}");
    185         return newJsonBuilder.toString();
    186     }
    187 }
    188