Index: pkg/expect/lib/expect.dart |
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart |
index 4ee2832d383bb10203d22ad7edcd9c98648aa0b5..8e312063943e96fc9f47f741e98234673b6e60c4 100644 |
--- a/pkg/expect/lib/expect.dart |
+++ b/pkg/expect/lib/expect.dart |
@@ -26,7 +26,7 @@ class Expect { |
* [start] and increasing [end], up to at most length characters. |
* If the start or end of the slice are not matching the start or end of |
* the string, ellipses are added before or after the slice. |
- * Control characters may be encoded as "\xhh" codes. |
+ * Characters other than printable ASCII are escaped. |
*/ |
static String _truncateString(String string, int start, int end, int length) { |
if (end - start > length) { |
@@ -40,21 +40,41 @@ class Expect { |
if (start < 0) start = 0; |
if (end > string.length) end = string.length; |
} |
- if (start == 0 && end == string.length) return string; |
StringBuffer buf = new StringBuffer(); |
if (start > 0) buf.write("..."); |
+ _escapeSubstring(buf, string, 0, string.length); |
+ if (end < string.length) buf.write("..."); |
+ return buf.toString(); |
+ } |
+ |
+ /// Return the string with characters that are not printable ASCII characters |
+ /// escaped as either "\xXX" codes or "\uXXXX" codes. |
+ static String _escapeString(String string) { |
+ StringBuffer buf = new StringBuffer(); |
+ _escapeSubstring(buf, string, 0, string.length); |
+ return buf.toString(); |
+ } |
+ |
+ static _escapeSubstring(StringBuffer buf, String string, int start, int end) { |
+ const hexDigits = "0123456789ABCDEF"; |
for (int i = start; i < end; i++) { |
int code = string.codeUnitAt(i); |
- if (code < 0x20) { |
+ if (0x20 <= code && code < 0x7F) { |
+ if (code == 0x5C) { |
+ buf.write(r"\\"); |
+ } else { |
+ buf.writeCharCode(code); |
+ } |
+ } else if (code < 0x100) { |
buf.write(r"\x"); |
- buf.write("0123456789abcdef"[code ~/ 16]); |
- buf.write("0123456789abcdef"[code % 16]); |
+ buf.write(hexDigits[code >> 4]); |
+ buf.write(hexDigits[code & 15]); |
} else { |
- buf.writeCharCode(string.codeUnitAt(i)); |
+ buf.write(r"\u{"); |
+ buf.write(code.toRadixString(16).toUpperCase()); |
+ buf.write(r"}"); |
} |
} |
- if (end < string.length) buf.write("..."); |
- return buf.toString(); |
} |
/** |
@@ -98,6 +118,8 @@ class Expect { |
if (stringDifference != null) { |
_fail("Expect.equals($stringDifference$msg) fails."); |
} |
+ _fail("Expect.equals(expected: <${_escapeString(expected)}>" |
+ ", actual: <${_escapeString(actual)}>$msg) fails."); |
} |
_fail("Expect.equals(expected: <$expected>, actual: <$actual>$msg) fails."); |
} |
@@ -145,6 +167,13 @@ class Expect { |
static void identical(var expected, var actual, [String reason = null]) { |
if (_identical(expected, actual)) return; |
String msg = _getMessage(reason); |
+ if (expected is String && actual is String) { |
+ String note = |
+ (expected == actual) ? ' Strings equal but not identical.' : ''; |
+ _fail("Expect.identical(expected: <${_escapeString(expected)}>" |
+ ", actual: <${_escapeString(actual)}>$msg) " |
+ "fails.$note"); |
+ } |
_fail("Expect.identical(expected: <$expected>, actual: <$actual>$msg) " |
"fails."); |
} |