Skip to content

Commit

Permalink
Fix regression on Stream isEqualTo assertion.
Browse files Browse the repository at this point in the history
Remove support for infinite Stream for startsWith assertion as it prevents chaining any other assertions when using finite streams.
  • Loading branch information
joel-costigliola committed Jul 3, 2016
1 parent 6d56480 commit d72a77e
Show file tree
Hide file tree
Showing 3 changed files with 244 additions and 114 deletions.
26 changes: 11 additions & 15 deletions src/main/java/org/assertj/core/api/ListAssert.java
Expand Up @@ -43,15 +43,14 @@ public ListAssert(List<? extends ELEMENT> actual) {

super(actual, ListAssert.class, new ObjectAssertFactory<ELEMENT>());
}

protected ListAssert(Stream<? extends ELEMENT> actual) {
this(actual == null ? null : new ListFromStream<>(actual));
}

@Override
public ListAssert<ELEMENT> isEqualTo(Object expected) {
if (actual instanceof ListFromStream) {
objects.assertEqual(info, asListFromStream().stream, expected);
if (actual instanceof ListFromStream && asListFromStream().stream == expected) {
return myself;
}
return super.isEqualTo(expected);
Expand All @@ -65,7 +64,7 @@ public ListAssert<ELEMENT> isInstanceOf(Class<?> type) {
}
return super.isInstanceOf(type);
}

@Override
public ListAssert<ELEMENT> isInstanceOfAny(Class<?>... types) {
if (actual instanceof ListFromStream) {
Expand All @@ -83,7 +82,7 @@ public ListAssert<ELEMENT> isOfAnyClassIn(Class<?>... types) {
}
return super.isOfAnyClassIn(types);
}

@Override
public ListAssert<ELEMENT> isExactlyInstanceOf(Class<?> type) {
if (actual instanceof ListFromStream) {
Expand Down Expand Up @@ -128,7 +127,7 @@ public ListAssert<ELEMENT> isNotExactlyInstanceOf(Class<?> type) {
}
return super.isNotExactlyInstanceOf(type);
}

@Override
public ListAssert<ELEMENT> isSameAs(Object expected) {
if (actual instanceof ListFromStream) {
Expand All @@ -154,9 +153,10 @@ public ListAssert<ELEMENT> startsWith(@SuppressWarnings("unchecked") ELEMENT...
}
objects.assertNotNull(info, actual);
checkIsNotNull(sequence);
// To handle infinite stream we use the internal iterator instead of iterator() that consumes it totally.
// NO SUPPORT FOR infinite streams as it prevents chaining other assertions afterward, it requires to consume the
// Stream partially, if you chain another assertion, the stream is already consumed.
@SuppressWarnings("unchecked")
Iterator<? extends ELEMENT> iterator = ((ListFromStream<ELEMENT>) actual).stream.iterator();
Iterator<? extends ELEMENT> iterator = asListFromStream().stream().iterator();
if (sequence.length == 0 && iterator.hasNext()) throw new AssertionError("actual is not empty");
int i = 0;
while (iterator.hasNext()) {
Expand All @@ -172,15 +172,15 @@ public ListAssert<ELEMENT> startsWith(@SuppressWarnings("unchecked") ELEMENT...
}

private AssertionError actualDoesNotStartWithSequence(AssertionInfo info, Object[] sequence) {
return Failures.instance().failure(info, shouldStartWith("Stream under test", sequence, iterables.getComparisonStrategy()));
return Failures.instance()
.failure(info, shouldStartWith("Stream under test", sequence, iterables.getComparisonStrategy()));
}


@SuppressWarnings("rawtypes")
private ListFromStream asListFromStream() {
return (ListFromStream) actual;
}

@VisibleForTesting
static class ListFromStream<ELEMENT> extends AbstractList<ELEMENT> {
private Stream<ELEMENT> stream;
Expand All @@ -191,29 +191,25 @@ public ListFromStream(Stream<ELEMENT> stream) {
}

public Stream<ELEMENT> stream() {
System.out.println("stream()");
initList();
return list.stream();
}

private List<ELEMENT> initList() {
if (list == null) {
System.out.println("initList : create list");
list = stream.collect(Collectors.toList());
}
return list;
}

@Override
public int size() {
System.out.println("size()");
initList();
return list.size();
}

@Override
public ELEMENT get(int index) {
System.out.println("get()");
initList();
return list.get(index);
}
Expand Down
Expand Up @@ -12,15 +12,11 @@
*/
package org.assertj.core.api;

import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.atIndex;
import static org.assertj.core.test.ErrorMessages.valuesToLookForIsNull;
import static org.assertj.core.test.ExpectedException.none;
import static org.assertj.core.test.ObjectArrays.emptyArray;
import static org.assertj.core.test.TestFailures.failBecauseExpectedAssertionErrorWasNotThrown;
import static org.assertj.core.util.Arrays.array;
import static org.assertj.core.util.FailureMessages.actualIsNull;
import static org.assertj.core.util.Lists.newArrayList;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyZeroInteractions;

Expand All @@ -30,7 +26,6 @@
import org.assertj.core.api.IterableAssert.LazyIterable;
import org.assertj.core.test.ExpectedException;
import org.assertj.core.test.StringStream;
import org.assertj.core.util.CaseInsensitiveStringComparator;
import org.junit.Rule;
import org.junit.Test;

Expand All @@ -41,8 +36,6 @@ public class Assertions_assertThat_with_Stream_Test {

private StringStream stringStream = new StringStream();

Stream<String> infiniteStream = Stream.generate(() -> "");

@Test
public void should_create_Assert() {
Object assertions = Assertions.assertThat(Stream.of("Luke", "Leia"));
Expand Down Expand Up @@ -153,107 +146,50 @@ public void isNotSameAs_should_check_the_original_stream_without_consuming_it()
Assertions.fail("Expected assertionError, because assert notSame on same stream.");
}

// startsWith tests

@Test
public void startsWith_should_work_with_infinite_streams() {
assertThat(infiniteStream).startsWith("", "");
}

@Test
public void should_throw_error_if_sequence_is_null() {
thrown.expectNullPointerException(valuesToLookForIsNull());
assertThat(infiniteStream).startsWith((String[]) null);
public void test_issue_245() throws Exception {
Foo foo1 = new Foo("id", 1);
foo1._f2 = "foo1";
Foo foo2 = new Foo("id", 2);
foo2._f2 = "foo1";
List<Foo> stream2 = newArrayList(foo2);
assertThat(Stream.of(foo1)).usingElementComparatorOnFields("_f2").isEqualTo(stream2);
assertThat(Stream.of(foo1)).usingElementComparatorOnFields("id").isEqualTo(stream2);
assertThat(Stream.of(foo1)).usingElementComparatorIgnoringFields("bar").isEqualTo(stream2);
}

@Test
public void should_pass_if_actual_and_sequence_are_empty() {
Stream<Object> empty = asList().stream();
assertThat(empty).startsWith(emptyArray());
public void test_issue_236() throws Exception {
List<Foo> stream2 = newArrayList(new Foo("id", 2));
assertThat(Stream.of(new Foo("id", 1))).usingElementComparatorOnFields("id")
.isEqualTo(stream2);
assertThat(Stream.of(new Foo("id", 1))).usingElementComparatorIgnoringFields("bar")
.isEqualTo(stream2);
}

@Test
public void should_fail_if_sequence_to_look_for_is_empty_and_actual_is_not() {
thrown.expect(AssertionError.class);
Stream<String> names = asList("Luke", "Leia").stream();
assertThat(names).startsWith(new String[0]);
}

@Test
public void should_fail_if_actual_is_null() {
thrown.expectAssertionError(actualIsNull());
Stream<Object> names = null;
assertThat(names).startsWith(emptyArray());
}

@Test
public void should_fail_if_sequence_is_bigger_than_actual() {
thrown.expect(AssertionError.class);
String[] sequence = { "Luke", "Leia", "Obi-Wan", "Han", "C-3PO", "R2-D2", "Anakin" };
Stream<String> names = asList("Luke", "Leia").stream();
assertThat(names).startsWith(sequence);
}

@Test
public void should_fail_if_actual_does_not_start_with_sequence() {
thrown.expect(AssertionError.class);
String[] sequence = { "Han", "C-3PO" };
Stream<String> names = asList("Luke", "Leia").stream();
assertThat(names).startsWith(sequence);
}

@Test
public void should_fail_if_actual_starts_with_first_elements_of_sequence_only() {
thrown.expect(AssertionError.class);
String[] sequence = { "Luke", "Yoda" };
Stream<String> names = asList("Luke", "Leia").stream();
assertThat(names).startsWith(sequence);
}
public static class Foo {
private String id;
private int bar;
public String _f2;

@Test
public void should_pass_if_actual_starts_with_sequence() {
Stream<String> names = asList("Luke", "Leia", "Yoda").stream();
assertThat(names).startsWith(array("Luke", "Leia"));
}

@Test
public void should_pass_if_actual_and_sequence_are_equal() {
Stream<String> names = asList("Luke", "Leia").stream();
assertThat(names).startsWith(array("Luke", "Leia"));
}

// ------------------------------------------------------------------------------------------------------------------
// tests using a custom comparison strategy
// ------------------------------------------------------------------------------------------------------------------

@Test
public void should_fail_if_actual_does_not_start_with_sequence_according_to_custom_comparison_strategy() {
thrown.expect(AssertionError.class);
Stream<String> names = asList("Luke", "Leia").stream();
String[] sequence = { "Han", "C-3PO" };
assertThat(names).usingElementComparator(CaseInsensitiveStringComparator.instance).startsWith(sequence);
}
public String getId() {
return id;
}

@Test
public void should_fail_if_actual_starts_with_first_elements_of_sequence_only_according_to_custom_comparison_strategy() {
thrown.expect(AssertionError.class);
Stream<String> names = asList("Luke", "Leia").stream();
String[] sequence = { "Luke", "Obi-Wan", "Han" };
assertThat(names).usingElementComparator(CaseInsensitiveStringComparator.instance).startsWith(sequence);
}
public int getBar() {
return bar;
}

@Test
public void should_pass_if_actual_starts_with_sequence_according_to_custom_comparison_strategy() {
Stream<String> names = asList("Luke", "Leia").stream();
String[] sequence = { "LUKE" };
assertThat(names).usingElementComparator(CaseInsensitiveStringComparator.instance).startsWith(sequence);
}
public Foo(String id, int bar) {
super();
this.id = id;
this.bar = bar;
}

@Test
public void should_pass_if_actual_and_sequence_are_equal_according_to_custom_comparison_strategy() {
Stream<String> names = asList("Luke", "Leia").stream();
String[] sequence = { "LUKE", "lEIA" };
assertThat(names).usingElementComparator(CaseInsensitiveStringComparator.instance).startsWith(sequence);
@Override
public String toString() {
return "Foo [id=" + id + ", bar=" + bar + "]";
}
}

}

0 comments on commit d72a77e

Please sign in to comment.