Expect.equals and Expect.identical escape more strings

I found it difficult to understand messages with strings that look the
same, e.g. containing zero-width character or different encodings of a
character.

BUG=
R=lrn@google.com

Review-Url: https://codereview.chromium.org/2750763002 .
This commit is contained in:
Stephen Adams 2017-04-06 15:38:49 -07:00
parent f1c7a22c43
commit 85af0259cb

View file

@ -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,23 +40,43 @@ 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("...");
for (int i = start; i < end; i++) {
int code = string.codeUnitAt(i);
if (code < 0x20) {
buf.write(r"\x");
buf.write("0123456789abcdef"[code ~/ 16]);
buf.write("0123456789abcdef"[code % 16]);
} else {
buf.writeCharCode(string.codeUnitAt(i));
}
}
_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 (0x20 <= code && code < 0x7F) {
if (code == 0x5C) {
buf.write(r"\\");
} else {
buf.writeCharCode(code);
}
} else if (code < 0x100) {
buf.write(r"\x");
buf.write(hexDigits[code >> 4]);
buf.write(hexDigits[code & 15]);
} else {
buf.write(r"\u{");
buf.write(code.toRadixString(16).toUpperCase());
buf.write(r"}");
}
}
}
/**
* Find the difference between two strings.
*
@ -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.");
}