All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fitbur.assertj.internal.Maps Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
/**
 * 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 2012-2016 the original author or authors.
 */
package com.fitbur.assertj.internal;

import static com.fitbur.assertj.data.MapEntry.entry;
import static com.fitbur.assertj.error.ShouldBeEmpty.shouldBeEmpty;
import static com.fitbur.assertj.error.ShouldBeNullOrEmpty.shouldBeNullOrEmpty;
import static com.fitbur.assertj.error.ShouldContain.shouldContain;
import static com.fitbur.assertj.error.ShouldContainExactly.elementsDifferAtIndex;
import static com.fitbur.assertj.error.ShouldContainExactly.shouldContainExactly;
import static com.fitbur.assertj.error.ShouldContainKeys.shouldContainKeys;
import static com.fitbur.assertj.error.ShouldContainOnly.shouldContainOnly;
import static com.fitbur.assertj.error.ShouldContainOnlyKeys.shouldContainOnlyKeys;
import static com.fitbur.assertj.error.ShouldContainValue.shouldContainValue;
import static com.fitbur.assertj.error.ShouldContainValues.shouldContainValues;
import static com.fitbur.assertj.error.ShouldNotBeEmpty.shouldNotBeEmpty;
import static com.fitbur.assertj.error.ShouldNotContain.shouldNotContain;
import static com.fitbur.assertj.error.ShouldNotContainKey.shouldNotContainKey;
import static com.fitbur.assertj.error.ShouldNotContainKeys.shouldNotContainKeys;
import static com.fitbur.assertj.error.ShouldNotContainValue.shouldNotContainValue;
import static com.fitbur.assertj.internal.Arrays.assertIsArray;
import static com.fitbur.assertj.internal.CommonValidations.checkSizes;
import static com.fitbur.assertj.internal.CommonValidations.hasSameSizeAsCheck;
import static com.fitbur.assertj.util.Objects.areEqual;
import static com.fitbur.assertj.util.Preconditions.checkNotNull;

import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import com.fitbur.assertj.api.AssertionInfo;
import com.fitbur.assertj.util.VisibleForTesting;

/**
 * Reusable assertions for {@link Map}s.
 * 
 * @author Alex Ruiz
 * @author Nicolas François
 * @author dorzey
 */
public class Maps {

  private static final Maps INSTANCE = new Maps();

  /**
   * Returns the singleton instance of this class.
   * 
   * @return the singleton instance of this class.
   */
  public static Maps instance() {
    return INSTANCE;
  }

  @VisibleForTesting
  Failures failures = Failures.instance();

  @VisibleForTesting
  Maps() {}

  /**
   * Asserts that the given {@code Map} is {@code null} or empty.
   * 
   * @param info contains information about the assertion.
   * @param actual the given map.
   * @throws AssertionError if the given {@code Map} is not {@code null} *and* contains one or more entries.
   */
  public void assertNullOrEmpty(AssertionInfo info, Map actual) {
    if (actual != null && !actual.isEmpty()) throw failures.failure(info, shouldBeNullOrEmpty(actual));
  }

  /**
   * Asserts that the given {@code Map} is empty.
   * 
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @throws AssertionError if the given {@code Map} is {@code null}.
   * @throws AssertionError if the given {@code Map} is not empty.
   */
  public void assertEmpty(AssertionInfo info, Map actual) {
    assertNotNull(info, actual);
    if (!actual.isEmpty()) throw failures.failure(info, shouldBeEmpty(actual));
  }

  /**
   * Asserts that the given {@code Map} is not empty.
   * 
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @throws AssertionError if the given {@code Map} is {@code null}.
   * @throws AssertionError if the given {@code Map} is empty.
   */
  public void assertNotEmpty(AssertionInfo info, Map actual) {
    assertNotNull(info, actual);
    if (actual.isEmpty()) throw failures.failure(info, shouldNotBeEmpty());
  }

  /**
   * Asserts that the number of entries in the given {@code Map} is equal to the expected one.
   * 
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @param expectedSize the expected size of {@code actual}.
   * @throws AssertionError if the given {@code Map} is {@code null}.
   * @throws AssertionError if the number of entries in the given {@code Map} is different than the expected one.
   */
  public void assertHasSize(AssertionInfo info, Map actual, int expectedSize) {
    assertNotNull(info, actual);
    checkSizes(actual, actual.size(), expectedSize, info);
  }

