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             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      */
reformatRepeatedStreams(File resultDir)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      */
readFile(File file)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      */
writeFile(File file, String jsonString)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      */
reformatJsonString(String jsonString)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