/* * Created on Nov 28, 2010 * * 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 @2010-2013 the original author or authors. */ package org.fest.assertions.internal; import static org.fest.assertions.error.ShouldBeEmpty.shouldBeEmpty; import static org.fest.assertions.error.ShouldBeNullOrEmpty.shouldBeNullOrEmpty; import static org.fest.assertions.error.ShouldContain.shouldContain; import static org.fest.assertions.error.ShouldContainAtIndex.shouldContainAtIndex; import static org.fest.assertions.error.ShouldContainNull.shouldContainNull; import static org.fest.assertions.error.ShouldContainOnly.shouldContainOnly; import static org.fest.assertions.error.ShouldContainSequence.shouldContainSequence; import static org.fest.assertions.error.ShouldEndWith.shouldEndWith; import static org.fest.assertions.error.ShouldHaveSize.shouldHaveSize; import static org.fest.assertions.error.ShouldNotBeEmpty.shouldNotBeEmpty; import static org.fest.assertions.error.ShouldNotContain.shouldNotContain; import static org.fest.assertions.error.ShouldNotContainAtIndex.shouldNotContainAtIndex; import static org.fest.assertions.error.ShouldNotContainNull.shouldNotContainNull; import static org.fest.assertions.error.ShouldNotHaveDuplicates.shouldNotHaveDuplicates; import static org.fest.assertions.error.ShouldStartWith.shouldStartWith; import static org.fest.assertions.internal.CommonErrors.arrayOfValuesToLookForIsEmpty; import static org.fest.assertions.internal.CommonErrors.arrayOfValuesToLookForIsNull; import static org.fest.assertions.internal.CommonValidations.checkIndexValueIsValid; import static org.fest.assertions.util.ArrayWrapperList.wrap; import static org.fest.util.Collections.duplicatesFrom; import static org.fest.util.Objects.areEqual; import static org.fest.util.Sets.newLinkedHashSet; import java.lang.reflect.Array; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Set; import org.fest.assertions.data.Index; import org.fest.assertions.description.Description; import org.fest.assertions.error.BasicErrorMessageFactory; import org.fest.assertions.util.ArrayWrapperList; import org.fest.util.VisibleForTesting; /** * Assertions for object and primitive arrays. It trades off performance for DRY. * * @author Alex Ruiz * @author Yvonne Wang */ class Arrays { private static final Arrays INSTANCE = new Arrays(); static Arrays instance() { return INSTANCE; } private Arrays() { } @VisibleForTesting Failures failures = Failures.instance(); void assertNullOrEmpty(Description description, Object array) { if (array == null || isArrayEmpty(array)) { return; } throw failures.failure(description, shouldBeNullOrEmpty(array)); } void assertEmpty(Description description, Object array) { assertNotNull(description, array); if (!isArrayEmpty(array)) { throw failures.failure(description, shouldBeEmpty(array)); } } void assertHasSize(Description description, Object array, int expectedSize) { assertNotNull(description, array); if (expectedSize < 0) { throw failures.failure(description, new BasicErrorMessageFactory("The expectedSize should not be negative")); } int sizeOfActual = sizeOf(array); if (sizeOfActual != expectedSize) { throw failures.failure(description, shouldHaveSize(array, sizeOfActual, expectedSize)); } } void assertContains(Description description, Object array, Object values) { checkIsNotNullAndNotEmpty(values); assertNotNull(description, array); assertNotEmpty(description, array); int valueCount = sizeOf(values); Set<Object> notFound = newLinkedHashSet(); for (int i = 0; i < valueCount; i++) { Object value = Array.get(values, i); if (!arrayContains(array, value)) { notFound.add(value); } } if (notFound.isEmpty()) { return; } throw failures.failure(description, shouldContain(array, values, notFound)); } void assertContains(Description description, Object array, Object value, Index index) { assertNotNull(description, array); assertNotEmpty(description, array); checkIndexValueIsValid(index, sizeOf(array) - 1); Object actualElement = Array.get(array, index.value); if (areEqual(actualElement, value)) { return; } throw failures.failure(description, shouldContainAtIndex(array, value, index, Array.get(array, index.value))); } void assertNotEmpty(Description description, Object array) { assertNotNull(description, array); if (isArrayEmpty(array)) { throw failures.failure(description, shouldNotBeEmpty()); } } void assertDoesNotContain(Description description, Object array, Object value, Index index) { assertNotNull(description, array); checkIndexValueIsValid(index, Integer.MAX_VALUE); int indexValue = index.value; if (indexValue >= sizeOf(array)) { return; } Object actualElement = Array.get(array, index.value); if (!areEqual(actualElement, value)) { return; } throw failures.failure(description, shouldNotContainAtIndex(array, value, index)); } void assertContainsOnly(Description description, Object array, Object values) { checkIsNotNullAndNotEmpty(values); assertNotNull(description, array); Set<Object> notExpected = asSet(array); Set<Object> notFound = containsOnly(notExpected, values); if (notExpected.isEmpty() && notFound.isEmpty()) { return; } throw failures.failure(description, shouldContainOnly(array, values, notFound, notExpected)); } private Set<Object> containsOnly(Set<Object> actual, Object values) { Set<Object> notFound = newLinkedHashSet(); for (Object o : asSet(values)) { if (actual.contains(o)) { actual.remove(o); } else { notFound.add(o); } } return notFound; } private Set<Object> asSet(Object array) { Set<Object> set = newLinkedHashSet(); int size = sizeOf(array); for (int i = 0; i < size; i++) { Object element = Array.get(array, i); set.add(element); } return set; } void assertContainsSequence(Description description, Object array, Object sequence) { checkIsNotNullAndNotEmpty(sequence); assertNotNull(description, array); int sizeOfActual = sizeOf(array); int sizeOfSequence = sizeOf(sequence); boolean firstFound = false; int index = 0; if (sizeOfActual < sizeOfSequence) { String format = "The size of sequence is greater than the size of array"; throw failures.failure(description, new BasicErrorMessageFactory(format, array, sequence)); } for (int i = 0; i < sizeOfActual && index < sizeOfSequence; i++) { if (areEqual(Array.get(array, i), Array.get(sequence, index))) { firstFound = true; index++; if (i >= sizeOfActual - 1 && index < sizeOfSequence) { throw arrayDoesNotContainSequence(description, array, sequence); } continue; } if (!firstFound) { if (i >= sizeOfActual - 1 && index < sizeOfSequence) { throw arrayDoesNotContainSequence(description, array, sequence); } continue; } else { throw arrayDoesNotContainSequence(description, array, sequence); } } } private AssertionError arrayDoesNotContainSequence(Description description, Object array, Object sequence) { return failures.failure(description, shouldContainSequence(array, sequence)); } void assertDoesNotContain(Description description, Object array, Object values) { checkIsNotNullAndNotEmpty(values); assertNotNull(description, array); Set<Object> found = new LinkedHashSet<Object>(); for (int i = 0; i < sizeOf(values); i++) { Object value = Array.get(values, i); if (arrayContains(array, value)) { found.add(value); } } if (found.isEmpty()) { return; } throw failures.failure(description, shouldNotContain(array, values, found)); } private boolean arrayContains(Object array, Object value) { int size = sizeOf(array); for (int i = 0; i < size; i++) { Object element = Array.get(array, i); if (areEqual(element, value)) { return true; } } return false; } void assertDoesNotHaveDuplicates(Description description, Object array) { assertNotNull(description, array); ArrayWrapperList wrapped = wrap(array); Collection<?> duplicates = duplicatesFrom(wrapped); if (duplicates == null || duplicates.isEmpty()) { return; } throw failures.failure(description, shouldNotHaveDuplicates(array, duplicates)); } void assertStartsWith(Description description, Object array, Object sequence) { checkIsNotNullAndNotEmpty(sequence); assertNotNull(description, array); int sequenceSize = sizeOf(sequence); int arraySize = sizeOf(array); if (arraySize < sequenceSize) { throw arrayDoesNotStartWithSequence(description, array, sequence); } for (int i = 0; i < sequenceSize; i++) { if (areEqual(Array.get(sequence, i), Array.get(array, i))) { continue; } throw arrayDoesNotStartWithSequence(description, array, sequence); } } private AssertionError arrayDoesNotStartWithSequence(Description description, Object array, Object sequence) { return failures.failure(description, shouldStartWith(array, sequence)); } void assertEndsWith(Description description, Object array, Object sequence) { checkIsNotNullAndNotEmpty(sequence); assertNotNull(description, array); int sequenceSize = sizeOf(sequence); int arraySize = sizeOf(array); if (arraySize < sequenceSize) { throw arrayDoesNotEndWithSequence(description, failures, array, sequence); } for (int i = 0; i < sequenceSize; i++) { int sequenceIndex = sequenceSize - (i + 1); int arrayIndex = arraySize - (i + 1); if (areEqual(Array.get(sequence, sequenceIndex), Array.get(array, arrayIndex))) { continue; } throw arrayDoesNotEndWithSequence(description, failures, array, sequence); } } void assertContainsNull(Description description, Object array) { assertNotNull(description, array); if (!arrayContains(array, null)) { throw failures.failure(description, shouldContainNull(array)); } } void assertDoesNotContainNull(Description description, Object array) { assertNotNull(description, array); if (arrayContains(array, null)) { throw failures.failure(description, shouldNotContainNull(array)); } } private void checkIsNotNullAndNotEmpty(Object values) { if (values == null) { throw arrayOfValuesToLookForIsNull(); } if (isArrayEmpty(values)) { throw arrayOfValuesToLookForIsEmpty(); } } private boolean isArrayEmpty(Object array) { return sizeOf(array) == 0; } private AssertionError arrayDoesNotEndWithSequence(Description description, Failures failures, Object array, Object sequence) { return failures.failure(description, shouldEndWith(array, sequence)); } private static void assertNotNull(Description description, Object array) { Objects.instance().assertNotNull(description, array); } private int sizeOf(Object array) { return Array.getLength(array); } }