diff --git a/README.md b/README.md new file mode 100644 index 0000000..cf76cca --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# AssertJ Eclipse Collections [![Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip) + +[![CI](https://github.com/assertj/assertj/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/assertj/assertj/actions/workflows/main.yml?query=branch%3Amain) diff --git a/pom.xml b/pom.xml index 7658305..9fefaee 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,14 @@ + + + mattbertolini + Matt Bertolini + https://github.com/mattbertolini + + + scm:git:https://github.com/assertj/assertj-eclipse-collections.git scm:git:https://github.com/assertj/assertj-eclipse-collections.git @@ -31,9 +39,10 @@ 3.27.3 + 11 13.0.0 - 5.11.4 + 5.12.1 @@ -46,10 +55,16 @@ org.eclipse.collections - eclipse-collections-api + eclipse-collections ${eclipse-collections.version} provided + + org.opentest4j + opentest4j + provided + true + org.junit.jupiter diff --git a/src/main/java/org/assertj/eclipse/collections/Main.java b/src/main/java/org/assertj/eclipse/collections/Main.java deleted file mode 100644 index 05edd14..0000000 --- a/src/main/java/org/assertj/eclipse/collections/Main.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * Copyright 2025-2025 the original author or authors. - */ -package org.assertj.eclipse.collections; - -/** - * Main - * @see org.assertj.core.api.Assertions - */ -public class Main { - - /** - * main - * - * @param args args - */ - public static void main(String[] args) { - System.out.println("Hello, World!"); - } - - private Main() { - } - -} diff --git a/src/main/java/org/assertj/eclipse/collections/api/Assertions.java b/src/main/java/org/assertj/eclipse/collections/api/Assertions.java new file mode 100644 index 0000000..21cf91f --- /dev/null +++ b/src/main/java/org/assertj/eclipse/collections/api/Assertions.java @@ -0,0 +1,43 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api; + +import org.assertj.core.util.CheckReturnValue; +import org.assertj.eclipse.collections.api.multimap.MultimapAssert; +import org.eclipse.collections.api.multimap.Multimap; + +/** + * Entry point for assertion methods for the Eclipse Collections library. Each method in this class is a static factory + * for a type-specific assertion object. + */ +@CheckReturnValue +public class Assertions { + /** + * Creates a new {@link Assertions}. + */ + protected Assertions() { + // Do nothing + } + + /** + * Creates a new instance of {@link MultimapAssert}. + * + * @param actual the actual value. + * @return the created assertion object. + * @param The type of keys in the BagMultimap + * @param The type of values in the BagMultimap + */ + public static MultimapAssert assertThat(Multimap actual) { + return new MultimapAssert<>(actual); + } +} diff --git a/src/main/java/org/assertj/eclipse/collections/api/BDDAssertions.java b/src/main/java/org/assertj/eclipse/collections/api/BDDAssertions.java new file mode 100644 index 0000000..719f656 --- /dev/null +++ b/src/main/java/org/assertj/eclipse/collections/api/BDDAssertions.java @@ -0,0 +1,43 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api; + +import org.assertj.core.util.CheckReturnValue; +import org.assertj.eclipse.collections.api.multimap.MultimapAssert; +import org.eclipse.collections.api.multimap.Multimap; + +/** + * Behavior-driven development style entry point for assertion methods for the Eclipse Collections library. Each method + * in this class is a static factory for a type-specific assertion object. + */ +@CheckReturnValue +public class BDDAssertions extends Assertions { + /** + * Creates a new {@link BDDAssertions}. + */ + protected BDDAssertions() { + // Do nothing + } + + /** + * Creates a new instance of {@link MultimapAssert}. + * + * @param actual the actual value. + * @return the created assertion object. + * @param The type of keys in the BagMultimap + * @param The type of values in the BagMultimap + */ + public static MultimapAssert then(Multimap actual) { + return assertThat(actual); + } +} diff --git a/src/main/java/org/assertj/eclipse/collections/api/EclipseCollectionsSoftAssertionsProvider.java b/src/main/java/org/assertj/eclipse/collections/api/EclipseCollectionsSoftAssertionsProvider.java new file mode 100644 index 0000000..e9b7cb8 --- /dev/null +++ b/src/main/java/org/assertj/eclipse/collections/api/EclipseCollectionsSoftAssertionsProvider.java @@ -0,0 +1,37 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api; + +import org.assertj.core.api.SoftAssertionsProvider; +import org.assertj.core.util.CheckReturnValue; +import org.assertj.eclipse.collections.api.multimap.MultimapAssert; +import org.eclipse.collections.api.multimap.Multimap; + +/** + * Soft assertions implementations for Eclipse Collections types. + */ +@CheckReturnValue +public interface EclipseCollectionsSoftAssertionsProvider extends SoftAssertionsProvider { + /** + * Creates a new, proxied instance of a {@link MultimapAssert} + * + * @param actual the path + * @return the created assertion object + * @param The type of keys in the actual BagMultimap + * @param The type of values in the actual BagMultimap + */ + @SuppressWarnings("unchecked") + default MultimapAssert assertThat(Multimap actual) { + return this.proxy(MultimapAssert.class, Multimap.class, actual); + } +} diff --git a/src/main/java/org/assertj/eclipse/collections/api/SoftAssertions.java b/src/main/java/org/assertj/eclipse/collections/api/SoftAssertions.java new file mode 100644 index 0000000..abc0c64 --- /dev/null +++ b/src/main/java/org/assertj/eclipse/collections/api/SoftAssertions.java @@ -0,0 +1,44 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api; + +import org.assertj.core.api.AbstractSoftAssertions; +import org.assertj.core.api.SoftAssertionsProvider; +import org.opentest4j.MultipleFailuresError; + +import java.util.function.Consumer; + +/** + * A soft assertions provider for Eclipse Collections assertions + */ +public class SoftAssertions extends AbstractSoftAssertions implements EclipseCollectionsSoftAssertionsProvider { + /** + * Creates a new {@link SoftAssertions}. + */ + public SoftAssertions() { + // Do nothing + } + + /** + * Convenience method for calling {@link EclipseCollectionsSoftAssertionsProvider#assertSoftly} for these assertion + * types. Equivalent to {@code SoftAssertion.assertSoftly(SoftAssertions.class, softly)}. + * + * @param softly the Consumer containing the code that will make the soft assertions. + * Takes one parameter (the SoftAssertions instance used to make the assertions). + * @throws MultipleFailuresError if possible or SoftAssertionError if any proxied assertion objects threw an {@link + * AssertionError} + */ + public static void assertSoftly(Consumer softly) { + SoftAssertionsProvider.assertSoftly(SoftAssertions.class, softly); + } +} diff --git a/src/main/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert.java b/src/main/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert.java new file mode 100644 index 0000000..0b69d65 --- /dev/null +++ b/src/main/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert.java @@ -0,0 +1,555 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static java.util.Objects.requireNonNull; +import static org.assertj.core.error.ShouldBeEmpty.shouldBeEmpty; +import static org.assertj.core.error.ShouldBeNullOrEmpty.shouldBeNullOrEmpty; +import static org.assertj.core.error.ShouldContain.shouldContain; +import static org.assertj.core.error.ShouldContainKey.shouldContainKey; +import static org.assertj.core.error.ShouldContainKeys.shouldContainKeys; +import static org.assertj.core.error.ShouldContainOnly.shouldContainOnly; +import static org.assertj.core.error.ShouldContainValue.shouldContainValue; +import static org.assertj.core.error.ShouldContainValues.shouldContainValues; +import static org.assertj.core.error.ShouldHaveSize.shouldHaveSize; +import static org.assertj.core.error.ShouldHaveSizeBetween.shouldHaveSizeBetween; +import static org.assertj.core.error.ShouldHaveSizeGreaterThan.shouldHaveSizeGreaterThan; +import static org.assertj.core.error.ShouldHaveSizeGreaterThanOrEqualTo.shouldHaveSizeGreaterThanOrEqualTo; +import static org.assertj.core.error.ShouldHaveSizeLessThan.shouldHaveSizeLessThan; +import static org.assertj.core.error.ShouldHaveSizeLessThanOrEqualTo.shouldHaveSizeLessThanOrEqualTo; +import static org.assertj.core.error.ShouldNotBeEmpty.shouldNotBeEmpty; +import static org.assertj.eclipse.collections.error.ShouldHaveDistinctSize.shouldHaveDistinctSize; +import static org.assertj.eclipse.collections.error.ShouldHaveDistinctSizeGreaterThan.shouldHaveDistinctSizeGreaterThan; +import static org.assertj.eclipse.collections.error.ShouldHaveDistinctSizeGreaterThanOrEqualTo.shouldHaveDistinctSizeGreaterThanOrEqualTo; + +import java.util.Map; + +import org.assertj.core.api.AbstractAssert; +import org.assertj.core.api.Condition; +import org.assertj.core.error.GroupTypeDescription; +import org.eclipse.collections.api.RichIterable; +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.api.multimap.Multimap; +import org.eclipse.collections.api.partition.list.PartitionMutableList; +import org.eclipse.collections.api.tuple.Pair; +import org.eclipse.collections.impl.tuple.Tuples; + +/** + * Base class for all implementations of assertions for {@link Multimap}. + * + * @param the type of keys in the Multimap. + * @param the type of values in the Multimap. + */ +public class MultimapAssert extends AbstractAssert, Multimap> { + + /** + * Creates a new {@link MultimapAssert}. + * + * @param actual The actual Multimap to assert against + */ + public MultimapAssert(Multimap actual) { + super(actual, MultimapAssert.class); + } + + /** + * Verifies that the actual {@link Multimap} contains the given entries. Entries are given in the form of {@link + * Pair} objects. + *