  /**
   * Asserts that the number of entries in the given {@code Map} has the same size as the other {@code Iterable}.
   * 
   * @param info contains information about the assertion.
   * @param map the given {@code Map}.
   * @param other the group to compare
   * @throws AssertionError if the given {@code Map} is {@code null}.
   * @throws AssertionError if the given {@code Iterable} is {@code null}.
   * @throws AssertionError if the number of entries in the given {@code Map} does not have the same size.
   */
  public void assertHasSameSizeAs(AssertionInfo info, Map map, Iterable other) {
    assertNotNull(info, map);
    hasSameSizeAsCheck(info, map, other, map.size());
  }

  /**
   * Asserts that the number of entries in the given {@code Map} has the same size as the other array.
   * 
   * @param info contains information about the assertion.
   * @param map the given {@code Map}.
   * @param other the group to compare
   * @throws AssertionError if the given {@code Map} is {@code null}.
   * @throws AssertionError if the given array is {@code null}.
   * @throws AssertionError if the number of entries in the given {@code Map} does not have the same size.
   */
  public void assertHasSameSizeAs(AssertionInfo info, Map map, Object other) {
    assertNotNull(info, map);
    assertIsArray(info, other);
    hasSameSizeAsCheck(info, map, other, map.size());
  }

  /**
   * Asserts that the size of the given {@code Map} is equal to the size of the other {@code Map}.
   *
   * @param info contains information about the assertion.
   * @param map the given {@code Map}.
   * @param other the other {@code Map} to compare
   * @throws NullPointerException if the other {@code Map} is {@code null}.
   * @throws AssertionError if the given {@code Map} is {@code null}.
   * @throws AssertionError if the size of the given {@code Map} is not equal to the other {@code Map} size
   */
  public void assertHasSameSizeAs(AssertionInfo info, Map map, Map other) {
    assertNotNull(info, map);
    hasSameSizeAsCheck(info, map, other, map.size());
  }

  /**
   * Asserts that the given {@code Map} contains the given entries, in any order.
   * 
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @param entries the entries that are expected to be in the given {@code Map}.
   * @throws NullPointerException if the array of entries is {@code null}.
   * @throws IllegalArgumentException if the array of entries is empty.
   * @throws NullPointerException if any of the entries in the given array is {@code null}.
   * @throws AssertionError if the given {@code Map} is {@code null}.
   * @throws AssertionError if the given {@code Map} does not contain the given entries.
   */
  public  void assertContains(AssertionInfo info, Map actual, Map.Entry[] entries) {
    failIfNull(entries);
    assertNotNull(info, actual);
    // if both actual and values are empty, then assertion passes.
    if (actual.isEmpty() && entries.length == 0)
      return;
    failIfEmptySinceActualIsNotEmpty(entries);
    Set> notFound = new LinkedHashSet<>();
    for (Map.Entry entry : entries) {
      if (!containsEntry(actual, entry)) {
        notFound.add(entry);
      }
    }
    if (notFound.isEmpty()) return;
    throw failures.failure(info, shouldContain(actual, entries, notFound));
  }

  /**
   * Asserts that the given {@code Map} does not contain the given entries.
   * 
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @param entries the entries that are expected to be in the given {@code Map}.
   * @throws NullPointerException if the array of entries is {@code null}.
   * @throws IllegalArgumentException if the array of entries is empty.
   * @throws NullPointerException if any of the entries in the given array is {@code null}.
   * @throws AssertionError if the given {@code Map} is {@code null}.
   * @throws AssertionError if the given {@code Map} contains any of the given entries.
   */
  public  void assertDoesNotContain(AssertionInfo info, Map actual,
                                          Map.Entry[] entries) {
    failIfNullOrEmpty(entries);
    assertNotNull(info, actual);
    Set> found = new LinkedHashSet<>();
    for (Map.Entry entry : entries) {
      if (containsEntry(actual, entry)) {
        found.add(entry);
      }
    }
    if (found.isEmpty()) return;
    throw failures.failure(info, shouldNotContain(actual, entries, found));
  }

  /**
   * Verifies that the actual map contain the given key.
   * 
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @param keys the given keys
   * @throws AssertionError if the actual map is {@code null}.
   * @throws AssertionError if the actual map not contains the given key.
   */
  public  void assertContainsKeys(AssertionInfo info, Map actual, @SuppressWarnings("unchecked") K... keys) {
    assertNotNull(info, actual);
    Set notFound = new LinkedHashSet<>();
    for (K key : keys) {
      if (!actual.containsKey(key)) {
        notFound.add(key);
      }
    }
    if (notFound.isEmpty()) return;
    throw failures.failure(info, shouldContainKeys(actual, notFound));
  }

  /**
   * Verifies that the actual map not contains the given key.
   * 
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @param key the given key
   * @throws AssertionError if the actual map is {@code null}.
   * @throws AssertionError if the actual map contains the given key.
   */
  public  void assertDoesNotContainKey(AssertionInfo info, Map actual, K key) {
    assertNotNull(info, actual);
    if (actual.containsKey(key)) throw failures.failure(info, shouldNotContainKey(actual, key));
  }

