001    /*
002     * Created on Feb 16, 2008
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005     * in compliance with the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License
010     * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011     * or implied. See the License for the specific language governing permissions and limitations under
012     * the License.
013     *
014     * Copyright @2008-2009 the original author or authors.
015     */
016    package org.fest.assertions;
017    
018    import static org.fest.assertions.ArrayInspection.copy;
019    import static org.fest.assertions.ArrayInspection.sizeOf;
020    import static org.fest.assertions.Formatting.inBrackets;
021    import static org.fest.util.Strings.concat;
022    
023    import java.util.ArrayList;
024    import java.util.List;
025    
026    /**
027     * Understands assertions for arrays.
028     * @param <T> the generic type of the arrays.
029     *
030     * @author Alex Ruiz
031     */
032    public abstract class ArrayAssert<T> extends GroupAssert<T> {
033    
034      /**
035       * Creates a new </code>{@link ArrayAssert}</code>.
036       * @param actual the target to verify.
037       */
038      protected ArrayAssert(T actual) {
039        super(actual);
040      }
041    
042      /**
043       * Returns the size of the actual array.
044       * @return the size of the actual array.
045       */
046      protected final int actualGroupSize() {
047        isNotNull();
048        return sizeOf(actual);
049      }
050    
051      /**
052       * Verifies that the actual <code>byte</code> array contains the given values.
053       * @param values the values to look for.
054       * @throws AssertionError if the actual <code>byte</code> array does not contain the given values.
055       */
056      protected final void assertContains(List<Object> values) {
057        List<Object> notFound = notFoundInActual(values);
058        if (notFound.isEmpty()) return;
059        failIfCustomMessageIsSet();
060        failureIfExpectedElementsNotFound(notFound.toArray());
061      }
062    
063      private List<Object> notFoundInActual(List<Object> values) {
064        List<Object> copy = copy(actual);
065        List<Object> notFound = new ArrayList<Object>();
066        for (Object value : values) {
067          if (copy.contains(value)) continue;
068          notFound.add(value);
069        }
070        return notFound;
071      }
072    
073      /**
074       * Verifies that the actual array contains the given values <strong>only</strong>.
075       * @param values the values to look for.
076       * @throws AssertionError if the actual array does not contain the given objects, or if the actual array contains
077       * elements other than the ones specified.
078       */
079      protected final void assertContainsOnly(List<Object> values) {
080        List<Object> copy = copy(actual);
081        List<Object> notFound = notFoundInCopy(copy, values);
082        if (!notFound.isEmpty()) failureIfExpectedElementsNotFound(notFound.toArray());
083        if (copy.isEmpty()) return;
084        throw failureIfUnexpectedElementsFound(copy.toArray());
085      }
086    
087      private List<Object> notFoundInCopy(List<Object> copy, List<Object> values) {
088        List<Object> notFound = new ArrayList<Object>();
089        for (Object value : values) {
090          if (!copy.contains(value)) {
091            notFound.add(value);
092            continue;
093          }
094          copy.remove(value);
095        }
096        return notFound;
097      }
098    
099      private void failureIfExpectedElementsNotFound(Object[] notFound) {
100        failIfCustomMessageIsSet();
101        fail(concat("array:", actualInBrackets(), " does not contain element(s):", inBrackets(notFound)));
102      }
103    
104      private AssertionError failureIfUnexpectedElementsFound(Object[] unexpected) {
105        failIfCustomMessageIsSet();
106        return failure(concat("unexpected element(s):", inBrackets(unexpected), " in array:", actualInBrackets()));
107      }
108    
109      /**
110       * Verifies that the actual array does not contain the given values.
111       * @param values the values the array should exclude.
112       * @throws AssertionError if the actual array contains any of the given values.
113       */
114      protected final void assertExcludes(List<Object> values) {
115        List<Object> copyOfActual = copy(actual);
116        List<Object> found = new ArrayList<Object>();
117        for (Object value : values) if (copyOfActual.contains(value)) found.add(value);
118        if (found.isEmpty()) return;
119        failIfCustomMessageIsSet();
120        fail(concat("array:", actualInBrackets(), " does not exclude element(s):", inBrackets(found.toArray())));
121      }
122    
123      /**
124       * Returns the <code>String</code> representation of the actual array in between brackets ("<" and ">").
125       * @return the <code>String</code> representation of the actual array in between brackets ("<" and ">").
126       */
127      protected final String actualInBrackets() {
128        return inBrackets(actual);
129      }
130    
131      /**
132       * Verifies that the actual array is not <code>null</code>.
133       * @throws AssertionError if the actual array is <code>null</code>.
134       */
135      protected final void assertThatActualIsNotNull() {
136        if (actual != null) return;
137        failIfCustomMessageIsSet();
138        fail("expecting a non-null array, but it was null");
139      }
140    
141      /**
142       * Verifies that the actual array is empty (not <code>null</code> with zero elements.)
143       * @throws AssertionError if the actual array is <code>null</code> or not empty.
144       */
145      public final void isEmpty() {
146        if (actualGroupSize() == 0) return;
147        failIfCustomMessageIsSet();
148        fail(concat("expecting empty array, but was:", actualInBrackets()));
149      }
150    
151      /**
152       * Verifies that the actual array is <code>null</code> or empty.
153       * @throws AssertionError if the actual array is not <code>null</code> or not empty.
154       */
155      public final void isNullOrEmpty() {
156        if (actual == null || actualGroupSize() == 0) return;
157        failIfCustomMessageIsSet();
158        fail(concat("expecting a null or empty array, but was:", actualInBrackets()));
159      }
160    
161      /**
162       * Verifies that the actual array contains at least on element.
163       * @throws AssertionError if the actual array is <code>null</code>.
164       * @throws AssertionError if the actual array is empty.
165       */
166      protected final void assertThatActualIsNotEmpty() {
167        if (actualGroupSize() > 0) return;
168        failIfCustomMessageIsSet();
169        fail("expecting a non-empty array, but it was empty");
170      }
171    
172      /**
173       * Verifies that the number of elements in the actual array is equal to the given one.
174       * @param expected the expected number of elements in the actual array.
175       * @throws AssertionError if the actual array is <code>null</code>.
176       * @throws AssertionError if the number of elements in the actual array is not equal to the given one.
177       */
178      protected final void assertThatActualHasSize(int expected) {
179        int actualSize = actualGroupSize();
180        if (actualSize == expected) return;
181        failIfCustomMessageIsSet();
182        fail(concat(
183            "expected size:", inBrackets(expected)," but was:", inBrackets(actualSize), " for array:", actualInBrackets()));
184      }
185    }