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 
CollectorUtil()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      */
pullFromDevice(ITestDevice device, String src, String dest)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      */
pullFromHost(File src, File dest)80     public static void pullFromHost(File src, File dest) {
81         try {
82             FileUtil.recursiveCopy(src, dest);
83             FileUtil.recursiveDelete(src);
84         } catch (IOException e) {
85             CLog.e("Caught exception during pull.");
86             CLog.e(e);
87         }
88     }
89 
90     /**
91      * Reformat test metrics jsons to convert multiple json objects with identical stream names into
92      * arrays of objects (b/28790467).
93      *
94      * @param resultDir The directory containing test metrics.
95      */
reformatRepeatedStreams(File resultDir)96     public static void reformatRepeatedStreams(File resultDir) {
97         try {
98             File[] reportLogs = resultDir.listFiles();
99             for (File reportLog : reportLogs) {
100                 writeFile(reportLog, reformatJsonString(readFile(reportLog)));
101             }
102         } catch (IOException e) {
103             CLog.e("Caught exception during reformatting.");
104             CLog.e(e);
105         }
106     }
107 
108     /**
109      * Helper function to read a file.
110      *
111      * @throws IOException
112      */
readFile(File file)113     private static String readFile(File file) throws IOException {
114         StringBuilder stringBuilder = new StringBuilder();
115         try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
116             String line;
117             while ((line = reader.readLine()) != null) {
118                 stringBuilder.append(line);
119             }
120         }
121         return stringBuilder.toString();
122     }
123 
124     /**
125      * Helper function to write to a file.
126      *
127      * @param file {@link File} to write to.
128      * @param jsonString String to be written.
129      * @throws IOException
130      */
writeFile(File file, String jsonString)131     private static void writeFile(File file, String jsonString) throws IOException {
132         file.createNewFile();
133         try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
134             writer.write(jsonString, 0, jsonString.length());
135         }
136     }
137 
138     /**
139      * Helper function to reformat JSON string.
140      *
141      * @param jsonString
142      * @return the reformatted JSON string.
143      */
reformatJsonString(String jsonString)144     public static String reformatJsonString(String jsonString) {
145         StringBuilder newJsonBuilder = new StringBuilder();
146         // Create map of stream names and json objects.
147         HashMap<String, List<String>> jsonMap = new HashMap<>();
148         Pattern p = Pattern.compile(TEST_METRICS_PATTERN);
149         Matcher m = p.matcher(jsonString);
150         while (m.find()) {
151             String key = m.group(1);
152             String value = m.group(2);
153             if (!jsonMap.containsKey(key)) {
154                 jsonMap.put(key, new ArrayList<String>());
155             }
156             jsonMap.get(key).add(value);
157         }
158         // Rewrite json string as arrays.
159         newJsonBuilder.append("{");
160         boolean firstLine = true;
161         for (String key : jsonMap.keySet()) {
162             if (!firstLine) {
163                 newJsonBuilder.append(",");
164             } else {
165                 firstLine = false;
166             }
167             newJsonBuilder.append("\"").append(key).append("\":[");
168             boolean firstValue = true;
169             for (String stream : jsonMap.get(key)) {
170                 if (!firstValue) {
171                     newJsonBuilder.append(",");
172                 } else {
173                     firstValue = false;
174                 }
175                 newJsonBuilder.append(stream);
176             }
177             newJsonBuilder.append("]");
178         }
179         newJsonBuilder.append("}");
180         return newJsonBuilder.toString();
181     }
182 }
183