Skip to content

Commit

Permalink
Merge branch 'main' into gh-3368
Browse files Browse the repository at this point in the history
  • Loading branch information
scordio committed Mar 5, 2024
2 parents da56f61 + 6543a5c commit 6852811
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 72 deletions.
2 changes: 1 addition & 1 deletion assertj-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
<dependency>
<groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier</artifactId>
<version>3.15.7</version>
<version>3.15.8</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class ShouldHaveCauseExactlyInstance extends BasicErrorMessageFactory {
public static ErrorMessageFactory shouldHaveCauseExactlyInstance(Throwable actual,
Class<? extends Throwable> expectedCauseType) {
return actual.getCause() == null
? new ShouldHaveCauseExactlyInstance(expectedCauseType)
? new ShouldHaveCauseExactlyInstance(expectedCauseType, actual)
: new ShouldHaveCauseExactlyInstance(actual, expectedCauseType);
}

Expand All @@ -47,8 +47,8 @@ private ShouldHaveCauseExactlyInstance(Throwable actual, Class<? extends Throwab
expectedCauseType, actual.getCause().getClass());
}

private ShouldHaveCauseExactlyInstance(Class<? extends Throwable> expectedCauseType) {
super("%nExpecting a throwable with cause being exactly an instance of:%n %s%nbut current throwable has no cause.",
expectedCauseType);
private ShouldHaveCauseExactlyInstance(Class<? extends Throwable> expectedCauseType, Throwable actual) {
super("%nExpecting a throwable with cause being exactly an instance of:%n %s%nbut current throwable has no cause." +
"%nThrowable that failed the check:%n" + escapePercent(getStackTrace(actual)), expectedCauseType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
import static org.assertj.core.util.IterableUtil.isNullOrEmpty;

import java.lang.reflect.Array;
import java.util.LinkedHashSet;
import java.util.Set;

/**
* Base implementation of {@link ComparisonStrategy} contract.
*
*
* @author Joel Costigliola
*/
public abstract class AbstractComparisonStrategy implements ComparisonStrategy {
Expand All @@ -30,21 +31,21 @@ public abstract class AbstractComparisonStrategy implements ComparisonStrategy {
public Iterable<?> duplicatesFrom(Iterable<?> iterable) {
if (isNullOrEmpty(iterable)) return EMPTY_SET;

Set<Object> duplicates = newSetUsingComparisonStrategy();
Set<Object> noDuplicates = newSetUsingComparisonStrategy();
Set<Object> duplicatesWithOrderPreserved = new LinkedHashSet<>();
for (Object element : iterable) {
if (noDuplicates.contains(element)) {
duplicates.add(element);
duplicatesWithOrderPreserved.add(element);
} else {
noDuplicates.add(element);
}
}
return duplicates;
return duplicatesWithOrderPreserved;
}

/**
* Returns a {@link Set} honoring the comparison strategy used.
*
*
* @return a {@link Set} honoring the comparison strategy used.
*/
protected abstract Set<Object> newSetUsingComparisonStrategy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ void should_create_error_message_for_no_cause() {
// THEN
then(message).isEqualTo("%nExpecting a throwable with cause being exactly an instance of:%n" +
" %s%n" +
"but current throwable has no cause.", expected);
"but current throwable has no cause." +
"%nThrowable that failed the check:%n%s", expected, getStackTrace(actual));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,63 +12,70 @@
*/
package org.assertj.core.internal;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.util.Arrays.array;
import static org.assertj.core.util.IterableUtil.isNullOrEmpty;
import static org.assertj.core.util.IterableUtil.sizeOf;
import static org.assertj.core.util.Lists.newArrayList;
import static org.assertj.core.util.Lists.list;

import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.Test;

/**
* Tests for {@link StandardComparisonStrategy#duplicatesFrom(java.util.Collection)}.<br>
* Tests for {@link StandardComparisonStrategy#duplicatesFrom(Iterable)}.<br>
*
* @author Joel Costigliola
*/
class StandardComparisonStrategy_duplicatesFrom_Test extends AbstractTest_StandardComparisonStrategy {

@Test
void should_return_existing_duplicates() {
List<String> list = newArrayList("Merry", "Frodo", null, null, "Merry", "Sam", "Frodo");
Iterable<?> duplicates = standardComparisonStrategy.duplicatesFrom(list);

assertThat(sizeOf(duplicates)).isEqualTo(3);
assertThat(standardComparisonStrategy.iterableContains(duplicates, "Frodo")).isTrue();
assertThat(standardComparisonStrategy.iterableContains(duplicates, "Merry")).isTrue();
assertThat(standardComparisonStrategy.iterableContains(duplicates, null)).isTrue();
void should_return_existing_duplicates_in_order() {
// GIVEN
List<String> list = list("Merry", "Frodo", null, null, "Merry", "Sam", "Frodo");
// WHEN
@SuppressWarnings("unchecked")
Iterable<Object> duplicates = (Iterable<Object>) standardComparisonStrategy.duplicatesFrom(list);
// THEN
then(duplicates).containsExactly(null, "Merry", "Frodo");
}

@Test
void should_return_existing_duplicates_array() {
List<String[]> list = newArrayList(array("Merry"), array("Frodo"), new String[] { null }, new String[] { null },
array("Merry"), array("Sam"), array("Frodo"));
Iterable<?> duplicates = standardComparisonStrategy.duplicatesFrom(list);

assertThat(standardComparisonStrategy.iterableContains(duplicates, new String[] { null })).as("must contains null").isTrue();
assertThat(standardComparisonStrategy.iterableContains(duplicates, array("Frodo"))).as("must contains Frodo").isTrue();
assertThat(standardComparisonStrategy.iterableContains(duplicates, array("Merry"))).as("must contains Merry").isTrue();
assertThat(sizeOf(duplicates)).isEqualTo(3);
// GIVEN
List<String[]> list = list(array("Merry"), array("Frodo"), new String[] { null }, new String[] { null },
array("Merry"), array("Sam"), array("Frodo"));
// WHEN
@SuppressWarnings("unchecked")
Iterable<String[]> duplicates = (Iterable<String[]>) standardComparisonStrategy.duplicatesFrom(list);
// THEN
then(duplicates).containsExactly(new String[] { null }, array("Merry"), array("Frodo"));
}

@Test
void should_not_return_any_duplicates() {
Iterable<?> duplicates = standardComparisonStrategy.duplicatesFrom(newArrayList("Frodo", "Sam", "Gandalf"));
assertThat(isNullOrEmpty(duplicates)).isTrue();
// GIVEN
Iterable<String> hobbits = list("Frodo", "Sam", "Gandalf");
// WHEN
Iterable<?> duplicates = standardComparisonStrategy.duplicatesFrom(hobbits);
// THEN
then(duplicates).isEmpty();
}

@Test
void should_not_return_any_duplicates_if_collection_is_empty() {
Iterable<?> duplicates = standardComparisonStrategy.duplicatesFrom(new ArrayList<>());
assertThat(isNullOrEmpty(duplicates)).isTrue();
// GIVEN
Iterable<String> emptyIterable = list();
// WHEN
Iterable<?> duplicates = standardComparisonStrategy.duplicatesFrom(emptyIterable);
// THEN
then(duplicates).isEmpty();
}

@Test
void should_not_return_any_duplicates_if_collection_is_null() {
// WHEN
Iterable<?> duplicates = standardComparisonStrategy.duplicatesFrom(null);
assertThat(isNullOrEmpty(duplicates)).isTrue();
// THEN
then(duplicates).isEmpty();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,22 @@
*/
package org.assertj.core.internal.throwables;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.error.ShouldHaveCauseExactlyInstance.shouldHaveCauseExactlyInstance;
import static org.assertj.core.test.TestData.someInfo;
import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
import static org.assertj.core.util.FailureMessages.actualIsNull;
import static org.mockito.Mockito.verify;

import org.assertj.core.api.AssertionInfo;
import org.assertj.core.internal.ThrowablesBaseTest;
import org.junit.jupiter.api.Test;

/**
* Tests for
* {@link org.assertj.core.internal.Throwables#assertHasCauseExactlyInstanceOf(org.assertj.core.api.AssertionInfo, Throwable, Class)}
* .
*
*
* @author Jean-Christophe Gay
*/
class Throwables_assertHasCauseExactlyInstanceOf_Test extends ThrowablesBaseTest {
Expand All @@ -43,51 +41,55 @@ void should_pass_if_cause_is_exactly_instance_of_expected_type() {

@Test
void should_fail_if_actual_is_null() {
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> throwables.assertHasCauseExactlyInstanceOf(someInfo(), null,
IllegalArgumentException.class))
.withMessage(actualIsNull());
// GIVEN
Throwable actual = null;
// WHEN
AssertionError error = expectAssertionError(() -> throwables.assertHasCauseExactlyInstanceOf(INFO, actual,
IllegalArgumentException.class));
// THEN
then(error).hasMessage(actualIsNull());
}

@Test
void should_throw_NullPointerException_if_given_type_is_null() {
assertThatNullPointerException().isThrownBy(() -> throwables.assertHasCauseExactlyInstanceOf(someInfo(),
throwableWithCause,
null))
.withMessage("The given type should not be null");
// GIVEN
Class<? extends Throwable> type = null;
// WHEN
Throwable throwable = catchThrowable(() -> throwables.assertHasCauseExactlyInstanceOf(INFO, throwableWithCause, type));
// THEN
then(throwable).isInstanceOf(NullPointerException.class)
.hasMessage("The given type should not be null");
}

@Test
void should_fail_if_actual_has_no_cause() {
AssertionInfo info = someInfo();
// GIVEN
Class<NullPointerException> expectedCauseType = NullPointerException.class;

Throwable error = catchThrowable(() -> throwables.assertHasCauseExactlyInstanceOf(info, actual, expectedCauseType));

assertThat(error).isInstanceOf(AssertionError.class);
verify(failures).failure(info, shouldHaveCauseExactlyInstance(actual, expectedCauseType));
// WHEN
expectAssertionError(() -> throwables.assertHasCauseExactlyInstanceOf(INFO, actual, expectedCauseType));
// THEN
verify(failures).failure(INFO, shouldHaveCauseExactlyInstance(actual, expectedCauseType));
}

@Test
void should_fail_if_cause_is_not_instance_of_expected_type() {
AssertionInfo info = someInfo();
// GIVEN
Class<NullPointerException> expectedCauseType = NullPointerException.class;

Throwable error = catchThrowable(() -> throwables.assertHasCauseExactlyInstanceOf(info, throwableWithCause,
expectedCauseType));

assertThat(error).isInstanceOf(AssertionError.class);
verify(failures).failure(info, shouldHaveCauseExactlyInstance(throwableWithCause, expectedCauseType));
// WHEN
expectAssertionError(() -> throwables.assertHasCauseExactlyInstanceOf(INFO, throwableWithCause,
expectedCauseType));
// THEN
verify(failures).failure(INFO, shouldHaveCauseExactlyInstance(throwableWithCause, expectedCauseType));
}

@Test
void should_fail_if_cause_is_not_exactly_instance_of_expected_type() {
AssertionInfo info = someInfo();
// GIVEN
Class<RuntimeException> expectedCauseType = RuntimeException.class;

Throwable error = catchThrowable(() -> throwables.assertHasCauseExactlyInstanceOf(info, throwableWithCause,
expectedCauseType));

assertThat(error).isInstanceOf(AssertionError.class);
verify(failures).failure(info, shouldHaveCauseExactlyInstance(throwableWithCause, expectedCauseType));
// WHEN
expectAssertionError(() -> throwables.assertHasCauseExactlyInstanceOf(INFO, throwableWithCause,
expectedCauseType));
// THEN
verify(failures).failure(INFO, shouldHaveCauseExactlyInstance(throwableWithCause, expectedCauseType));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.newLinkedHashSet;
import static java.util.Objects.requireNonNull;
import static org.assertj.core.error.ShouldBeEmpty.shouldBeEmpty;
import static org.assertj.core.error.ShouldContain.shouldContain;
import static org.assertj.core.error.ShouldContainOnly.shouldContainOnly;
import static org.assertj.core.error.ShouldHaveSize.shouldHaveSize;
import static org.assertj.core.error.ShouldNotBeEmpty.shouldNotBeEmpty;
import static org.assertj.core.error.ShouldNotContainKeys.shouldNotContainKeys;
import static org.assertj.guava.error.ShouldContainKeys.shouldContainKeys;
import static org.assertj.guava.error.ShouldContainValues.shouldContainValues;
import static org.assertj.guava.util.ExceptionUtils.throwIllegalArgumentExceptionIfTrue;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

Expand Down Expand Up @@ -313,4 +316,75 @@ public final MultimapAssert<K, V> containsAllEntriesOf(Multimap<? extends K, ? e
throw assertionError(shouldContain(actual, other, entriesNotFoundInActual));
}

/**
* Verifies that the actual multimap does not contain the given key.
* <p>
* Examples:
* <pre><code class='java'> Multimap&lt;Ring, TolkienCharacter&gt; elvesRingBearers = HashMultimap.create();
* elvesRingBearers.put(nenya, galadriel);
* elvesRingBearers.put(narya, gandalf);
* elvesRingBearers.put(vilya, elrond);
*
* // assertion will pass
* assertThat(elvesRingBearers).doesNotContainKey(oneRing);
*
* // assertion will fail
* assertThat(elvesRingBearers).doesNotContainKey(vilya);</code></pre>
*
* @param key the given key
* @return {@code this} assertions object
* @throws AssertionError if the actual map is {@code null}.
* @throws AssertionError if the actual map contains the given key.
* @since 3.26.0
*/
public MultimapAssert<K, V> doesNotContainKey(K key) {
return doesNotContainKeys(key);
}

/**
* Verifies that the actual multimap does not contain any of the given keys.
* <p>
* Examples:
* <pre><code class='java'> Multimap&lt;Ring, TolkienCharacter&gt; elvesRingBearers = HashMultimap.create();
* elvesRingBearers.put(nenya, galadriel);
* elvesRingBearers.put(narya, gandalf);
* elvesRingBearers.put(vilya, elrond);
*
* // assertion will pass
* assertThat(elvesRingBearers).doesNotContainKeys(oneRing, someManRing);
*
* // assertions will fail
* assertThat(elvesRingBearers).doesNotContainKeys(vilya, nenya);
* assertThat(elvesRingBearers).doesNotContainKeys(vilya, oneRing);</code></pre>
*
* @param keys the given keys
* @return {@code this} assertions object
* @throws AssertionError if the actual map is {@code null}.
* @throws AssertionError if the actual map contains the given key.
* @throws NullPointerException if the varargs of keys is null
* @since 3.26.0
*/
public MultimapAssert<K, V> doesNotContainKeys(K... keys) {
isNotNull();
assertDoesNotContainKeys(keys);
return this;
}

private void assertDoesNotContainKeys(K[] keys) {
requireNonNull(keys, "The array of keys to look for should not be null");
Set<K> foundKeys = findKeys(actual, keys);
if (!foundKeys.isEmpty()) throw assertionError(shouldNotContainKeys(actual, foundKeys));
}

private static <K> Set<K> findKeys(Multimap<K, ?> actual, K[] expectedKeys) {
// Stream API avoided for performance reasons
Set<K> foundKeys = new LinkedHashSet<>();
for (K expectedKey : expectedKeys) {
if (actual.containsKey(expectedKey)) {
foundKeys.add(expectedKey);
}
}
return foundKeys;
}

}

0 comments on commit 6852811

Please sign in to comment.