Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A sort of fix for issue #1127 (take 2) #1300

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 58 additions & 18 deletions src/main/java/org/junit/internal/ComparisonCriteria.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,23 @@ private void arrayEquals(String message, Object expecteds, Object actuals, boole

// Only include the user-provided message in the outer exception.
String exceptionMessage = outer ? header : "";
int expectedsLength = assertArraysAreSameLength(expecteds, actuals, exceptionMessage);

for (int i = 0; i < expectedsLength; i++) {
if (expecteds == null) {
Assert.fail(exceptionMessage + "expected array was null");
}
if (actuals == null) {
Assert.fail(exceptionMessage + "actual array was null");
}

int actualsLength = Array.getLength(actuals);
int expectedsLength = Array.getLength(expecteds);
if (actualsLength != expectedsLength) {
header = header + "array lengths differed, expected.length="
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+=?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can do. I always get a bit creeped out by doing += on strings, for some reason!

+ expectedsLength + " actual.length=" + actualsLength + "; ";
}
int prefixLength = Math.min(actualsLength, expectedsLength);

for (int i = 0; i < prefixLength; i++) {
Object expected = Array.get(expecteds, i);
Object actual = Array.get(actuals, i);

Expand All @@ -65,27 +79,53 @@ private void arrayEquals(String message, Object expecteds, Object actuals, boole
}
}
}
}

private boolean isArray(Object expected) {
return expected != null && expected.getClass().isArray();
if (actualsLength != expectedsLength) {
Object expected = getToStringableArrayElement(expecteds, expectedsLength, prefixLength);
Object actual = getToStringableArrayElement(actuals, actualsLength, prefixLength);
try {
Assert.assertEquals(expected, actual);
} catch (AssertionError e) {
throw new ArrayComparisonFailure(header, e, prefixLength);
}
}
}

