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 |