  /**
   * Verifies that the actual map not contains all the given keys.
   *
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @param keys the given keys
   * @throws AssertionError if the actual map is {@code null}.
   * @throws AssertionError if the actual map contains all the given keys.
   */
  public  void assertDoesNotContainKeys(AssertionInfo info, Map actual,
                                              @SuppressWarnings("unchecked") K... keys) {
    assertNotNull(info, actual);
    Set found = new LinkedHashSet<>();
    for (K key : keys) {
      if (key != null && actual.containsKey(key)) {
        found.add(key);
      }
    }
    if (!found.isEmpty()) throw failures.failure(info, shouldNotContainKeys(actual, found));
  }

  /**
   * Verifies that the actual map contains only the given keys and nothing else, in any order.
   * 
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @param keys the keys that are expected to be in the given {@code Map}.
   * @throws NullPointerException if the array of keys is {@code null}.
   * @throws IllegalArgumentException if the array of keys is empty.
   * @throws AssertionError if the given {@code Map} is {@code null}.
   * @throws AssertionError if the given {@code Map} does not contain the given keys or if the given {@code Map}
   *           contains keys that are not in the given array.
   */
  public  void assertContainsOnlyKeys(AssertionInfo info, Map actual,
                                            @SuppressWarnings("unchecked") K... keys) {
    assertNotNull(info, actual);
    failIfNull(keys);
    if (actual.isEmpty() && keys.length == 0) {
      return;
    }
    failIfEmpty(keys);

    Set notFound = new LinkedHashSet<>();
    Set notExpected = new LinkedHashSet<>();

    compareActualMapAndExpectedKeys(actual, keys, notExpected, notFound);

    if (!notFound.isEmpty() || !notExpected.isEmpty())
      throw failures.failure(info, shouldContainOnlyKeys(actual, keys, notFound, notExpected));
  }

  /**
   * Verifies that the actual map contain the given value.
   * 
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @param value the given value
   * @throws AssertionError if the actual map is {@code null}.
   * @throws AssertionError if the actual map not contains the given value.
   */
  public  void assertContainsValue(AssertionInfo info, Map actual, V value) {
    assertNotNull(info, actual);
    if (!actual.containsValue(value)) throw failures.failure(info, shouldContainValue(actual, value));
  }

  /**
   * Verifies that the actual map contain the given values.
   *
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @param values the given values
   * @throws AssertionError if the actual map is {@code null}.
   * @throws AssertionError if the actual map not contains the given values.
   * @throws NullPointerException if values vararg is {@code null}.
   */
  public  void assertContainsValues(AssertionInfo info, Map actual,
                                          @SuppressWarnings("unchecked") V... values) {
    assertNotNull(info, actual);
    checkNotNull(values, "The array of values to look for should not be null");
    if (actual.isEmpty() && values.length == 0) return;
    //
    Set valuesNotFound = new LinkedHashSet<>();
    for (V valueToLookFor : values) {
      if (!actual.containsValue(valueToLookFor)) valuesNotFound.add(valueToLookFor);
    }
    if (!valuesNotFound.isEmpty()) throw failures.failure(info, shouldContainValues(actual, valuesNotFound));
  }

  /**
   * Verifies that the actual map not contains the given value.
   * 
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @param value the given value
   * @throws AssertionError if the actual map is {@code null}.
   * @throws AssertionError if the actual map contains the given value.
   */
  public  void assertDoesNotContainValue(AssertionInfo info, Map actual, V value) {
    assertNotNull(info, actual);
    if (actual.containsValue(value)) throw failures.failure(info, shouldNotContainValue(actual, value));
  }

  /**
   * Verifies that the actual map contains only the given entries and nothing else, in any order.
   * 
   * @param info contains information about the assertion.
   * @param actual the given {@code Map}.
   * @param entries the entries that should be in the actual map.
   * @throws AssertionError if the actual map is {@code null}.
   * @throws NullPointerException if the given entries array is {@code null}.
   * @throws IllegalArgumentException if the given entries array is empty.
   * @throws AssertionError if the actual map does not contain the given entries, i.e. the actual map contains some or
   *           none of the given entries, or the actual map contains more entries than the given ones.
   */
  public  void assertContainsOnly(AssertionInfo info, Map actual,
                                        @SuppressWarnings("unchecked") Map.Entry... entries) {
    doCommonContainsCheck(info, actual, entries);
    if (actual.isEmpty() && entries.length == 0) {
      return;
    }
    failIfEmpty(entries);

    Set> notFound = new LinkedHashSet<>();
    Set> notExpected = new LinkedHashSet<>();

    compareActualMapAndExpectedEntries(actual, entries, notExpected, notFound);

    if (!notFound.isEmpty() || !notExpected.isEmpty())
      throw failures.failure(info, shouldContainOnly(actual, entries, notFound, notExpected));
  }