private int assertArraysAreSameLength(Object expecteds,
Object actuals, String header) {
if (expecteds == null) {
Assert.fail(header + "expected array was null");
}
if (actuals == null) {
Assert.fail(header + "actual array was null");
private static final Object END_OF_ARRAY_SENTINEL = objectWithToString("end of array");

private Object getToStringableArrayElement(Object array, int length, int index) {
if (index < length) {
Object element = Array.get(array, index);
if (isArray(element)) {
return objectWithToString(componentTypeName(element.getClass()) + "[" + Array.getLength(element) + "]");
} else {
return element;
}
} else {
return END_OF_ARRAY_SENTINEL;
}
int actualsLength = Array.getLength(actuals);
int expectedsLength = Array.getLength(expecteds);
if (actualsLength != expectedsLength) {
Assert.fail(header + "array lengths differed, expected.length="
+ expectedsLength + " actual.length=" + actualsLength);
}

private static Object objectWithToString(final String string) {
return new Object() {
@Override
public String toString() {
return string;
}
};
}

private String componentTypeName(Class<?> arrayClass) {
Class<?> componentType = arrayClass.getComponentType();
if (componentType.isArray()) {
return componentTypeName(componentType) + "[]";
} else {
return componentType.getName();
}
return expectedsLength;
}

private boolean isArray(Object expected) {
return expected != null && expected.getClass().isArray();
}

protected abstract void assertElementsEqual(Object expected, Object actual);
Expand Down
220 changes: 169 additions & 51 deletions src/test/java/org/junit/tests/assertion/AssertionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,87 +57,117 @@ public void failWithMessageToString() {
}
}

@Test(expected = AssertionError.class)
@Test
public void arraysNotEqual() {
assertArrayEquals((new Object[]{new Object()}), (new Object[]{new Object()}));
assertArrayEqualsFailure(
new Object[]{"right"},
new Object[]{"wrong"},
"arrays first differed at element [0]; expected:<[right]> but was:<[wrong]>");
}

@Test(expected = AssertionError.class)
@Test
public void arraysNotEqualWithMessage() {
assertArrayEquals("not equal", (new Object[]{new Object()}), (new Object[]{new Object()}));
assertArrayEqualsFailure(
"not equal",
new Object[]{"right"},
new Object[]{"wrong"},
"not equal: arrays first differed at element [0]; expected:<[right]> but was:<[wrong]>");
}

@Test
public void arraysExpectedNullMessage() {
try {
assertArrayEquals("not equal", null, (new Object[]{new Object()}));
assertArrayEquals("not equal", null, new Object[]{new Object()});
} catch (AssertionError exception) {
assertEquals("not equal: expected array was null", exception.getMessage());
return;
}
fail("should have thrown an exception");
}

@Test
public void arraysActualNullMessage() {
try {
assertArrayEquals("not equal", (new Object[]{new Object()}), null);
assertArrayEquals("not equal", new Object[]{new Object()}, null);
} catch (AssertionError exception) {
assertEquals("not equal: actual array was null", exception.getMessage());
return;
}
fail("should have thrown an exception");
}

@Test
public void arraysDifferentLengthMessage() {
try {
assertArrayEquals("not equal", (new Object[0]), (new Object[1]));
} catch (AssertionError exception) {
assertEquals("not equal: array lengths differed, expected.length=0 actual.length=1", exception.getMessage());
}
public void arraysDifferentLengthDifferingAtStartMessage() {
assertArrayEqualsFailure(
"not equal",
new Object[]{true},
new Object[]{false, true},
"not equal: array lengths differed, expected.length=1 actual.length=2; arrays first differed at element [0]; expected:<true> but was:<false>");
}

@Test(expected = ArrayComparisonFailure.class)
@Test
public void arraysDifferentLengthDifferingAtEndMessage() {
assertArrayEqualsFailure(
"not equal",
new Object[]{true},
new Object[]{true, false},
"not equal: array lengths differed, expected.length=1 actual.length=2; arrays first differed at element [1]; expected:<end of array> but was:<false>");
}

@Test
public void arraysDifferentLengthDifferingAtEndAndExpectedArrayLongerMessage() {
assertArrayEqualsFailure(
"not equal",
new Object[]{true, false},
new Object[]{true},
"not equal: array lengths differed, expected.length=2 actual.length=1; arrays first differed at element [1]; expected:<false> but was:<end of array>");
}

@Test
public void arraysElementsDiffer() {
assertArrayEquals("not equal", (new Object[]{"this is a very long string in the middle of an array"}), (new Object[]{"this is another very long string in the middle of an array"}));
assertArrayEqualsFailure(
"not equal",
new Object[]{"this is a very long string in the middle of an array"},
new Object[]{"this is another very long string in the middle of an array"},
"not equal: arrays first differed at element [0]; expected:<this is a[] very long string in...> but was:<this is a[nother] very long string in...>");
}

@Test
public void arraysDifferAtElement0nullMessage() {
try {
assertArrayEquals((new Object[]{true}), (new Object[]{false}));
} catch (AssertionError exception) {
assertEquals("arrays first differed at element [0]; expected:<true> but was:<false>", exception
.getMessage());
}
assertArrayEqualsFailure(
new Object[]{true},
new Object[]{false},
"arrays first differed at element [0]; expected:<true> but was:<false>"
);
}

@Test
public void arraysDifferAtElement1nullMessage() {
try {
assertArrayEquals((new Object[]{true, true}), (new Object[]{true,
false}));
} catch (AssertionError exception) {
assertEquals("arrays first differed at element [1]; expected:<true> but was:<false>", exception
.getMessage());
}
assertArrayEqualsFailure(
new Object[]{true, true},
new Object[]{true, false},
"arrays first differed at element [1]; expected:<true> but was:<false>"
);
}

@Test
public void arraysDifferAtElement0withMessage() {
try {
assertArrayEquals("message", (new Object[]{true}), (new Object[]{false}));
} catch (AssertionError exception) {
assertEquals("message: arrays first differed at element [0]; expected:<true> but was:<false>", exception
.getMessage());
}
assertArrayEqualsFailure(
"message",
new Object[]{true},
new Object[]{false},
"message: arrays first differed at element [0]; expected:<true> but was:<false>"
);
}

@Test
public void arraysDifferAtElement1withMessage() {
try {
assertArrayEquals("message", (new Object[]{true, true}), (new Object[]{true, false}));
fail();
} catch (AssertionError exception) {
assertEquals("message: arrays first differed at element [1]; expected:<true> but was:<false>", exception.getMessage());
}
assertArrayEqualsFailure(
"message",
new Object[]{true, true},
new Object[]{true, false},
"message: arrays first differed at element [1]; expected:<true> but was:<false>"
);
}

@Test
Expand Down Expand Up @@ -196,30 +226,118 @@ public void multiDimensionalArraysDeclaredAsOneDimensionalAreEqual() {

@Test
public void multiDimensionalArraysAreNotEqual() {
try {
assertArrayEquals("message", (new Object[][]{{true, true}, {false, false}}), (new Object[][]{{true, true}, {true, false}}));
fail();
} catch (AssertionError exception) {
assertEquals("message: arrays first differed at element [1][0]; expected:<false> but was:<true>", exception.getMessage());
}
assertArrayEqualsFailure(
"message",
new Object[][]{{true, true}, {false, false}},
new Object[][]{{true, true}, {true, false}},
"message: arrays first differed at element [1][0]; expected:<false> but was:<true>");
}

@Test
public void multiDimensionalArraysAreNotEqualNoMessage() {
assertArrayEqualsFailure(
new Object[][]{{true, true}, {false, false}},
new Object[][]{{true, true}, {true, false}},
"arrays first differed at element [1][0]; expected:<false> but was:<true>");
}

@Test
public void twoDimensionalArraysDifferentOuterLengthNotEqual() {
assertArrayEqualsFailure(
"not equal",
new Object[][]{{true}, {}},
new Object[][]{{}},
"not equal: array lengths differed, expected.length=1 actual.length=0; arrays first differed at element [0][0]; expected:<true> but was:<end of array>");
assertArrayEqualsFailure(
"not equal",
new Object[][]{{}, {true}},
new Object[][]{{}},
"not equal: array lengths differed, expected.length=2 actual.length=1; arrays first differed at element [1]; expected:<java.lang.Object[1]> but was:<end of array>");
assertArrayEqualsFailure(
"not equal",
new Object[][]{{}},
new Object[][]{{true}, {}},
"not equal: array lengths differed, expected.length=0 actual.length=1; arrays first differed at element [0][0]; expected:<end of array> but was:<true>");
assertArrayEqualsFailure(
"not equal",
new Object[][]{{}},
new Object[][]{{}, {true}},
"not equal: array lengths differed, expected.length=1 actual.length=2; arrays first differed at element [1]; expected:<end of array> but was:<java.lang.Object[1]>");
}

@Test
public void primitiveArraysConvertedToStringCorrectly() {
assertArrayEqualsFailure(
"not equal",
new boolean[][]{{}, {true}},
new boolean[][]{{}},
"not equal: array lengths differed, expected.length=2 actual.length=1; arrays first differed at element [1]; expected:<boolean[1]> but was:<end of array>");
assertArrayEqualsFailure(
"not equal",
new int[][]{{}, {23}},
new int[][]{{}},
"not equal: array lengths differed, expected.length=2 actual.length=1; arrays first differed at element [1]; expected:<int[1]> but was:<end of array>");
}

@Test
public void twoDimensionalArraysConvertedToStringCorrectly() {
assertArrayEqualsFailure(
"not equal",
new Object[][][]{{}, {{true}}},
new Object[][][]{{}},
"not equal: array lengths differed, expected.length=2 actual.length=1; arrays first differed at element [1]; expected:<java.lang.Object[][1]> but was:<end of array>");
}

@Test
public void twoDimensionalArraysDifferentInnerLengthNotEqual() {
assertArrayEqualsFailure(
"not equal",
new Object[][]{{true}, {}},
new Object[][]{{}, {}},
"not equal: array lengths differed, expected.length=1 actual.length=0; arrays first differed at element [0][0]; expected:<true> but was:<end of array>");
assertArrayEqualsFailure(
"not equal",
new Object[][]{{}, {true}},
new Object[][]{{}, {}},
"not equal: array lengths differed, expected.length=1 actual.length=0; arrays first differed at element [1][0]; expected:<true> but was:<end of array>");
assertArrayEqualsFailure(
"not equal",
new Object[][]{{}, {}},
new Object[][]{{true}, {}},
"not equal: array lengths differed, expected.length=0 actual.length=1; arrays first differed at element [0][0]; expected:<end of array> but was:<true>");
assertArrayEqualsFailure(
"not equal",
new Object[][]{{}, {}},
new Object[][]{{}, {true}},
"not equal: array lengths differed, expected.length=0 actual.length=1; arrays first differed at element [1][0]; expected:<end of array> but was:<true>");
}

private void assertArrayEqualsFailure(Object[] expecteds, Object[] actuals, String expectedMessage) {
try {
assertArrayEquals(expecteds, actuals);
} catch (ArrayComparisonFailure e) {
assertEquals(expectedMessage, e.getMessage());
return;
}
fail("should have thrown an exception");
}

private void assertArrayEqualsFailure(String message, Object[] expecteds, Object[] actuals, String expectedMessage) {
try {
assertArrayEquals((new Object[][]{{true, true}, {false, false}}), (new Object[][]{{true, true}, {true, false}}));
fail();
} catch (AssertionError exception) {
assertEquals("arrays first differed at element [1][0]; expected:<false> but was:<true>", exception.getMessage());
assertArrayEquals(message, expecteds, actuals);
} catch (ArrayComparisonFailure e) {
assertEquals(expectedMessage, e.getMessage());
return;
}
fail("should have thrown an exception");
}

@Test
public void multiDimensionalArraysDifferentLengthMessage() {
try {
assertArrayEquals("message", new Object[][]{{true, true}, {false, false}}, new Object[][]{{true, true}, {false}});
} catch (AssertionError exception) {
assertEquals("message: arrays first differed at element [1]; array lengths differed, expected.length=2 actual.length=1", exception.getMessage());
assertEquals("message: array lengths differed, expected.length=2 actual.length=1; arrays first differed at element [1][1]; expected:<false> but was:<end of array>", exception.getMessage());
return;
}

Expand All @@ -231,7 +349,7 @@ public void multiDimensionalArraysDifferentLengthNoMessage() {
try {
assertArrayEquals(new Object[][]{{true, true}, {false, false}}, new Object[][]{{true, true}, {false}});
} catch (AssertionError exception) {
assertEquals("arrays first differed at element [1]; array lengths differed, expected.length=2 actual.length=1", exception.getMessage());
assertEquals("array lengths differed, expected.length=2 actual.length=1; arrays first differed at element [1][1]; expected:<false> but was:<end of array>", exception.getMessage());
return;
}

Expand Down