OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library utils; | 5 library utils; |
6 | 6 |
7 import 'dart:io'; | 7 import 'dart:io'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 | 9 |
10 import 'path.dart'; | 10 import 'path.dart'; |
11 | 11 |
12 // This is the maximum time we expect stdout/stderr of subprocesses to deliver | 12 // This is the maximum time we expect stdout/stderr of subprocesses to deliver |
13 // data after we've got the exitCode. | 13 // data after we've got the exitCode. |
14 const Duration MAX_STDIO_DELAY = const Duration(seconds: 30); | 14 const Duration MAX_STDIO_DELAY = const Duration(seconds: 30); |
15 | 15 |
16 String MAX_STDIO_DELAY_PASSED_MESSAGE = | 16 String MAX_STDIO_DELAY_PASSED_MESSAGE = |
17 """Not waiting for stdout/stderr from subprocess anymore | 17 """Not waiting for stdout/stderr from subprocess anymore |
18 ($MAX_STDIO_DELAY passed). Please note that this could be an indicator | 18 ($MAX_STDIO_DELAY passed). Please note that this could be an indicator |
19 that there is a hanging process which we were unable to kill."""; | 19 that there is a hanging process which we were unable to kill."""; |
20 | 20 |
21 class DebugLogger { | 21 class DebugLogger { |
22 static IOSink _sink; | 22 static IOSink _sink; |
23 | 23 |
24 /** | 24 /** |
25 * If [path] was null, the DebugLogger will write messages to stdout. | 25 * If [path] was null, the DebugLogger will write messages to stdout. |
26 */ | 26 */ |
27 static init(Path path, {append: false}) { | 27 static init(Path path, {append: false}) { |
(...skipping 11 matching lines...) Expand all Loading... |
39 } | 39 } |
40 | 40 |
41 static String _formatErrorMessage(String msg, error) { | 41 static String _formatErrorMessage(String msg, error) { |
42 if (error == null) return msg; | 42 if (error == null) return msg; |
43 msg += ": $error"; | 43 msg += ": $error"; |
44 // TODO(floitsch): once the dart-executable that is bundled | 44 // TODO(floitsch): once the dart-executable that is bundled |
45 // with the Dart sources is updated, pass a trace parameter too and do: | 45 // with the Dart sources is updated, pass a trace parameter too and do: |
46 // if (trace != null) msg += "\nStackTrace: $trace"; | 46 // if (trace != null) msg += "\nStackTrace: $trace"; |
47 return msg; | 47 return msg; |
48 } | 48 } |
| 49 |
49 static void info(String msg, [error]) { | 50 static void info(String msg, [error]) { |
50 msg = _formatErrorMessage(msg, error); | 51 msg = _formatErrorMessage(msg, error); |
51 _print("$_datetime Info: $msg"); | 52 _print("$_datetime Info: $msg"); |
52 } | 53 } |
53 | 54 |
54 static void warning(String msg, [error]) { | 55 static void warning(String msg, [error]) { |
55 msg = _formatErrorMessage(msg, error); | 56 msg = _formatErrorMessage(msg, error); |
56 _print("$_datetime Warning: $msg"); | 57 _print("$_datetime Warning: $msg"); |
57 } | 58 } |
58 | 59 |
(...skipping 22 matching lines...) Expand all Loading... |
81 } | 82 } |
82 | 83 |
83 addString(String s, {bool indentation: true, bool newLine: true}) { | 84 addString(String s, {bool indentation: true, bool newLine: true}) { |
84 if (indentation) { | 85 if (indentation) { |
85 buffer.write(indentationString()); | 86 buffer.write(indentationString()); |
86 } | 87 } |
87 buffer.write(s.replaceAll("\n", "\n${indentationString()}")); | 88 buffer.write(s.replaceAll("\n", "\n${indentationString()}")); |
88 if (newLine) buffer.write("\n"); | 89 if (newLine) buffer.write("\n"); |
89 } | 90 } |
90 | 91 |
91 prettifyJsonInternal( | 92 prettifyJsonInternal(Object obj, |
92 Object obj, {bool indentation: true, bool newLine: true}) { | 93 {bool indentation: true, bool newLine: true}) { |
93 if (obj is List) { | 94 if (obj is List) { |
94 addString("[", indentation: indentation); | 95 addString("[", indentation: indentation); |
95 currentIndentation += shiftWidth; | 96 currentIndentation += shiftWidth; |
96 for (var item in obj) { | 97 for (var item in obj) { |
97 | |
98 prettifyJsonInternal(item, indentation: indentation, newLine: false); | 98 prettifyJsonInternal(item, indentation: indentation, newLine: false); |
99 addString(",", indentation: false); | 99 addString(",", indentation: false); |
100 } | 100 } |
101 currentIndentation -= shiftWidth; | 101 currentIndentation -= shiftWidth; |
102 addString("]", indentation: indentation); | 102 addString("]", indentation: indentation); |
103 } else if (obj is Map) { | 103 } else if (obj is Map) { |
104 addString("{", indentation: indentation); | 104 addString("{", indentation: indentation); |
105 currentIndentation += shiftWidth; | 105 currentIndentation += shiftWidth; |
106 for (var key in obj.keys) { | 106 for (var key in obj.keys) { |
107 addString("$key: ", indentation: indentation, newLine: false); | 107 addString("$key: ", indentation: indentation, newLine: false); |
108 currentIndentation += shiftWidth; | 108 currentIndentation += shiftWidth; |
109 prettifyJsonInternal(obj[key], indentation: false); | 109 prettifyJsonInternal(obj[key], indentation: false); |
110 currentIndentation -= shiftWidth; | 110 currentIndentation -= shiftWidth; |
111 } | 111 } |
112 currentIndentation -= shiftWidth; | 112 currentIndentation -= shiftWidth; |
113 addString("}", indentation: indentation, newLine: newLine); | 113 addString("}", indentation: indentation, newLine: newLine); |
114 } else { | 114 } else { |
115 addString("$obj", indentation: indentation, newLine: newLine); | 115 addString("$obj", indentation: indentation, newLine: newLine); |
116 } | 116 } |
117 } | 117 } |
118 prettifyJsonInternal(json); | 118 prettifyJsonInternal(json); |
119 return buffer.toString(); | 119 return buffer.toString(); |
120 } | 120 } |
121 | 121 |
122 | |
123 /** | 122 /** |
124 * [areByteArraysEqual] compares a range of bytes from [buffer1] with a | 123 * [areByteArraysEqual] compares a range of bytes from [buffer1] with a |
125 * range of bytes from [buffer2]. | 124 * range of bytes from [buffer2]. |
126 * | 125 * |
127 * Returns [true] if the [count] bytes in [buffer1] (starting at | 126 * Returns [true] if the [count] bytes in [buffer1] (starting at |
128 * [offset1]) match the [count] bytes in [buffer2] (starting at | 127 * [offset1]) match the [count] bytes in [buffer2] (starting at |
129 * [offset2]). | 128 * [offset2]). |
130 * Otherwise [false] is returned. | 129 * Otherwise [false] is returned. |
131 */ | 130 */ |
132 bool areByteArraysEqual(List<int> buffer1, int offset1, | 131 bool areByteArraysEqual( |
133 List<int> buffer2, int offset2, | 132 List<int> buffer1, int offset1, List<int> buffer2, int offset2, int count) { |
134 int count) { | |
135 if ((offset1 + count) > buffer1.length || | 133 if ((offset1 + count) > buffer1.length || |
136 (offset2 + count) > buffer2.length) { | 134 (offset2 + count) > buffer2.length) { |
137 return false; | 135 return false; |
138 } | 136 } |
139 | 137 |
140 for (var i = 0; i < count; i++) { | 138 for (var i = 0; i < count; i++) { |
141 if (buffer1[offset1 + i] != buffer2[offset2 + i]) { | 139 if (buffer1[offset1 + i] != buffer2[offset2 + i]) { |
142 return false; | 140 return false; |
143 } | 141 } |
144 } | 142 } |
145 return true; | 143 return true; |
146 } | 144 } |
147 | 145 |
148 /** | 146 /** |
149 * [findBytes] searches for [pattern] in [data] beginning at [startPos]. | 147 * [findBytes] searches for [pattern] in [data] beginning at [startPos]. |
150 * | 148 * |
151 * Returns [true] if [pattern] was found in [data]. | 149 * Returns [true] if [pattern] was found in [data]. |
152 * Otherwise [false] is returned. | 150 * Otherwise [false] is returned. |
153 */ | 151 */ |
154 int findBytes(List<int> data, List<int> pattern, [int startPos=0]) { | 152 int findBytes(List<int> data, List<int> pattern, [int startPos = 0]) { |
155 // TODO(kustermann): Use one of the fast string-matching algorithms! | 153 // TODO(kustermann): Use one of the fast string-matching algorithms! |
156 for (int i = startPos; i < (data.length - pattern.length); i++) { | 154 for (int i = startPos; i < (data.length - pattern.length); i++) { |
157 bool found = true; | 155 bool found = true; |
158 for (int j = 0; j < pattern.length; j++) { | 156 for (int j = 0; j < pattern.length; j++) { |
159 if (data[i + j] != pattern[j]) { | 157 if (data[i + j] != pattern[j]) { |
160 found = false; | 158 found = false; |
161 break; | 159 break; |
162 } | 160 } |
163 } | 161 } |
164 if (found) { | 162 if (found) { |
165 return i; | 163 return i; |
166 } | 164 } |
167 } | 165 } |
168 return -1; | 166 return -1; |
169 } | 167 } |
170 | 168 |
171 List<int> encodeUtf8(String string) { | 169 List<int> encodeUtf8(String string) { |
172 return UTF8.encode(string); | 170 return UTF8.encode(string); |
173 } | 171 } |
174 | 172 |
175 // TODO(kustermann,ricow): As soon we have a debug log we should log | 173 // TODO(kustermann,ricow): As soon we have a debug log we should log |
176 // invalid utf8-encoded input to the log. | 174 // invalid utf8-encoded input to the log. |
177 // Currently invalid bytes will be replaced by a replacement character. | 175 // Currently invalid bytes will be replaced by a replacement character. |
178 String decodeUtf8(List<int> bytes) { | 176 String decodeUtf8(List<int> bytes) { |
179 return UTF8.decode(bytes, allowMalformed: true); | 177 return UTF8.decode(bytes, allowMalformed: true); |
180 } | 178 } |
181 | 179 |
182 class Locations { | 180 class Locations { |
183 static String getBrowserLocation(String browserName, | 181 static String getBrowserLocation( |
184 Map globalConfiguration) { | 182 String browserName, Map globalConfiguration) { |
185 var location = globalConfiguration[browserName]; | 183 var location = globalConfiguration[browserName]; |
186 if (location != null && location != '') { | 184 if (location != null && location != '') { |
187 return location; | 185 return location; |
188 } | 186 } |
189 var browserLocations = { | 187 var browserLocations = { |
190 'firefox': const { | 188 'firefox': const { |
191 'windows': 'C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe', | 189 'windows': 'C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe', |
192 'linux': 'firefox', | 190 'linux': 'firefox', |
193 'macos': '/Applications/Firefox.app/Contents/MacOS/firefox' | 191 'macos': '/Applications/Firefox.app/Contents/MacOS/firefox' |
194 }, | 192 }, |
195 'chrome': const { | 193 'chrome': const { |
196 'windows': | 194 'windows': |
197 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe', | 195 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe', |
198 'macos': | 196 'macos': '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', |
199 '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', | 197 'linux': 'google-chrome' |
200 'linux': 'google-chrome' | 198 }, |
201 }, | 199 'dartium': const { |
202 'dartium': const { | 200 'windows': 'client\\tests\\dartium\\chrome.exe', |
203 'windows': 'client\\tests\\dartium\\chrome.exe', | 201 'macos': 'client/tests/dartium/Chromium.app/Contents/MacOS/Chromium', |
204 'macos': 'client/tests/dartium/Chromium.app/Contents/MacOS/Chromium', | 202 'linux': 'client/tests/dartium/chrome' |
205 'linux': 'client/tests/dartium/chrome' | 203 }, |
206 }, | 204 'safari': const { |
207 'safari': const { | 205 'macos': '/Applications/Safari.app/Contents/MacOS/Safari' |
208 'macos': '/Applications/Safari.app/Contents/MacOS/Safari' | 206 }, |
209 }, | 207 'safarimobilesim': const { |
210 'safarimobilesim': const { | 208 'macos': '/Applications/Xcode.app/Contents/Developer/Platforms/' |
211 'macos': '/Applications/Xcode.app/Contents/Developer/Platforms/' | 209 'iPhoneSimulator.platform/Developer/Applications/' |
212 'iPhoneSimulator.platform/Developer/Applications/' | 210 'iPhone Simulator.app/Contents/MacOS/iPhone Simulator' |
213 'iPhone Simulator.app/Contents/MacOS/iPhone Simulator' | 211 }, |
214 }, | 212 'ie9': const { |
215 'ie9': const { | 213 'windows': 'C:\\Program Files\\Internet Explorer\\iexplore.exe' |
216 'windows': 'C:\\Program Files\\Internet Explorer\\iexplore.exe' | 214 }, |
217 }, | 215 'ie10': const { |
218 'ie10': const { | 216 'windows': 'C:\\Program Files\\Internet Explorer\\iexplore.exe' |
219 'windows': 'C:\\Program Files\\Internet Explorer\\iexplore.exe' | 217 }, |
220 }, | 218 'ie11': const { |
221 'ie11': const { | 219 'windows': 'C:\\Program Files\\Internet Explorer\\iexplore.exe' |
222 'windows': 'C:\\Program Files\\Internet Explorer\\iexplore.exe' | 220 } |
223 }}; | 221 }; |
224 browserLocations['ff'] = browserLocations['firefox']; | 222 browserLocations['ff'] = browserLocations['firefox']; |
225 | 223 |
226 assert(browserLocations[browserName] != null); | 224 assert(browserLocations[browserName] != null); |
227 location = browserLocations[browserName][Platform.operatingSystem]; | 225 location = browserLocations[browserName][Platform.operatingSystem]; |
228 if (location != null) { | 226 if (location != null) { |
229 return location; | 227 return location; |
230 } else { | 228 } else { |
231 throw '$browserName not supported on ${Platform.operatingSystem}'; | 229 throw '$browserName not supported on ${Platform.operatingSystem}'; |
232 } | 230 } |
233 } | 231 } |
234 } | 232 } |
235 | 233 |
236 // This function is pretty stupid and only puts quotes around an argument if | 234 // This function is pretty stupid and only puts quotes around an argument if |
237 // it the argument contains a space. | 235 // it the argument contains a space. |
238 String escapeCommandLineArgument(String argument) { | 236 String escapeCommandLineArgument(String argument) { |
239 if (argument.contains(' ')) { | 237 if (argument.contains(' ')) { |
240 return '"$argument"'; | 238 return '"$argument"'; |
241 } | 239 } |
242 return argument; | 240 return argument; |
243 } | 241 } |
244 | 242 |
245 class HashCodeBuilder { | 243 class HashCodeBuilder { |
246 int _value = 0; | 244 int _value = 0; |
247 | 245 |
248 void add(Object object) { | 246 void add(Object object) { |
249 _value = ((_value * 31) ^ object.hashCode) & 0x3FFFFFFF; | 247 _value = ((_value * 31) ^ object.hashCode) & 0x3FFFFFFF; |
250 } | 248 } |
251 | 249 |
252 void addJson(Object object) { | 250 void addJson(Object object) { |
253 if (object == null || object is num || object is String || | 251 if (object == null || |
254 object is Uri || object is bool) { | 252 object is num || |
| 253 object is String || |
| 254 object is Uri || |
| 255 object is bool) { |
255 add(object); | 256 add(object); |
256 } else if (object is List) { | 257 } else if (object is List) { |
257 object.forEach(addJson); | 258 object.forEach(addJson); |
258 } else if (object is Map) { | 259 } else if (object is Map) { |
259 for (var key in object.keys.toList()..sort()) { | 260 for (var key in object.keys.toList()..sort()) { |
260 addJson(key); | 261 addJson(key); |
261 addJson(object[key]); | 262 addJson(object[key]); |
262 } | 263 } |
263 } else { | 264 } else { |
264 throw new Exception("Can't build hashcode for non json-like object " | 265 throw new Exception("Can't build hashcode for non json-like object " |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 throw new Exception("Can't compare two non json-like objects " | 298 throw new Exception("Can't compare two non json-like objects " |
298 "(a: ${a.runtimeType}, b: ${b.runtimeType})"); | 299 "(a: ${a.runtimeType}, b: ${b.runtimeType})"); |
299 } | 300 } |
300 } | 301 } |
301 | 302 |
302 class UniqueObject { | 303 class UniqueObject { |
303 static int _nextId = 1; | 304 static int _nextId = 1; |
304 final int _hashCode; | 305 final int _hashCode; |
305 | 306 |
306 int get hashCode => _hashCode; | 307 int get hashCode => _hashCode; |
307 operator==(other) => other is UniqueObject && _hashCode == other._hashCode; | 308 operator ==(other) => other is UniqueObject && _hashCode == other._hashCode; |
308 | 309 |
309 UniqueObject() : _hashCode = ++_nextId; | 310 UniqueObject() : _hashCode = ++_nextId; |
310 } | 311 } |
OLD | NEW |