| 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 |