+ * Example: + *

{@code
+   *     Multimap multimap = Multimaps.mutable.list.with("Key1", "Value1", "Key2", "Value2");
+   *
+   *     // assertion will pass
+   *     assertThat(multimap).contains(Tuples.pair("Key1", "Value1"), Tuples.pair("Key2", "Value2"));
+   *
+   *     // assertion will fail
+   *     assertThat(multimap).contains(Tuples.pair("Key1", "Value3"), Tuples.pair("Key2", "Value1"));
+   *     }
+ * + * @param entries the entries that are expected to be present in the {@link Multimap}. + * @return this assertion object for method chaining. + * @throws AssertionError if the actual {@link Multimap} does not contain the given entries + */ + @SafeVarargs + public final MultimapAssert contains(Pair... entries) { + return this.containsForProxy(Lists.mutable.of(entries)); + } + + /** + * Verifies that the actual {@code Multimap} contains the provided entries. Entries are provided as + * an array of {@code Map.Entry} objects. + * + * @param entries the entries that are expected to be contained within the {@code Multimap}. + * @return this assertion object for method chaining. + * @throws AssertionError if the actual {@code Multimap} does not contain one or more of the specified entries. + */ + @SafeVarargs + public final MultimapAssert contains(Map.Entry... entries) { + MutableList> pairs = Lists.mutable.of(entries).collect(Tuples::pairFrom); + return this.containsForProxy(pairs); + } + + /** + * Verifies that the actual {@code Multimap} contains the provided entries. + * + * @param entries the list of entries that are expected to be contained within the {@code Multimap}. + * @return this assertion object for method chaining. + * @throws AssertionError if the actual {@code Multimap} does not contain one or more of the specified entries. + */ + protected MultimapAssert containsForProxy(MutableList> entries) { + this.isNotNull(); + MutableList> entriesNotFound = entries + .reject(entry -> this.actual.containsKeyAndValue(entry.getOne(), entry.getTwo())); + if (entriesNotFound.isEmpty()) { + return this.myself; + } + throw this.assertionError(shouldContain(this.actual, entries, entriesNotFound)); + } + + /** + * Verifies that the actual {@link Multimap} contains the given key-value entry. + * + * @param key the key that is expected to be present in the {@link Multimap}. + * @param value the value that is expected to be associated with the given key in the {@link Multimap}. + * @return this assertion object for method chaining. + * @throws AssertionError if the actual {@link Multimap} does not contain the given key-value entry. + * @see #contains(Pair[]) + * @see #contains(Map.Entry[]) + */ + public MultimapAssert containsEntry(KEY key, VALUE value) { + return this.contains(Tuples.pair(key, value)); + } + + /** + * Verifies that the actual {@link Multimap} contains the given keys. + *

+ * Example: + *

{@code
+   * Multimap multimap = Multimaps.mutable.list.with("Key1", "Value1", "Key2", "Value2");
+   *
+   * // assertion will pass
+   * assertThat(multimap).containsKeys("Key1", "Key2");
+   *
+   * // assertion will fail
+   * assertThat(multimap).containsKeys("Key3");
+   * }
+ * + * @param keys the keys that are expected to be present in the {@link Multimap}. + * @return this assertion object for method chaining. + * @throws AssertionError if the actual {@link Multimap} does not contain the given keys. + */ + public MultimapAssert containsKeys(KEY... keys) { + this.isNotNull(); + MutableList keysNotFound = Lists.mutable.of(keys).reject(this.actual::containsKey); + if (keysNotFound.isEmpty()) { + return this.myself; + } + throw this.assertionError(shouldContainKeys(this.actual, keysNotFound.toSet())); + } + + /** + * Verifies that the map contains only the given entries. + * + * @param entries the array of map entries to validate against the map + * @return this assertion object for method chaining + * @throws AssertionError if the actual {@link Multimap} does not contain only the given entries. + */ + @SafeVarargs + public final MultimapAssert containsOnly(Map.Entry... entries) { + MutableList> pairs = Lists.mutable.of(entries).collect(Tuples::pairFrom); + return this.containsOnlyForProxy(pairs); + } + + /** + * Verifies that the current object contains only the specified pairs of key-value entries. + * + * @param entries the pairs of key-value entries to check against + * @return this assertion object for method chaining + * @throws AssertionError if the actual {@link Multimap} does not contain only the given entries. + */ + @SafeVarargs + public final MultimapAssert containsOnly(Pair... entries) { + return this.containsOnlyForProxy(Lists.mutable.of(entries)); + } + + /** + * Verifies that the current object contains only the specified list of pairs of key-value entries. + * + * @param entries the list of pairs of key-value entries to check against + * @return this assertion object for method chaining + * @throws AssertionError if the actual {@link Multimap} does not contain only the given entries. + */ + protected MultimapAssert containsOnlyForProxy(MutableList> entries) { + this.isNotNull(); + PartitionMutableList> partition = entries + .partition(entry -> this.actual.containsKeyAndValue(entry.getOne(), entry.getTwo())); + + MutableList> found = partition.getSelected(); + MutableList> notFound = partition.getRejected(); + RichIterable> notExpected = this.actual.keyValuePairsView().reject(found::contains); + + if (notFound.isEmpty() && notExpected.isEmpty()) { + return this.myself; + } + + GroupTypeDescription groupTypeDescription = new GroupTypeDescription("multimap", "multimap entries"); + throw this.assertionError(shouldContainOnly(this.actual, entries, notFound, notExpected, groupTypeDescription)); + } + + /** + * Verifies that the actual map contains the given values. + * + * @param values the values expected to be present in the actual map + * @return the current assertion object for method chaining + * @throws AssertionError if the actual map does not contain the given values + */ + public MultimapAssert containsValues(VALUE... values) { + this.isNotNull(); + MutableList valuesNotFound = Lists.mutable.of(values).reject(this.actual::containsValue); + if (valuesNotFound.isEmpty()) { + return this.myself; + } + throw this.assertionError(shouldContainValues(this.actual, valuesNotFound.toSet())); + } + + /** + * Verifies that the actual {@code Multimap} has the expected number of distinct keys. + * + * @param expected the expected number of distinct keys in the {@code Multimap}. + * @return this assertion object for method chaining. + * @throws AssertionError if the actual number of distinct keys in the {@code Multimap} does not match the expected size. + */ + public MultimapAssert hasDistinctSize(int expected) { + this.isNotNull(); + int actualSize = this.actual.sizeDistinct(); + if (actualSize == expected) { + return this.myself; + } + throw this.assertionError(shouldHaveDistinctSize(this.actual, actualSize, expected)); + } + + /** + * Verifies that the distinct size of the {@link Multimap} is greater than the specified boundary. + * + * @param boundary the size that the actual number of distinct keys should exceed. + * @return this assertion object for method chaining. + * @throws AssertionError if the actual distinct size of the {@link Multimap} is not greater than the specified boundary. + */ + public MultimapAssert hasDistinctSizeGreaterThan(int boundary) { + this.isNotNull(); + int actualSize = this.actual.sizeDistinct(); + if (actualSize > boundary) { + return this.myself; + } + throw this.assertionError(shouldHaveDistinctSizeGreaterThan(this.actual, actualSize, boundary)); + } + + /** + * Verifies that the distinct size of the {@link Multimap} is greater than or equal to the specified boundary. + * + * @param boundary the minimum distinct size to compare the Multimap against + * @return this assertion for method chaining + * @throws AssertionError if the distinct size of the collection is less than the specified boundary + */ + public MultimapAssert hasDistinctSizeGreaterThanOrEqualTo(int boundary) { + this.isNotNull(); + int actualSize = this.actual.sizeDistinct(); + if (actualSize >= boundary) { + return this.myself; + } + throw this.assertionError(shouldHaveDistinctSizeGreaterThanOrEqualTo(this.actual, actualSize, boundary)); + } + + /** + * Verifies that at least one key in the actual {@link Multimap} satisfies the given condition. + * + * @param keyCondition the condition to evaluate the keys against; must not be null. + * @return this assertion object for method chaining. + * @throws NullPointerException if the provided condition is null. + * @throws AssertionError if none of the keys in the {@link Multimap} satisfy the given condition. + */ + public MultimapAssert hasKeySatisfying(Condition keyCondition) { + this.isNotNull(); + requireNonNull(keyCondition, "The condition to evaluate should not be null"); + + if (this.actual.keysView().anySatisfy(keyCondition::matches)) { + return this.myself; + } + + throw this.assertionError(shouldContainKey(this.actual, keyCondition)); + } + + /** + * Verifies that the number of key-value entry pairs in the {@link Multimap} is equal to the given one. + *

+ * Example: + *

{@code
+   * Multimap multimap = Multimaps.mutable.list.with("Key", "Value1", "Key", "Value2");
+   *
+   * // assertion will pass
+   * assertThat(multimap).hasSize(2);
+   *
+   * // assertions will fail
+   * assertThat(multimap).hasSize(0);
+   * assertThat(multimap).hasSize(1);
+   * }
+ * + * @param expected the expected size of the {@link Multimap}. + * @return {@code this} assertion object. + * @throws AssertionError if the actual size of the {@link Multimap} is not equal to the expected size. + */ + public MultimapAssert hasSize(int expected) { + this.isNotNull(); + int actualSize = this.actual.size(); + if (actualSize == expected) { + return this.myself; + } + throw this.assertionError(shouldHaveSize(this.actual, actualSize, expected)); + } + + /** + * Verifies that the number of key-value entry pairs in the {@link Multimap} is between the given boundaries + * (inclusive). + *

+ * Example: + *

{@code
+   * Multimap multimap = Multimaps.mutable.list.with("Key1", "Value1", "Key1", "Value2", "Key2", "Value3");
+   *
+   * // assertion will pass
+   * assertThat(multimap).hasSizeBetween(1, 4)
+   *                     .hasSizeBetween(2, 3);
+   *
+   * // assertions will fail
+   * assertThat(multimap).hasSizeBetween(4, 5);
+   * }
+ * + * @param lowerBoundary the lower boundary compared to which actual size should be greater than or equal to. + * @param higherBoundary the higher boundary compared to which actual size should be less than or equal to. + * @return {@code this} assertion object. + * @throws AssertionError if the actual size of the {@link Multimap} is not between the given boundaries. + */ + public MultimapAssert hasSizeBetween(int lowerBoundary, int higherBoundary) { + this.isNotNull(); + int actualSize = this.actual.size(); + if (actualSize >= lowerBoundary && actualSize <= higherBoundary) { + return this.myself; + } + throw this.assertionError(shouldHaveSizeBetween(this.actual, actualSize, lowerBoundary, higherBoundary)); + } + + /** + * Verifies that the number of key-value entry pairs in the {@link Multimap} is greater than the specified boundary. + *

+ * Example: + *

{@code
+   * Multimap multimap = Multimaps.mutable.list.with("Key1", "Value1", "Key1", "Value2", "Key2", "Value3");
+   *
+   * // assertion will pass
+   * assertThat(multimap).hasSizeGreaterThan(1);
+   *
+   * // assertions will fail
+   * assertThat(multimap).hasSizeGreaterThan(3);
+   * assertThat(multimap).hasSizeGreaterThan(4);
+   * }
+ * + * @param boundary the size that the actual number of key-value pairs should exceed. + * @return {@code this} assertion object. + * @throws AssertionError if the actual size of the {@link Multimap} is not greater than the specified boundary. + */ + public MultimapAssert hasSizeGreaterThan(int boundary) { + this.isNotNull(); + int actualSize = this.actual.size(); + if (actualSize > boundary) { + return this.myself; + } + throw this.assertionError(shouldHaveSizeGreaterThan(this.actual, actualSize, boundary)); + } + + /** + * Verifies that the number of key-value entry pairs in the {@link Multimap} is greater than or equal to the + * boundary. + *

+ * Example: + *

{@code
+   * Multimap multimap = Multimaps.mutable.list.with("Key1", "Value1", "Key2", "Value2");
+   *
+   * // assertions will pass
+   * assertThat(multimap).hasSizeGreaterThanOrEqualTo(1)
+   *                     .hasSizeGreaterThanOrEqualTo(2);
+   *
+   * // assertions will fail
+   * assertThat(multimap).hasSizeGreaterThanOrEqualTo(3);
+   * assertThat(multimap).hasSizeGreaterThanOrEqualTo(5);
+   * }
+ * + * @param boundary the minimum size (inclusive) the {@link Multimap} should have. + * @return {@code this} assertion object for method chaining. + * @throws AssertionError if the actual size of the {@link Multimap} is less than the expected size. + */ + public MultimapAssert hasSizeGreaterThanOrEqualTo(int boundary) { + this.isNotNull(); + int actualSize = this.actual.size(); + if (actualSize >= boundary) { + return this.myself; + } + throw this.assertionError(shouldHaveSizeGreaterThanOrEqualTo(this.actual, actualSize, boundary)); + } + + /** + * Verifies that the number of key-value entry pairs in the {@link Multimap} is less than the boundary. + *

+ * Example: + *

{@code
+   * Multimap multimap = Multimaps.mutable.list.with("Key1", "Value1", "Key2", "Value2");
+   *
+   * // assertion will pass
+   * assertThat(multimap).hasSizeLessThan(3);
+   *
+   * // assertions will fail
+   * assertThat(multimap).hasSizeLessThan(1);
+   * assertThat(multimap).hasSizeLessThan(2);
+   * }
+ * + * @param boundary the maximum size (exclusive) the {@link Multimap} should have. + * @return {@code this} assertion object. + * @throws AssertionError if the actual size of the {@link Multimap} is not less than the expected size. + */ + public MultimapAssert hasSizeLessThan(int boundary) { + this.isNotNull(); + int actualSize = this.actual.size(); + if (actualSize < boundary) { + return this.myself; + } + throw this.assertionError(shouldHaveSizeLessThan(this.actual, actualSize, boundary)); + } + + /** + * Verifies that the number of key-value entry pairs in the {@link Multimap} is less than or equal to the boundary. + *

+ * Example: + *

{@code
+   * Multimap multimap = Multimaps.mutable.list.with("Key1", "Value1", "Key2", "Value2");
+   *
+   * // assertion will pass
+   * assertThat(multimap).hasSizeLessThanOrEqualTo(2)
+   *                     .hasSizeLessThanOrEqualTo(3);
+   *
+   * // assertions will fail
+   * assertThat(multimap).hasSizeLessThanOrEqualTo(0);
+   * assertThat(multimap).hasSizeLessThanOrEqualTo(1);
+   * }
+ * + * @param boundary the maximum expected size of the {@link Multimap}. + * @return {@code this} assertion object for method chaining. + * @throws AssertionError if the actual size of the {@link Multimap} is greater than the expected size. + */ + public MultimapAssert hasSizeLessThanOrEqualTo(int boundary) { + this.isNotNull(); + int actualSize = this.actual.size(); + if (actualSize <= boundary) { + return this.myself; + } + throw this.assertionError(shouldHaveSizeLessThanOrEqualTo(this.actual, actualSize, boundary)); + } + + /** + * Verifies that at least one value in the actual {@link Multimap} satisfies the given condition. + * + * @param valueCondition the condition to evaluate the values against; must not be null. + * @return this assertion object for method chaining. + * @throws NullPointerException if the provided condition is null. + * @throws AssertionError if none of the values in the {@link Multimap} satisfy the given condition. + */ + public MultimapAssert hasValueSatisfying(Condition valueCondition) { + this.isNotNull(); + requireNonNull(valueCondition, "The condition to evaluate should not be null"); + + if (this.actual.valuesView().anySatisfy(valueCondition::matches)) { + return this.myself; + } + throw this.assertionError(shouldContainValue(this.actual, valueCondition)); + } + + /** + * Verifies that the {@link Multimap} is empty. + *

+ * Example: + *

{@code
+   * // assertion will pass
+   * assertThat(Multimaps.mutable.list.empty()).isEmpty();
+   *
+   * // assertion will fail
+   * Multimap multimap = Multimaps.mutable.list.with("Key", "Value");
+   * assertThat(multimap).isEmpty();
+   * }
+ * + * @throws AssertionError if the {@link Multimap} of values is not empty. + */ + public void isEmpty() { + this.isNotNull(); + if (!this.actual.isEmpty()) { + throw this.assertionError(shouldBeEmpty(this.actual)); + } + } + + /** + * Verifies that the {@link Multimap} is not empty. + *

+ * Example: + *

{@code
+   * // assertion will pass
+   * Multimap multimap = Multimaps.mutable.list.with("Key", "Value");
+   * assertThat(multimap).isNotEmpty();
+   *
+   * // assertion will fail
+   * assertThat(Multimaps.mutable.list.empty()).isNotEmpty();
+   * }
+ * + * @return this assertion object for method chaining + * @throws AssertionError if the {@link Multimap} of values is empty. + */ + public MultimapAssert isNotEmpty() { + this.isNotNull(); + if (!this.actual.isEmpty()) { + return this.myself; + } + throw this.assertionError(shouldNotBeEmpty()); + } + + /** + * Verifies that the {@link Multimap} is null or empty. + *

+ * Example: + *

{@code
+   * // assertions that will pass
+   * Multimap multimap = null;
+   * assertThat(multimap).isNullOrEmpty();
+   *
+   * Multimap emptyMultimap = Multimaps.mutable.list.empty();
+   * assertThat(emptyMultimap).isNullOrEmpty();
+   *
+   * // assertion will fail
+   * Multimap multimapWithElements = Multimaps.mutable.list.with("Key", "Value");
+   * assertThat(multimapWithElements).isNullOrEmpty();
+   * }
+ * + * @throws AssertionError if the {@link Multimap} is either null or empty. + */ + public void isNullOrEmpty() { + if (this.actual == null || this.actual.isEmpty()) { + return; + } + throw this.assertionError(shouldBeNullOrEmpty(this.actual)); + } +} diff --git a/src/main/java/org/assertj/eclipse/collections/error/ShouldHaveDistinctSize.java b/src/main/java/org/assertj/eclipse/collections/error/ShouldHaveDistinctSize.java new file mode 100644 index 0000000..1e9a28d --- /dev/null +++ b/src/main/java/org/assertj/eclipse/collections/error/ShouldHaveDistinctSize.java @@ -0,0 +1,39 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.error; + +import org.assertj.core.error.BasicErrorMessageFactory; +import org.assertj.core.error.ErrorMessageFactory; + +import static java.lang.String.format; + +/** + * Creates an error message indicating that an assertion that verifies that a value has certain distinct size failed. + */ +public class ShouldHaveDistinctSize extends BasicErrorMessageFactory { + /** + * Creates a new {@code ShouldHaveDistinctSize}. + * + * @param actual the actual value in the failed assertion. + * @param actualSize the distinct size of {@code actual}. + * @param expectedSize the expected size. + * @return the created {@code ErrorMessageFactory}. + */ + public static ErrorMessageFactory shouldHaveDistinctSize(Object actual, int actualSize, int expectedSize) { + return new ShouldHaveDistinctSize(actual, actualSize, expectedSize); + } + + private ShouldHaveDistinctSize(Object actual, int actualSize, int expectedSize) { + super(format("%nExpected distinct size: %s but was: %s in:%n%s", expectedSize, actualSize, "%s"), actual); + } +} diff --git a/src/main/java/org/assertj/eclipse/collections/error/ShouldHaveDistinctSizeGreaterThan.java b/src/main/java/org/assertj/eclipse/collections/error/ShouldHaveDistinctSizeGreaterThan.java new file mode 100644 index 0000000..bd41094 --- /dev/null +++ b/src/main/java/org/assertj/eclipse/collections/error/ShouldHaveDistinctSizeGreaterThan.java @@ -0,0 +1,43 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.error; + +import static java.lang.String.format; + +import org.assertj.core.error.BasicErrorMessageFactory; +import org.assertj.core.error.ErrorMessageFactory; + +/** + * Creates an error message indicating that an assertion that verifies a minimum distinct size failed. + */ +public class ShouldHaveDistinctSizeGreaterThan extends BasicErrorMessageFactory { + /** + * Creates a new {@link ShouldHaveDistinctSizeGreaterThan}. + * + * @param actual the actual value in the failed assertion. + * @param actualSize the size of {@code actual}. + * @param expectedMinSize the expected size. + * @return the created {@code ErrorMessageFactory}. + */ + public static ErrorMessageFactory shouldHaveDistinctSizeGreaterThan(Object actual, int actualSize, int expectedMinSize) { + return new ShouldHaveDistinctSizeGreaterThan(actual, actualSize, expectedMinSize); + } + + private ShouldHaveDistinctSizeGreaterThan(Object actual, int actualSize, int expectedSize) { + super(format("%n" + + "Expecting distinct size of:%n" + + " %%s%n" + + "to be greater than %s but was %s", expectedSize, actualSize), + actual); + } +} diff --git a/src/main/java/org/assertj/eclipse/collections/error/ShouldHaveDistinctSizeGreaterThanOrEqualTo.java b/src/main/java/org/assertj/eclipse/collections/error/ShouldHaveDistinctSizeGreaterThanOrEqualTo.java new file mode 100644 index 0000000..207bda6 --- /dev/null +++ b/src/main/java/org/assertj/eclipse/collections/error/ShouldHaveDistinctSizeGreaterThanOrEqualTo.java @@ -0,0 +1,44 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.error; + +import org.assertj.core.error.BasicErrorMessageFactory; +import org.assertj.core.error.ErrorMessageFactory; + +import static java.lang.String.format; + +/** + * Creates an error message indicating that an assertion verifying that the distinct size of a value + * is greater than or equal to a specified minimum size has failed. + */ +public class ShouldHaveDistinctSizeGreaterThanOrEqualTo extends BasicErrorMessageFactory { + /** + * Creates a new {@link ShouldHaveDistinctSizeGreaterThanOrEqualTo}. + * + * @param actual the actual value in the failed assertion. + * @param actualSize the size of {@code actual}. + * @param expectedMinSize the expected size. + * @return the created {@code ErrorMessageFactory}. + */ + public static ErrorMessageFactory shouldHaveDistinctSizeGreaterThanOrEqualTo(Object actual, int actualSize, int expectedMinSize) { + return new ShouldHaveDistinctSizeGreaterThanOrEqualTo(actual, actualSize, expectedMinSize); + } + + private ShouldHaveDistinctSizeGreaterThanOrEqualTo(Object actual, int actualSize, int expectedSize) { + super(format("%n" + + "Expecting distinct size of:%n" + + " %%s%n" + + "to be greater than or equal to %s but was %s", expectedSize, actualSize), + actual); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsEntry_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsEntry_Test.java new file mode 100644 index 0000000..9bf2ac7 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsEntry_Test.java @@ -0,0 +1,67 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.eclipse.collections.impl.tuple.Tuples.pair; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.eclipse.collections.api.tuple.Pair; +import org.eclipse.collections.impl.factory.Multimaps; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_ContainsEntry_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void passes(Multimap actual) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).containsEntry("ENT", "Reed")); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void failsEmpty(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsEntry("ENT", "Reed")) + .withMessageContaining("Expecting") + .withMessageContaining("to contain") + .withMessageContaining("but could not find the following element(s)"); + } + + @Test + void failsNullMultimap() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).containsEntry("ENT", "Reed")) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void failsMissingEntry(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsEntry("VOY", "Kes")) + .withMessageContaining("Expecting") + .withMessageContaining("to contain") + .withMessageContaining("but could not find the following element(s)"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void softAssertionPasses(Multimap actual) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).containsEntry("ENT", "Reed")); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsKeys_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsKeys_Test.java new file mode 100644 index 0000000..7bf5aa8 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsKeys_Test.java @@ -0,0 +1,64 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_ContainsKeys_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void passes(Multimap actual) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).containsKeys("TOS", "TNG", "DS9")); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void failsEmpty(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsKeys("TOS", "TNG", "DS9")) + .withMessageContaining("Expecting actual") + .withMessageContaining("{}") + .withMessageContaining("to contain keys"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void failsMissingKey(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsKeys("DIS")) + .withMessageContaining("Expecting actual") + .withMessageContaining("to contain key") + .withMessageContaining("DIS"); + } + + @Test + void failsNullMultimap() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).containsKeys("TOS", "TNG", "DS9")) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void softAssertionPasses(Multimap actual) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).containsKeys("TOS", "TNG", "DS9")); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsOnly_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsOnly_Test.java new file mode 100644 index 0000000..0e98b72 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsOnly_Test.java @@ -0,0 +1,185 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.eclipse.collections.impl.tuple.Tuples.pair; + +import java.util.Map; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.eclipse.collections.api.tuple.Pair; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_ContainsOnly_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#shipMultimaps") + void passesWithPairs(Multimap actual) { + Pair[] exactMatchPairs = new Pair[]{ + pair("TNG", "Enterprise"), + pair("DS9", "Deep Space Nine"), + pair("DS9", "Defiant"), + pair("VOY", "Voyager") + }; + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).containsOnly(exactMatchPairs)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#shipMultimaps") + void passesWithEntries(Multimap actual) { + Map.Entry[] exactMatchEntries = new Map.Entry[]{ + pair("TNG", "Enterprise").toEntry(), + pair("DS9", "Deep Space Nine").toEntry(), + pair("DS9", "Defiant").toEntry(), + pair("VOY", "Voyager").toEntry() + }; + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).containsOnly(exactMatchEntries)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#shipMultimaps") + void failsWhenAdditionalKeysOrValuesExistWithPair(Multimap actual) { + Pair[] partialMatchMissingPairs = new Pair[]{ + pair("TNG", "Enterprise"), + pair("DS9", "Defiant"), + pair("VOY", "Voyager") + }; + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsOnly(partialMatchMissingPairs)) + .withMessageContaining("to contain only") + .withMessageContaining("but the following multimap entries were unexpected"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#shipMultimaps") + void failsWhenAdditionalKeysOrValuesExistWithEntry(Multimap actual) { + Map.Entry[] partialMatchMissingEntries = new Map.Entry[]{ + pair("TNG", "Enterprise").toEntry(), + pair("DS9", "Defiant").toEntry(), + pair("VOY", "Voyager").toEntry() + }; + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsOnly(partialMatchMissingEntries)) + .withMessageContaining("to contain only") + .withMessageContaining("but the following multimap entries were unexpected"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#shipMultimaps") + void failsWhenEntryIsMissingWithPair(Multimap actual) { + Pair[] partialMatchExtraPairs = new Pair[]{ + pair("TOS", "Enterprise"), + pair("TNG", "Enterprise"), + pair("DS9", "Deep Space Nine"), + pair("DS9", "Defiant"), + pair("VOY", "Voyager") + }; + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsOnly(partialMatchExtraPairs)) + .withMessageContaining("to contain only") + .withMessageContaining("but could not find the following multimap entries"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#shipMultimaps") + void failsWhenEntryIsMissingWithEntry(Multimap actual) { + Map.Entry[] partialMatchExtraEntries = new Map.Entry[]{ + pair("TOS", "Enterprise").toEntry(), + pair("TNG", "Enterprise").toEntry(), + pair("DS9", "Deep Space Nine").toEntry(), + pair("DS9", "Defiant").toEntry(), + pair("VOY", "Voyager").toEntry() + }; + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsOnly(partialMatchExtraEntries)) + .withMessageContaining("to contain only") + .withMessageContaining("but could not find the following multimap entries"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void failsForEmptyMultimapWithPair(Multimap actual) { + Pair[] exactMatchPairs = new Pair[]{ + pair("TNG", "Enterprise"), + pair("DS9", "Deep Space Nine") + }; + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsOnly(exactMatchPairs)) + .withMessageContaining("to contain only") + .withMessageContaining("but could not find the following multimap entries"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void failsForEmptyMultimapWithEntry(Multimap actual) { + Map.Entry[] exactMatchEntries = new Map.Entry[]{ + pair("TNG", "Enterprise").toEntry(), + pair("DS9", "Deep Space Nine").toEntry() + }; + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsOnly(exactMatchEntries)) + .withMessageContaining("to contain only") + .withMessageContaining("but could not find the following multimap entries"); + } + + @Test + void failsForNullMultimapWithPair() { + Pair[] exactMatchPairs = new Pair[]{ + pair("TNG", "Enterprise"), + pair("DS9", "Deep Space Nine") + }; + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).containsOnly(exactMatchPairs)) + .withMessageContaining("Expecting actual not to be null"); + } + + @Test + void failsForNullMultimapWithEntry() { + Map.Entry[] exactMatchEntries = new Map.Entry[]{ + pair("TNG", "Enterprise").toEntry(), + pair("DS9", "Deep Space Nine").toEntry() + }; + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).containsOnly(exactMatchEntries)) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#shipMultimaps") + void softAssertionPassesWithPairs(Multimap actual) { + Pair[] exactMatchPairs = new Pair[]{ + pair("TNG", "Enterprise"), + pair("DS9", "Deep Space Nine"), + pair("DS9", "Defiant"), + pair("VOY", "Voyager") + }; + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).containsOnly(exactMatchPairs)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#shipMultimaps") + void softAssertionPassesWithEntries(Multimap actual) { + Map.Entry[] exactMatchEntries = new Map.Entry[]{ + pair("TNG", "Enterprise").toEntry(), + pair("DS9", "Deep Space Nine").toEntry(), + pair("DS9", "Defiant").toEntry(), + pair("VOY", "Voyager").toEntry() + }; + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).containsOnly(exactMatchEntries)); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsValues_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsValues_Test.java new file mode 100644 index 0000000..9a50f29 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_ContainsValues_Test.java @@ -0,0 +1,64 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_ContainsValues_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void passes(Multimap actual) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).containsValues("Kirk", "Picard", "Sisko", "Janeway", "Archer")); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void failsEmpty(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsValues("Kirk", "Picard", "Sisko", "Janeway", "Archer")) + .withMessageContaining("Expecting actual") + .withMessageContaining("{}") + .withMessageContaining("to contain values"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void failsMissingValue(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).containsValues("Kes")) + .withMessageContaining("Expecting actual") + .withMessageContaining("to contain value") + .withMessageContaining("Kes"); + } + + @Test + void failsNullMultimap() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).containsValues("Kirk", "Picard", "Sisko", "Janeway", "Archer")) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void softAssertionPasses(Multimap actual) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).containsValues("Kirk", "Picard", "Sisko", "Janeway", "Archer")); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_Contains_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_Contains_Test.java new file mode 100644 index 0000000..789cdd8 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_Contains_Test.java @@ -0,0 +1,123 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.eclipse.collections.impl.tuple.Tuples.pair; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import java.util.Map; +import java.util.stream.Stream; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.eclipse.collections.api.tuple.Pair; +import org.eclipse.collections.impl.tuple.Tuples; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_Contains_Test { + + @ParameterizedTest + @MethodSource("successfulPairTestCases") + void containsPairsPasses(Multimap actual, Pair[] expectedPairs) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).contains(expectedPairs)); + } + + @ParameterizedTest + @MethodSource("missingPairTestCases") + void containsPairsFails(Multimap actual, Pair missingPair) { + assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> + new MultimapAssert<>(actual).contains(missingPair)) + .withMessageContaining("Expecting") + .withMessageContaining("but could not find the following element(s)") + .withMessageContaining(missingPair.toString()); + } + + @Test + void nullActualWithPair() { + assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> + new MultimapAssert<>(null).contains(pair("TOS", "McCoy"))) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("successfulPairTestCases") + void softAssertionsWithPairPasses(Multimap actual, Pair[] expectedPairs) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).contains(expectedPairs)); + } + + @ParameterizedTest + @MethodSource("successfulMapEntryTestCases") + void containsEntriesPasses(Multimap actual, Map.Entry[] expectedEntries) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).contains(expectedEntries)); + } + + @ParameterizedTest + @MethodSource("missingMapEntryTestCases") + void containsEntriesFails(Multimap actual, Map.Entry missingEntry) { + assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> + new MultimapAssert<>(actual).contains(missingEntry)) + .withMessageContaining("Expecting") + .withMessageContaining("but could not find the following element(s)") + .withMessageContaining(Tuples.pairFrom(missingEntry).toString()); + } + + @Test + void nullActualWithEntry() { + assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> + new MultimapAssert<>(null).contains((Map.Entry) pair("TOS", "McCoy").toEntry())) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("successfulMapEntryTestCases") + void softAssertionsWithEntryPasses(Multimap actual, Map.Entry[] expectedEntries) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).contains(expectedEntries)); + } + + private static Stream successfulPairTestCases() { + return Stream.of( + arguments(MultimapTestData.mutableBagMultimap(), new Pair[]{pair("TOS", "McCoy"), pair("TNG", "Crusher")}), + arguments(MultimapTestData.mutableListMultimap(), new Pair[]{pair("TOS", "McCoy"), pair("TNG", "Crusher")}), + arguments(MultimapTestData.mutableSetMultimap(), new Pair[]{pair("TOS", "McCoy"), pair("TNG", "Crusher")}) + ); + } + + private static Stream successfulMapEntryTestCases() { + return Stream.of( + arguments(MultimapTestData.mutableBagMultimap(), new Map.Entry[]{pair("TOS", "McCoy").toEntry(), pair("TNG", "Crusher").toEntry()}), + arguments(MultimapTestData.mutableListMultimap(), new Map.Entry[]{pair("TOS", "McCoy").toEntry(), pair("TNG", "Crusher").toEntry()}), + arguments(MultimapTestData.mutableSetMultimap(), new Map.Entry[]{pair("TOS", "McCoy").toEntry(), pair("TNG", "Crusher").toEntry()}) + ); + } + + private static Stream missingPairTestCases() { + return Stream.of( + arguments(MultimapTestData.mutableBagMultimap(), pair("VOY", "Kes")), + arguments(MultimapTestData.mutableListMultimap(), pair("VOY", "Kes")), + arguments(MultimapTestData.mutableSetMultimap(), pair("VOY", "Kes")) + ); + } + + private static Stream missingMapEntryTestCases() { + return Stream.of( + arguments(MultimapTestData.mutableBagMultimap(), pair("VOY", "Kes").toEntry()), + arguments(MultimapTestData.mutableListMultimap(), pair("VOY", "Kes").toEntry()), + arguments(MultimapTestData.mutableSetMultimap(), pair("VOY", "Kes").toEntry()) + ); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasDistinctSizeGreaterThan_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasDistinctSizeGreaterThan_Test.java new file mode 100644 index 0000000..deda665 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasDistinctSizeGreaterThan_Test.java @@ -0,0 +1,73 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.eclipse.collections.impl.factory.Multimaps; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_HasDistinctSizeGreaterThan_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#distinctSizeLowerBoundaryTestData") + void passesGreaterThan(Multimap actual, int lowerBoundary) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasDistinctSizeGreaterThan(lowerBoundary)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#distinctSizeUpperBoundaryTestData") + void failsLesser(Multimap actual, int upperBoundary) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasDistinctSizeGreaterThan(upperBoundary)) + .withMessageContaining("Expecting distinct size of") + .withMessageContaining(String.format("to be greater than %s but was %s", upperBoundary, actual.sizeDistinct())); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#distinctSizeEqualsTestData") + void failsEquals(Multimap actual, int equalsBoundary) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasDistinctSizeGreaterThan(equalsBoundary)) + .withMessageContaining("Expecting distinct size of") + .withMessageContaining(String.format("to be greater than %s but was %s", equalsBoundary, actual.sizeDistinct())); + } + + @Test + void failsNullMultimap() { + int lowerBoundary = 2; // Using the same value as in distinctSizeLowerBoundaryTestData + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).hasDistinctSizeGreaterThan(lowerBoundary)) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void failsEmptyMultimap(Multimap actual) { + int lowerBoundary = 2; // Using the same value as in distinctSizeLowerBoundaryTestData + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasDistinctSizeGreaterThan(lowerBoundary)) + .withMessageContaining(String.format("to be greater than %s but was 0", lowerBoundary)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#distinctSizeLowerBoundaryTestData") + void softAssertionPasses(Multimap actual, int lowerBoundary) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).hasDistinctSizeGreaterThan(lowerBoundary)); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasDistinctSize_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasDistinctSize_Test.java new file mode 100644 index 0000000..2769111 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasDistinctSize_Test.java @@ -0,0 +1,53 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_HasDistinctSize_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#distinctSizeEqualsTestData") + void passes(Multimap actual, int expectedSize) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasDistinctSize(expectedSize)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimapsWithExpectedDistinctSize") + void failsEmpty(Multimap actual, int expectedSize) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasDistinctSize(expectedSize)) + .withMessageContaining(String.format("Expected distinct size: %s but was: 0", expectedSize)); + } + + @Test + void failsNullMultimap() { + int expectedSize = 5; // Using the same value as in distinctSizeEqualsTestData + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).hasDistinctSize(expectedSize)) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#distinctSizeEqualsTestData") + void softAssertionPasses(Multimap actual, int expectedSize) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).hasDistinctSize(expectedSize)); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasKeySatisfying_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasKeySatisfying_Test.java new file mode 100644 index 0000000..68be703 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasKeySatisfying_Test.java @@ -0,0 +1,56 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.core.api.Condition; +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_HasKeySatisfying_Test { + + private static final Condition PASSING_CONDITION = new Condition<>("DS9"::equals, "key equals DS9"); + private static final Condition FAILING_CONDITION = new Condition<>("DIS"::equals, "key equals DIS"); + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void passesKeySatisfying(Multimap actual) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasKeySatisfying(PASSING_CONDITION)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void failsKeyNotSatisfying(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasKeySatisfying(FAILING_CONDITION)) + .withMessageContaining(FAILING_CONDITION.description().toString()); + } + + @Test + void failsNullMultimap() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).hasKeySatisfying(PASSING_CONDITION)) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void softAssertionPasses(Multimap actual) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).hasKeySatisfying(PASSING_CONDITION)); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeBetween_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeBetween_Test.java new file mode 100644 index 0000000..1789114 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeBetween_Test.java @@ -0,0 +1,80 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_HasSizeBetween_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeBetweenTestData") + void passesSizeBetween(Multimap actual, int lowerBoundary, int upperBoundary) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasSizeBetween(lowerBoundary, upperBoundary)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeBetweenInclusiveUpperTestData") + void passesSizeBetweenInclusiveUpper(Multimap actual, int lowerBoundary, int upperBoundary) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasSizeBetween(lowerBoundary, upperBoundary)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeBetweenInclusiveLowerTestData") + void passesSizeBetweenInclusiveLower(Multimap actual, int lowerBoundary, int upperBoundary) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasSizeBetween(lowerBoundary, upperBoundary)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeBelowLowerBoundaryTestData") + void failsSizeFallsBelowLowerBoundary(Multimap actual, int lowerBoundary, int upperBoundary) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasSizeBetween(lowerBoundary, upperBoundary)) + .withMessageContaining(String.format("Expected size to be between: %s and %s but was: %s", lowerBoundary, upperBoundary, actual.size())); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeAboveUpperBoundaryTestData") + void failsSizeFallsAboveUpperBoundary(Multimap actual, int lowerBoundary, int upperBoundary) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasSizeBetween(lowerBoundary, upperBoundary)) + .withMessageContaining(String.format("Expected size to be between: %s and %s but was: %s", lowerBoundary, upperBoundary, actual.size())); + } + + @Test + void failsNullMultimap() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).hasSizeBetween(25, 50)) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void failsEmptyMultimap(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasSizeBetween(25, 50)) + .withMessageContaining(String.format("Expected size to be between: %s and %s but was: %s", 25, 50, actual.size())); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeBetweenTestData") + void softAssertionPasses(Multimap actual, int lowerBoundary, int upperBoundary) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).hasSizeBetween(lowerBoundary, upperBoundary)); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeGreaterThan_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeGreaterThan_Test.java new file mode 100644 index 0000000..944656e --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeGreaterThan_Test.java @@ -0,0 +1,70 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_HasSizeGreaterThan_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeLowerBoundaryTestData") + void passesGreaterThan(Multimap actual, int lowerBoundary) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasSizeGreaterThan(lowerBoundary)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeUpperBoundaryTestData") + void failsLesser(Multimap actual, int upperBoundary) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasSizeGreaterThan(upperBoundary)) + .withMessageContaining("Expecting size of") + .withMessageContaining(String.format("to be greater than %s but was %s", upperBoundary, actual.size())); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeEqualsTestData") + void failsEquals(Multimap actual, int equalsBoundary) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasSizeGreaterThan(equalsBoundary)) + .withMessageContaining("Expecting size of") + .withMessageContaining(String.format("to be greater than %s but was %s", equalsBoundary, actual.size())); + } + + @Test + void failsNullMultimap() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).hasSizeGreaterThan(50)) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void failsEmptyMultimap(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasSizeGreaterThan(5)) + .withMessageContaining(String.format("to be greater than %s but was 0", 5)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeLowerBoundaryTestData") + void softAssertionPasses(Multimap actual, int lowerBoundary) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).hasSizeGreaterThan(lowerBoundary)); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeLessThanOrEqualTo_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeLessThanOrEqualTo_Test.java new file mode 100644 index 0000000..3b29ade --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeLessThanOrEqualTo_Test.java @@ -0,0 +1,59 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_HasSizeLessThanOrEqualTo_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeUpperBoundaryTestData") + void passesLessThan(Multimap actual, int upperBoundary) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasSizeLessThanOrEqualTo(upperBoundary)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeEqualsTestData") + void passesEqual(Multimap actual, int equalsBoundary) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasSizeLessThanOrEqualTo(equalsBoundary)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeLowerBoundaryTestData") + void failsGreater(Multimap actual, int lowerBoundary) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasSizeLessThanOrEqualTo(lowerBoundary)) + .withMessageContaining("Expecting size of") + .withMessageContaining(String.format("to be less than or equal to %s but was %s", lowerBoundary, actual.size())); + } + + @Test + void failsNullMultimap() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).hasSizeLessThanOrEqualTo(42)) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeUpperBoundaryTestData") + void softAssertionPasses(Multimap actual, int upperBoundary) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).hasSizeLessThanOrEqualTo(upperBoundary)); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeLessThan_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeLessThan_Test.java new file mode 100644 index 0000000..72a1113 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSizeLessThan_Test.java @@ -0,0 +1,62 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_HasSizeLessThan_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeUpperBoundaryTestData") + void passesLessThan(Multimap actual, int upperBoundary) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasSizeLessThan(upperBoundary)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeLowerBoundaryTestData") + void failsGreater(Multimap actual, int lowerBoundary) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasSizeLessThan(lowerBoundary)) + .withMessageContaining("Expecting size of") + .withMessageContaining(String.format("to be less than %s but was %s", lowerBoundary, actual.size())); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeEqualsTestData") + void failsEquals(Multimap actual, int equalsBoundary) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasSizeLessThan(equalsBoundary)) + .withMessageContaining("Expecting size of") + .withMessageContaining(String.format("to be less than %s but was %s", equalsBoundary, actual.size())); + } + + @Test + void failsNullMultimap() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).hasSizeLessThan(50)) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeUpperBoundaryTestData") + void softAssertionPasses(Multimap actual, int upperBoundary) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).hasSizeLessThan(upperBoundary)); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSize_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSize_Test.java new file mode 100644 index 0000000..fa164c1 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasSize_Test.java @@ -0,0 +1,52 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_HasSize_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeEqualsTestData") + void passes(Multimap actual, int expectedSize) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasSize(expectedSize)); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimapsWithExpectedSize") + void failsEmpty(Multimap actual, int expectedSize) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasSize(expectedSize)) + .withMessageContaining(String.format("Expected size: %s but was: 0", expectedSize)); + } + + @Test + void failsNullMultimap() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).hasSize(38)) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#sizeEqualsTestData") + void softAssertionPasses(Multimap actual, int expectedSize) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).hasSize(expectedSize)); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasValueSatisfying_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasValueSatisfying_Test.java new file mode 100644 index 0000000..a9731b9 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_HasValueSatisfying_Test.java @@ -0,0 +1,73 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import java.util.stream.Stream; + +import org.assertj.core.api.Condition; +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_HasValueSatisfying_Test { + + @ParameterizedTest + @MethodSource("successfulConditionTestCases") + void passesValueSatisfying(Multimap actual, Condition condition) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).hasValueSatisfying(condition)); + } + + @ParameterizedTest + @MethodSource("failureConditionTestCases") + void failsValueNotSatisfying(Multimap actual, Condition condition) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).hasValueSatisfying(condition)) + .withMessageContaining(condition.description().toString()); + } + + @ParameterizedTest + @MethodSource("successfulConditionTestCases") + void failsNullMultimap(Multimap ignored, Condition condition) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>((Multimap) null).hasValueSatisfying(condition)) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("successfulConditionTestCases") + void softAssertionPasses(Multimap actual, Condition condition) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).hasValueSatisfying(condition)); + } + + private static Stream successfulConditionTestCases() { + return Stream.of( + arguments(MultimapTestData.mutableBagMultimap(), new Condition<>(value -> value.equals("Janeway"), "value equals Janeway")), + arguments(MultimapTestData.mutableListMultimap(), new Condition<>(value -> value.equals("Janeway"), "value equals Janeway")), + arguments(MultimapTestData.mutableSetMultimap(), new Condition<>(value -> value.equals("Janeway"), "value equals Janeway")) + ); + } + + private static Stream failureConditionTestCases() { + return Stream.of( + arguments(MultimapTestData.mutableBagMultimap(), new Condition<>(value -> value.equals("Kes"), "value equals Kes")), + arguments(MultimapTestData.mutableListMultimap(), new Condition<>(value -> value.equals("Kes"), "value equals Kes")), + arguments(MultimapTestData.mutableSetMultimap(), new Condition<>(value -> value.equals("Kes"), "value equals Kes")) + ); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_IsEmpty_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_IsEmpty_Test.java new file mode 100644 index 0000000..f0263b1 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_IsEmpty_Test.java @@ -0,0 +1,53 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_IsEmpty_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void passes(Multimap actual) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).isEmpty()); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void failsNotEmpty(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).isEmpty()) + .withMessageContaining("Expecting empty but was: " + actual.toString()); + } + + @Test + void failsNullMultimap() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).isEmpty()) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void softAssertionPasses(Multimap actual) { + assertThatNoException().isThrownBy(() -> + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).isEmpty())); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_IsNotEmpty_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_IsNotEmpty_Test.java new file mode 100644 index 0000000..6fb891e --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_IsNotEmpty_Test.java @@ -0,0 +1,56 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import java.util.stream.Stream; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_IsNotEmpty_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void passesNotEmpty(Multimap actual) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).isNotEmpty()); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void failsEmpty(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).isNotEmpty()) + .withMessageContaining("Expecting actual not to be empty"); + } + + @Test + void failsNullMultimap() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(null).isNotEmpty()) + .withMessageContaining("Expecting actual not to be null"); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void softAssertionPasses(Multimap actual) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).isNotEmpty()); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_IsNullOrEmpty_Test.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_IsNullOrEmpty_Test.java new file mode 100644 index 0000000..f94b81e --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapAssert_IsNullOrEmpty_Test.java @@ -0,0 +1,55 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import org.assertj.eclipse.collections.api.SoftAssertions; +import org.eclipse.collections.api.multimap.Multimap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class MultimapAssert_IsNullOrEmpty_Test { + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void passesEmptyMultimap(Multimap actual) { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(actual).isNullOrEmpty()); + } + + @Test + void passesNullMultimap() { + assertThatNoException().isThrownBy(() -> new MultimapAssert<>(null).isNullOrEmpty()); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#nonEmptyMultimaps") + void failsNotNullOrEmpty(Multimap actual) { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> new MultimapAssert<>(actual).isNullOrEmpty()) + .withMessageContaining("Expecting null or empty but was: " + actual.toString()); + } + + @ParameterizedTest + @MethodSource("org.assertj.eclipse.collections.api.multimap.MultimapTestData#emptyMultimaps") + void softAssertionPassesEmpty(Multimap actual) { + SoftAssertions.assertSoftly(softly -> softly.assertThat(actual).isNullOrEmpty()); + } + + @Test + void softAssertionPassesNullMultimap() { + assertThatNoException().isThrownBy(() -> SoftAssertions.assertSoftly(softly -> softly.assertThat(null).isNullOrEmpty())); + } +} diff --git a/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapTestData.java b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapTestData.java new file mode 100644 index 0000000..dc00d73 --- /dev/null +++ b/src/test/java/org/assertj/eclipse/collections/api/multimap/MultimapTestData.java @@ -0,0 +1,216 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2025-2025 the original author or authors. + */ +package org.assertj.eclipse.collections.api.multimap; + +import org.eclipse.collections.api.factory.Bags; +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.factory.Sets; +import org.eclipse.collections.api.multimap.bag.BagMultimap; +import org.eclipse.collections.api.multimap.bag.MutableBagMultimap; +import org.eclipse.collections.api.multimap.list.ListMultimap; +import org.eclipse.collections.api.multimap.list.MutableListMultimap; +import org.eclipse.collections.api.multimap.set.MutableSetMultimap; +import org.eclipse.collections.api.multimap.set.SetMultimap; +import org.eclipse.collections.impl.factory.Multimaps; +import org.junit.jupiter.params.provider.Arguments; + +import java.util.stream.Stream; + +import static org.junit.jupiter.params.provider.Arguments.arguments; + +class MultimapTestData { + public static Stream emptyMultimaps() { + return Stream.of( + arguments(Multimaps.mutable.bag.empty()), + arguments(Multimaps.mutable.list.empty()), + arguments(Multimaps.mutable.set.empty()) + ); + } + + public static Stream nonEmptyMultimaps() { + return Stream.of( + arguments(mutableBagMultimap()), + arguments(mutableListMultimap()), + arguments(mutableSetMultimap()) + ); + } + + public static Stream sizeUpperBoundaryTestData() { + return Stream.of( + arguments(mutableBagMultimap(), 50), + arguments(mutableListMultimap(), 50), + arguments(mutableSetMultimap(), 50) + ); + } + + public static Stream sizeLowerBoundaryTestData() { + return Stream.of( + arguments(mutableBagMultimap(), 5), + arguments(mutableListMultimap(), 5), + arguments(mutableSetMultimap(), 5) + ); + } + + public static Stream sizeEqualsTestData() { + return Stream.of( + arguments(mutableBagMultimap(), 38), + arguments(mutableListMultimap(), 38), + arguments(mutableSetMultimap(), 38) + ); + } + + public static Stream sizeBetweenTestData() { + return Stream.of( + arguments(mutableBagMultimap(), 25, 50), + arguments(mutableListMultimap(), 25, 50), + arguments(mutableSetMultimap(), 25, 50) + ); + } + + public static Stream sizeBetweenInclusiveUpperTestData() { + return Stream.of( + arguments(mutableBagMultimap(), 25, 38), + arguments(mutableListMultimap(), 25, 38), + arguments(mutableSetMultimap(), 25, 38) + ); + } + + public static Stream sizeBetweenInclusiveLowerTestData() { + return Stream.of( + arguments(mutableBagMultimap(), 38, 50), + arguments(mutableListMultimap(), 38, 50), + arguments(mutableSetMultimap(), 38, 50) + ); + } + + public static Stream sizeBelowLowerBoundaryTestData() { + return Stream.of( + arguments(mutableBagMultimap(), 50, 57), + arguments(mutableListMultimap(), 50, 57), + arguments(mutableSetMultimap(), 50, 57) + ); + } + + public static Stream sizeAboveUpperBoundaryTestData() { + return Stream.of( + arguments(mutableBagMultimap(), 25, 32), + arguments(mutableListMultimap(), 25, 32), + arguments(mutableSetMultimap(), 25, 32) + ); + } + + public static Stream emptyMultimapsWithExpectedSize() { + return Stream.of( + arguments(Multimaps.mutable.bag.empty(), 38), + arguments(Multimaps.mutable.list.empty(), 38), + arguments(Multimaps.mutable.set.empty(), 38) + ); + } + + public static Stream distinctSizeEqualsTestData() { + return Stream.of( + arguments(mutableBagMultimap(), 5), + arguments(mutableListMultimap(), 5), + arguments(mutableSetMultimap(), 5) + ); + } + + public static Stream emptyMultimapsWithExpectedDistinctSize() { + return Stream.of( + arguments(Multimaps.mutable.bag.empty(), 5), + arguments(Multimaps.mutable.list.empty(), 5), + arguments(Multimaps.mutable.set.empty(), 5) + ); + } + + public static Stream distinctSizeLowerBoundaryTestData() { + return Stream.of( + arguments(mutableBagMultimap(), 2), + arguments(mutableListMultimap(), 2), + arguments(mutableSetMultimap(), 2) + ); + } + + public static Stream distinctSizeUpperBoundaryTestData() { + return Stream.of( + arguments(mutableBagMultimap(), 10), + arguments(mutableListMultimap(), 10), + arguments(mutableSetMultimap(), 10) + ); + } + + public static BagMultimap mutableBagMultimap() { + MutableBagMultimap multimap = Multimaps.mutable.bag.of(); + multimap.putAll("TOS", Bags.immutable.of("Kirk", "Spock", "McCoy", "Scotty", "Uhura", "Sulu", "Chekov")); + multimap.putAll("TNG", Bags.immutable.of("Picard", "Riker", "Data", "Geordi", "Troi", "Crusher", "Worf")); + multimap.putAll("DS9", Bags.immutable.of("Sisko", "Kira", "Obrien", "Dax", "Odo", "Bashir", "Worf", "Quark", "Jake")); + multimap.putAll("VOY", Bags.immutable.of("Janeway", "Chakotay", "Torres", "Paris", "The Doctor", "Tuvok", "Kim", "Seven")); + multimap.putAll("ENT", Bags.immutable.of("Archer", "Trip", "Tpol", "Reed", "Hoshi", "Phlox", "Mayweather")); + return multimap; + } + + public static ListMultimap mutableListMultimap() { + MutableListMultimap multimap = Multimaps.mutable.list.of(); + multimap.putAll("TOS", Lists.immutable.of("Kirk", "Spock", "McCoy", "Scotty", "Uhura", "Sulu", "Chekov")); + multimap.putAll("TNG", Lists.immutable.of("Picard", "Riker", "Data", "Geordi", "Troi", "Crusher", "Worf")); + multimap.putAll("DS9", Lists.immutable.of("Sisko", "Kira", "Obrien", "Dax", "Odo", "Bashir", "Worf", "Quark", "Jake")); + multimap.putAll("VOY", Lists.immutable.of("Janeway", "Chakotay", "Torres", "Paris", "The Doctor", "Tuvok", "Kim", "Seven")); + multimap.putAll("ENT", Lists.immutable.of("Archer", "Trip", "Tpol", "Reed", "Hoshi", "Phlox", "Mayweather")); + return multimap; + } + + public static SetMultimap mutableSetMultimap() { + MutableSetMultimap multimap = Multimaps.mutable.set.of(); + multimap.putAll("TOS", Sets.immutable.of("Kirk", "Spock", "McCoy", "Scotty", "Uhura", "Sulu", "Chekov")); + multimap.putAll("TNG", Sets.immutable.of("Picard", "Riker", "Data", "Geordi", "Troi", "Crusher", "Worf")); + multimap.putAll("DS9", Sets.immutable.of("Sisko", "Kira", "Obrien", "Dax", "Odo", "Bashir", "Worf", "Quark", "Jake")); + multimap.putAll("VOY", Sets.immutable.of("Janeway", "Chakotay", "Torres", "Paris", "The Doctor", "Tuvok", "Kim", "Seven")); + multimap.putAll("ENT", Sets.immutable.of("Archer", "Trip", "Tpol", "Reed", "Hoshi", "Phlox", "Mayweather")); + return multimap; + } + + public static Stream shipMultimaps() { + return Stream.of( + arguments(mutableBagShipMultimap()), + arguments(mutableListShipMultimap()), + arguments(mutableSetShipMultimap()) + ); + } + + public static BagMultimap mutableBagShipMultimap() { + MutableBagMultimap multimap = Multimaps.mutable.bag.of(); + multimap.put("TNG", "Enterprise"); + multimap.put("DS9", "Deep Space Nine"); + multimap.put("DS9", "Defiant"); + multimap.put("VOY", "Voyager"); + return multimap; + } + + public static ListMultimap mutableListShipMultimap() { + MutableListMultimap multimap = Multimaps.mutable.list.of(); + multimap.put("TNG", "Enterprise"); + multimap.put("DS9", "Deep Space Nine"); + multimap.put("DS9", "Defiant"); + multimap.put("VOY", "Voyager"); + return multimap; + } + + public static SetMultimap mutableSetShipMultimap() { + MutableSetMultimap multimap = Multimaps.mutable.set.of(); + multimap.put("TNG", "Enterprise"); + multimap.put("DS9", "Deep Space Nine"); + multimap.put("DS9", "Defiant"); + multimap.put("VOY", "Voyager"); + return multimap; + } +}