  /**
   * Verifies that the actual map contains only the given entries and nothing else, in order.
* This assertion should only be used with map that have a consistent iteration order (i.e. don't use it with * {@link java.util.HashMap}). * * @param info contains information about the assertion. * @param actual the given {@code Map}. * @param entries the given entries. * @throws NullPointerException if the given entries array is {@code null}. * @throws AssertionError if the actual map is {@code null}. * @throws IllegalArgumentException if the given entries array is empty. * @throws AssertionError if the actual map does not contain the given entries with same order, i.e. the actual map * contains some or none of the given entries, or the actual map contains more entries than the given ones * or entries are the same but the order is not. */ public void assertContainsExactly(AssertionInfo info, Map actual, @SuppressWarnings("unchecked") Map.Entry... entries) { doCommonContainsCheck(info, actual, entries); if (actual.isEmpty() && entries.length == 0) return; failIfEmpty(entries); assertHasSameSizeAs(info, actual, entries); Set> notFound = new LinkedHashSet<>(); Set> notExpected = new LinkedHashSet<>(); compareActualMapAndExpectedEntries(actual, entries, notExpected, notFound); if (notExpected.isEmpty() && notFound.isEmpty()) { // check entries order int index = 0; for (K keyFromActual : actual.keySet()) { if (!areEqual(keyFromActual, entries[index].getKey())) { Map.Entry actualEntry = entry(keyFromActual, actual.get(keyFromActual)); throw failures.failure(info, elementsDifferAtIndex(actualEntry, entries[index], index)); } index++; } // all entries are in the same order. return; } throw failures.failure(info, shouldContainExactly(actual, entries, notFound, notExpected)); } private void compareActualMapAndExpectedKeys(Map actual, K[] keys, Set notExpected, Set notFound) { Map actualEntries = new LinkedHashMap<>(actual); for (K key : keys) { if (actualEntries.containsKey(key)) { // this is an expected key actualEntries.remove(key); } else { // this is a not found key notFound.add(key); } } // All remaining keys from actual copy are not expected entries. for (K key : actualEntries.keySet()) { notExpected.add(key); } } private void compareActualMapAndExpectedEntries(Map actual, Map.Entry[] entries, Set> notExpected, Set> notFound) { Map expectedEntries = entriesToMap(entries); Map actualEntries = new LinkedHashMap<>(actual); for (Map.Entry entry : expectedEntries.entrySet()) { if (containsEntry(actualEntries, entry(entry.getKey(), entry.getValue()))) { // this is an expected entry actualEntries.remove(entry.getKey()); } else { // this is a not found entry notFound.add(entry(entry.getKey(), entry.getValue())); } } // All remaining entries from actual copy are not expected entries. for (Map.Entry entry : actualEntries.entrySet()) { notExpected.add(entry(entry.getKey(), entry.getValue())); } } private void doCommonContainsCheck(AssertionInfo info, Map actual, Map.Entry[] entries) { assertNotNull(info, actual); failIfNull(entries); } private static Map entriesToMap(Map.Entry[] entries) { Map expectedEntries = new LinkedHashMap<>(); for (Map.Entry entry : entries) { expectedEntries.put(entry.getKey(), entry.getValue()); } return expectedEntries; } private static void failIfEmpty(K[] keys) { if (keys.length == 0) throw new IllegalArgumentException("The array of keys to look for should not be empty"); } private static void failIfEmpty(Map.Entry[] entries) { if (entries.length == 0) throw new IllegalArgumentException("The array of entries to look for should not be empty"); } private static void failIfNullOrEmpty(Map.Entry[] entries) { failIfNull(entries); failIfEmpty(entries); } private static void failIfNull(K[] keys) { checkNotNull(keys, "The array of keys to look for should not be null"); } private static void failIfNull(Map.Entry[] entries) { checkNotNull(entries, "The array of entries to look for should not be null"); } private boolean containsEntry(Map actual, Map.Entry entry) { checkNotNull(entry, "Entries to look for should not be null"); return actual.containsKey(entry.getKey()) ? areEqual(actual.get(entry.getKey()), entry.getValue()) : false; } private void assertNotNull(AssertionInfo info, Map actual) { Objects.instance().assertNotNull(info, actual); } private static void failIfEmptySinceActualIsNotEmpty(Map.Entry[] values) { if (values.length == 0) throw new AssertionError("actual is not empty"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy