| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
| 6 * This library contains an Expect class with static methods that can be used | 6 * This library contains an Expect class with static methods that can be used |
| 7 * for simple unit-tests. | 7 * for simple unit-tests. |
| 8 */ | 8 */ |
| 9 library expect; | 9 library expect; |
| 10 | 10 |
| 11 /** | 11 /** |
| 12 * Expect is used for tests that do not want to make use of the | 12 * Expect is used for tests that do not want to make use of the |
| 13 * Dart unit test library - for example, the core language tests. | 13 * Dart unit test library - for example, the core language tests. |
| 14 * Third parties are discouraged from using this, and should use | 14 * Third parties are discouraged from using this, and should use |
| 15 * the expect() function in the unit test library instead for | 15 * the expect() function in the unit test library instead for |
| 16 * test assertions. | 16 * test assertions. |
| 17 */ | 17 */ |
| 18 class Expect { | 18 class Expect { |
| 19 /** | 19 /** |
| 20 * Return a slice of a string. | 20 * Return a slice of a string. |
| 21 * | 21 * |
| 22 * The slice will contain at least the substring from [start] to the lower of | 22 * The slice will contain at least the substring from [start] to the lower of |
| 23 * [end] and `start + length`. | 23 * [end] and `start + length`. |
| 24 * If the result is no more than `length - 10` characters long, | 24 * If the result is no more than `length - 10` characters long, |
| 25 * context may be added by extending the range of the slice, by decreasing | 25 * context may be added by extending the range of the slice, by decreasing |
| 26 * [start] and increasing [end], up to at most length characters. | 26 * [start] and increasing [end], up to at most length characters. |
| 27 * If the start or end of the slice are not matching the start or end of | 27 * If the start or end of the slice are not matching the start or end of |
| 28 * the string, ellipses are added before or after the slice. | 28 * the string, ellipses are added before or after the slice. |
| 29 * Control characters may be encoded as "\xhh" codes. | 29 * Characters other than printable ASCII are escaped. |
| 30 */ | 30 */ |
| 31 static String _truncateString(String string, int start, int end, int length) { | 31 static String _truncateString(String string, int start, int end, int length) { |
| 32 if (end - start > length) { | 32 if (end - start > length) { |
| 33 end = start + length; | 33 end = start + length; |
| 34 } else if (end - start < length) { | 34 } else if (end - start < length) { |
| 35 int overflow = length - (end - start); | 35 int overflow = length - (end - start); |
| 36 if (overflow > 10) overflow = 10; | 36 if (overflow > 10) overflow = 10; |
| 37 // Add context. | 37 // Add context. |
| 38 start = start - ((overflow + 1) ~/ 2); | 38 start = start - ((overflow + 1) ~/ 2); |
| 39 end = end + (overflow ~/ 2); | 39 end = end + (overflow ~/ 2); |
| 40 if (start < 0) start = 0; | 40 if (start < 0) start = 0; |
| 41 if (end > string.length) end = string.length; | 41 if (end > string.length) end = string.length; |
| 42 } | 42 } |
| 43 if (start == 0 && end == string.length) return string; | |
| 44 StringBuffer buf = new StringBuffer(); | 43 StringBuffer buf = new StringBuffer(); |
| 45 if (start > 0) buf.write("..."); | 44 if (start > 0) buf.write("..."); |
| 46 for (int i = start; i < end; i++) { | 45 _escapeSubstring(buf, string, 0, string.length); |
| 47 int code = string.codeUnitAt(i); | |
| 48 if (code < 0x20) { | |
| 49 buf.write(r"\x"); | |
| 50 buf.write("0123456789abcdef"[code ~/ 16]); | |
| 51 buf.write("0123456789abcdef"[code % 16]); | |
| 52 } else { | |
| 53 buf.writeCharCode(string.codeUnitAt(i)); | |
| 54 } | |
| 55 } | |
| 56 if (end < string.length) buf.write("..."); | 46 if (end < string.length) buf.write("..."); |
| 57 return buf.toString(); | 47 return buf.toString(); |
| 58 } | 48 } |
| 59 | 49 |
| 50 /// Return the string with characters that are not printable ASCII characters |
| 51 /// escaped as either "\xXX" codes or "\uXXXX" codes. |
| 52 static String _escapeString(String string) { |
| 53 StringBuffer buf = new StringBuffer(); |
| 54 _escapeSubstring(buf, string, 0, string.length); |
| 55 return buf.toString(); |
| 56 } |
| 57 |
| 58 static _escapeSubstring(StringBuffer buf, String string, int start, int end) { |
| 59 const hexDigits = "0123456789ABCDEF"; |
| 60 for (int i = start; i < end; i++) { |
| 61 int code = string.codeUnitAt(i); |
| 62 if (0x20 <= code && code < 0x7F) { |
| 63 if (code == 0x5C) { |
| 64 buf.write(r"\\"); |
| 65 } else { |
| 66 buf.writeCharCode(code); |
| 67 } |
| 68 } else if (code < 0x100) { |
| 69 buf.write(r"\x"); |
| 70 buf.write(hexDigits[code >> 4]); |
| 71 buf.write(hexDigits[code & 15]); |
| 72 } else { |
| 73 buf.write(r"\u{"); |
| 74 buf.write(code.toRadixString(16).toUpperCase()); |
| 75 buf.write(r"}"); |
| 76 } |
| 77 } |
| 78 } |
| 79 |
| 60 /** | 80 /** |
| 61 * Find the difference between two strings. | 81 * Find the difference between two strings. |
| 62 * | 82 * |
| 63 * This finds the first point where two strings differ, and returns | 83 * This finds the first point where two strings differ, and returns |
| 64 * a text describing the difference. | 84 * a text describing the difference. |
| 65 * | 85 * |
| 66 * For small strings (length less than 20) nothing is done, and null is | 86 * For small strings (length less than 20) nothing is done, and null is |
| 67 * returned. Small strings can be compared visually, but for longer strings | 87 * returned. Small strings can be compared visually, but for longer strings |
| 68 * only a slice containing the first difference will be shown. | 88 * only a slice containing the first difference will be shown. |
| 69 */ | 89 */ |
| (...skipping 21 matching lines...) Expand all Loading... |
| 91 * Checks whether the expected and actual values are equal (using `==`). | 111 * Checks whether the expected and actual values are equal (using `==`). |
| 92 */ | 112 */ |
| 93 static void equals(var expected, var actual, [String reason = null]) { | 113 static void equals(var expected, var actual, [String reason = null]) { |
| 94 if (expected == actual) return; | 114 if (expected == actual) return; |
| 95 String msg = _getMessage(reason); | 115 String msg = _getMessage(reason); |
| 96 if (expected is String && actual is String) { | 116 if (expected is String && actual is String) { |
| 97 String stringDifference = _stringDifference(expected, actual); | 117 String stringDifference = _stringDifference(expected, actual); |
| 98 if (stringDifference != null) { | 118 if (stringDifference != null) { |
| 99 _fail("Expect.equals($stringDifference$msg) fails."); | 119 _fail("Expect.equals($stringDifference$msg) fails."); |
| 100 } | 120 } |
| 121 _fail("Expect.equals(expected: <${_escapeString(expected)}>" |
| 122 ", actual: <${_escapeString(actual)}>$msg) fails."); |
| 101 } | 123 } |
| 102 _fail("Expect.equals(expected: <$expected>, actual: <$actual>$msg) fails."); | 124 _fail("Expect.equals(expected: <$expected>, actual: <$actual>$msg) fails."); |
| 103 } | 125 } |
| 104 | 126 |
| 105 /** | 127 /** |
| 106 * Checks whether the actual value is a bool and its value is true. | 128 * Checks whether the actual value is a bool and its value is true. |
| 107 */ | 129 */ |
| 108 static void isTrue(var actual, [String reason = null]) { | 130 static void isTrue(var actual, [String reason = null]) { |
| 109 if (_identical(actual, true)) return; | 131 if (_identical(actual, true)) return; |
| 110 String msg = _getMessage(reason); | 132 String msg = _getMessage(reason); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 138 _fail("Expect.isNotNull(actual: <$actual>$msg) fails."); | 160 _fail("Expect.isNotNull(actual: <$actual>$msg) fails."); |
| 139 } | 161 } |
| 140 | 162 |
| 141 /** | 163 /** |
| 142 * Checks whether the expected and actual values are identical | 164 * Checks whether the expected and actual values are identical |
| 143 * (using `identical`). | 165 * (using `identical`). |
| 144 */ | 166 */ |
| 145 static void identical(var expected, var actual, [String reason = null]) { | 167 static void identical(var expected, var actual, [String reason = null]) { |
| 146 if (_identical(expected, actual)) return; | 168 if (_identical(expected, actual)) return; |
| 147 String msg = _getMessage(reason); | 169 String msg = _getMessage(reason); |
| 170 if (expected is String && actual is String) { |
| 171 String note = |
| 172 (expected == actual) ? ' Strings equal but not identical.' : ''; |
| 173 _fail("Expect.identical(expected: <${_escapeString(expected)}>" |
| 174 ", actual: <${_escapeString(actual)}>$msg) " |
| 175 "fails.$note"); |
| 176 } |
| 148 _fail("Expect.identical(expected: <$expected>, actual: <$actual>$msg) " | 177 _fail("Expect.identical(expected: <$expected>, actual: <$actual>$msg) " |
| 149 "fails."); | 178 "fails."); |
| 150 } | 179 } |
| 151 | 180 |
| 152 // Unconditional failure. | 181 // Unconditional failure. |
| 153 static void fail(String msg) { | 182 static void fail(String msg) { |
| 154 _fail("Expect.fail('$msg')"); | 183 _fail("Expect.fail('$msg')"); |
| 155 } | 184 } |
| 156 | 185 |
| 157 /** | 186 /** |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 const TrustTypeAnnotations(); | 496 const TrustTypeAnnotations(); |
| 468 } | 497 } |
| 469 | 498 |
| 470 /// Annotation class for testing of dart2js. Use this as metadata on method | 499 /// Annotation class for testing of dart2js. Use this as metadata on method |
| 471 /// declarations to disable closed world assumptions on parameters, effectively | 500 /// declarations to disable closed world assumptions on parameters, effectively |
| 472 /// assuming that the runtime arguments could be any value. Note that the | 501 /// assuming that the runtime arguments could be any value. Note that the |
| 473 /// constraints due to [TrustTypeAnnotations] still apply. | 502 /// constraints due to [TrustTypeAnnotations] still apply. |
| 474 class AssumeDynamic { | 503 class AssumeDynamic { |
| 475 const AssumeDynamic(); | 504 const AssumeDynamic(); |
| 476 } | 505 } |
| OLD | NEW |