001 /* 002 * Created on Mar 29, 2009 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 @2009 the original author or authors. 015 */ 016 package org.fest.assertions; 017 018 import static org.fest.assertions.Collections.found; 019 import static org.fest.assertions.Collections.notFound; 020 import static org.fest.assertions.Formatting.inBrackets; 021 import static org.fest.util.Collections.duplicatesFrom; 022 import static org.fest.util.Collections.list; 023 import static org.fest.util.Objects.areEqual; 024 import static org.fest.util.Strings.concat; 025 026 import java.util.ArrayList; 027 import java.util.Collection; 028 import java.util.List; 029 030 import org.fest.util.Collections; 031 032 /** 033 * Understands assertions for <code>{@link List}</code>s. To create a new instance of this class use the 034 * method <code>{@link Assertions#assertThat(List)}</code>. 035 * @since 1.1 036 * 037 * @author Alex Ruiz 038 */ 039 public class ListAssert extends GroupAssert<List<?>> { 040 041 /** 042 * Creates a new </code>{@link ListAssert}</code>. 043 * @param actual the target to verify. 044 */ 045 protected ListAssert(List<?> actual) { 046 super(actual); 047 } 048 049 /** 050 * Verifies that the actual <code>{@link List}</code> contains the given object at the given index. 051 * @param o the object to look for. 052 * @param index the index where the object should be stored in the actual <code>List</code>. 053 * @return this assertion object. 054 * @throws NullPointerException if the given <code>Index</code> is <code>null</code>. 055 * @throws IndexOutOfBoundsException if the value of the given <code>Index</code> is negative, or equal to or greater 056 * than the size of the actual <code>List</code>. 057 * @throws AssertionError if the given <code>List</code> does not contain the given object at the given index. 058 */ 059 public ListAssert contains(Object o, Index index) { 060 if (index == null) throw new NullPointerException(formattedErrorMessage("The given index should not be null")); 061 isNotNull().isNotEmpty(); 062 int indexValue = index.value(); 063 int listSize = actualGroupSize(); 064 if (indexValue < 0 || indexValue >= listSize) failIndexOutOfBounds(indexValue); 065 Object actualElement = actual.get(indexValue); 066 if (!areEqual(actualElement, o)) failElementNotFound(o, actualElement, indexValue); 067 return this; 068 } 069 070 private void failElementNotFound(Object e, Object a, int index) { 071 failIfCustomMessageIsSet(); 072 fail(concat("expecting ", inBrackets(e), " at index ", inBrackets(index), " but found ", inBrackets(a))); 073 } 074 075 private void failIndexOutOfBounds(int index) { 076 throw new IndexOutOfBoundsException( 077 formattedErrorMessage(concat( 078 "The index ", inBrackets(index), " should be greater than or equal to zero and less than ", actualGroupSize()))); 079 } 080 081 /** 082 * Verifies that the actual <code>{@link List}</code> contains the given sequence of objects, without any other 083 * objects between them. 084 * @param sequence the sequence of objects to look for. 085 * @return this assertion object. 086 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 087 * @throws AssertionError if the given array is <code>null</code>. 088 * @throws AssertionError if the actual <code>List</code> does not contain the given sequence of objects. 089 */ 090 public ListAssert containsSequence(Object...sequence) { 091 isNotNull(); 092 validateIsNotNull(sequence); 093 int sequenceSize = sequence.length; 094 if (sequenceSize == 0) return this; 095 int indexOfFirst = actual.indexOf(sequence[0]); 096 if (indexOfFirst == -1) failIfSequenceNotFound(sequence); 097 int listSize = actualGroupSize(); 098 for (int i = 0; i < sequenceSize; i++) { 099 int actualIndex = indexOfFirst + i; 100 if (actualIndex > listSize - 1) failIfSequenceNotFound(sequence); 101 if (!areEqual(sequence[i], actual.get(actualIndex))) failIfSequenceNotFound(sequence); 102 } 103 return this; 104 } 105 106 private void failIfSequenceNotFound(Object[] notFound) { 107 failIfCustomMessageIsSet(); 108 fail(concat("list:", inBrackets(actual), " does not contain the sequence:", inBrackets(notFound))); 109 } 110 111 /** 112 * Verifies that the actual <code>{@link List}</code> starts with the given sequence of objects, without any other 113 * objects between them. Same as <code>{@link #containsSequence}</code>, but verifies also that first given object is 114 * also first element of <code>List</code>. 115 * @param sequence the sequence of objects to look for. 116 * @return this assertion object. 117 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 118 * @throws AssertionError if the given array is <code>null</code>. 119 * @throws AssertionError if the actual <code>List</code> is not empty and with the given sequence of objects is 120 * empty. 121 * @throws AssertionError if the actual <code>List</code> does not start with the given sequence of objects. 122 */ 123 public ListAssert startsWith(Object...sequence) { 124 isNotNull(); 125 validateIsNotNull(sequence); 126 int sequenceSize = sequence.length; 127 int listSize = actualGroupSize(); 128 if (sequenceSize == 0 && listSize == 0) return this; 129 if (sequenceSize == 0 && listSize != 0) failIfNotStartingWithSequence(sequence); 130 if (listSize < sequenceSize) failIfNotStartingWithSequence(sequence); 131 for (int i = 0; i < sequenceSize; i++) 132 if (!areEqual(sequence[i], actual.get(i))) failIfNotStartingWithSequence(sequence); 133 return this; 134 } 135 136 private void failIfNotStartingWithSequence(Object[] notFound) { 137 failIfCustomMessageIsSet(); 138 fail(concat("list:", inBrackets(actual), " does not start with the sequence:", inBrackets(notFound))); 139 } 140 141 /** 142 * Verifies that the actual <code>{@link List}</code> ends with the given sequence of objects, without any other 143 * objects between them. Same as <code>{@link #containsSequence}</code>, but verifies also that last given object is 144 * also last element of <code>List</code>. 145 * @param sequence the sequence of objects to look for. 146 * @return this assertion object. 147 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 148 * @throws AssertionError if the given array is <code>null</code>. 149 * @throws AssertionError if the actual <code>List</code> is not empty and with the given sequence of objects is 150 * empty. 151 * @throws AssertionError if the actual <code>List</code> does not end with the given sequence of objects. 152 */ 153 public ListAssert endsWith(Object...sequence) { 154 isNotNull(); 155 validateIsNotNull(sequence); 156 int sequenceSize = sequence.length; 157 int listSize = actualGroupSize(); 158 if (sequenceSize == 0 && listSize == 0) return this; 159 if (sequenceSize == 0 && listSize != 0) failIfNotEndingWithSequence(sequence); 160 if (listSize < sequenceSize) failIfNotEndingWithSequence(sequence); 161 for (int i = 0; i < sequenceSize; i++) { 162 int sequenceIndex = sequenceSize - 1 - i; 163 int listIndex = listSize - 1 - i; 164 if (!areEqual(sequence[sequenceIndex], actual.get(listIndex))) failIfNotEndingWithSequence(sequence); 165 } 166 return this; 167 } 168 169 private void failIfNotEndingWithSequence(Object[] notFound) { 170 failIfCustomMessageIsSet(); 171 fail(concat("list:", inBrackets(actual), " does not end with the sequence:", inBrackets(notFound))); 172 } 173 174 /** 175 * Verifies that the actual <code>{@link List}</code> contains the given objects, in any order. 176 * @param objects the objects to look for. 177 * @return this assertion object. 178 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 179 * @throws NullPointerException if the given array is <code>null</code>. 180 * @throws AssertionError if the actual <code>List</code> does not contain the given objects. 181 */ 182 public ListAssert contains(Object...objects) { 183 isNotNull(); 184 validateIsNotNull(objects); 185 Collection<Object> notFound = notFoundInActual(objects); 186 if (notFound.isEmpty()) return this; 187 throw failureIfExpectedElementsNotFound(notFound); 188 } 189 190 private Collection<Object> notFoundInActual(Object... objects) { 191 return notFound(actual, objects); 192 } 193 194 /** 195 * Verifies that the actual <code>{@link List}</code> contains the given objects <strong>only</strong>, in any order. 196 * @param objects the objects to look for. 197 * @return this assertion object. 198 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 199 * @throws NullPointerException if the given array is <code>null</code>. 200 * @throws AssertionError if the actual <code>List</code> does not contain the given objects, or if the actual 201 * <code>List</code> contains elements other than the ones specified. 202 */ 203 public ListAssert containsOnly(Object...objects) { 204 isNotNull(); 205 validateIsNotNull(objects); 206 List<Object> copy = new ArrayList<Object>(actual); 207 List<Object> notFound = notFoundInCopy(copy, objects); 208 if (!notFound.isEmpty()) throw failureIfExpectedElementsNotFound(notFound); 209 if (copy.isEmpty()) return this; 210 throw failureIfUnexpectedElementsFound(copy); 211 } 212 213 private List<Object> notFoundInCopy(List<Object> copy, Object... objects) { 214 List<Object> notFound = new ArrayList<Object>(); 215 for (Object o : objects) { 216 if (!copy.contains(o)) { 217 notFound.add(o); 218 continue; 219 } 220 copy.remove(o); 221 } 222 return notFound; 223 } 224 225 private AssertionError failureIfExpectedElementsNotFound(Collection<Object> notFound) { 226 failIfCustomMessageIsSet(); 227 return failure(concat("list:", inBrackets(actual), " does not contain element(s):", inBrackets(notFound))); 228 } 229 230 private AssertionError failureIfUnexpectedElementsFound(List<Object> unexpected) { 231 failIfCustomMessageIsSet(); 232 return failure(concat("unexpected element(s):", inBrackets(unexpected), " in list:", inBrackets(actual))); 233 } 234 235 /** 236 * Verifies that the actual <code>{@link List}</code> does not contain the given objects. 237 * @param objects the objects that the <code>List</code> should exclude. 238 * @return this assertion object. 239 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 240 * @throws NullPointerException if the given array is <code>null</code>. 241 * @throws AssertionError if the actual <code>List</code> contains any of the given objects. 242 */ 243 public ListAssert excludes(Object...objects) { 244 isNotNull(); 245 validateIsNotNull(objects); 246 Collection<Object> found = found(actual, objects); 247 if (found.isEmpty()) return this; 248 failIfCustomMessageIsSet(); 249 throw failure(concat("list:", inBrackets(actual), " does not exclude element(s):", inBrackets(found))); 250 } 251 252 private void validateIsNotNull(Object[] objects) { 253 if (objects == null) 254 throw new NullPointerException(formattedErrorMessage("the given array of objects should not be null")); 255 } 256 257 /** 258 * Verifies that the actual <code>{@link List}</code> does not have duplicates. 259 * @return this assertion object. 260 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 261 * @throws AssertionError if the actual <code>List</code> has duplicates. 262 */ 263 public ListAssert doesNotHaveDuplicates() { 264 isNotNull(); 265 Collection<?> duplicates = duplicatesFrom(actual); 266 if (duplicates.isEmpty()) return this; 267 failIfCustomMessageIsSet(); 268 throw failure(concat("list:", inBrackets(actual), " contains duplicate(s):", inBrackets(duplicates))); 269 } 270 271 /** {@inheritDoc} */ 272 public ListAssert as(String description) { 273 description(description); 274 return this; 275 } 276 277 /** {@inheritDoc} */ 278 public ListAssert describedAs(String description) { 279 return as(description); 280 } 281 282 /** {@inheritDoc} */ 283 public ListAssert as(Description description) { 284 description(description); 285 return this; 286 } 287 288 /** {@inheritDoc} */ 289 public ListAssert describedAs(Description description) { 290 return as(description); 291 } 292 293 /** 294 * Verifies that the actual <code>{@link List}</code> satisfies the given condition. 295 * @param condition the given condition. 296 * @return this assertion object. 297 * @throws NullPointerException if the given condition is <code>null</code>. 298 * @throws AssertionError if the actual <code>List</code> does not satisfy the given condition. 299 * @see #is(Condition) 300 */ 301 public ListAssert satisfies(Condition<List<?>> condition) { 302 assertSatisfies(condition); 303 return this; 304 } 305 306 /** 307 * Verifies that the actual <code>{@link List}</code> does not satisfy the given condition. 308 * @param condition the given condition. 309 * @return this assertion object. 310 * @throws NullPointerException if the given condition is <code>null</code>. 311 * @throws AssertionError if the actual <code>List</code> satisfies the given condition. 312 * @see #isNot(Condition) 313 */ 314 public ListAssert doesNotSatisfy(Condition<List<?>> condition) { 315 assertDoesNotSatisfy(condition); 316 return this; 317 } 318 319 /** 320 * Alias for <code>{@link #satisfies(Condition)}</code>. 321 * @param condition the given condition. 322 * @return this assertion object. 323 * @throws NullPointerException if the given condition is <code>null</code>. 324 * @throws AssertionError if the actual <code>List</code> does not satisfy the given condition. 325 * @since 1.2 326 */ 327 public ListAssert is(Condition<List<?>> condition) { 328 assertIs(condition); 329 return this; 330 } 331 332 /** 333 * Alias for <code>{@link #doesNotSatisfy(Condition)}</code>. 334 * @param condition the given condition. 335 * @return this assertion object. 336 * @throws NullPointerException if the given condition is <code>null</code>. 337 * @throws AssertionError if the actual <code>List</code> satisfies the given condition. 338 * @since 1.2 339 */ 340 public ListAssert isNot(Condition<List<?>> condition) { 341 assertIsNot(condition); 342 return this; 343 } 344 345 /** 346 * Verifies that the number of elements in the actual <code>{@link List}</code> is equal to the given one. 347 * @param expected the expected number of elements in the actual <code>List</code>. 348 * @return this assertion object. 349 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 350 * @throws AssertionError if the number of elements of the actual <code>List</code> is not equal to the given one. 351 */ 352 public ListAssert hasSize(int expected) { 353 int actualSize = actualGroupSize(); 354 if (actualSize == expected) return this; 355 failIfCustomMessageIsSet(); 356 throw failure(concat( 357 "expected size:", inBrackets(expected)," but was:", inBrackets(actualSize), " for list:", inBrackets(actual))); 358 } 359 360 /** 361 * Returns the number of elements in the actual <code>{@link List}</code>. 362 * @return the number of elements in the actual <code>List</code>. 363 */ 364 protected int actualGroupSize() { 365 isNotNull(); 366 return actual.size(); 367 } 368 369 /** 370 * Verifies that the actual <code>{@link List}</code> is empty (not <code>null</code> with zero elements.) 371 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 372 * @throws AssertionError if the actual <code>List</code> is not empty. 373 */ 374 public void isEmpty() { 375 isNotNull(); 376 if (Collections.isEmpty(actual)) return; 377 failIfCustomMessageIsSet(); 378 fail(concat("expecting empty list, but was:", inBrackets(actual))); 379 } 380 381 /** 382 * Verifies that the actual <code>{@link List}</code> contains at least on element. 383 * @return this assertion object. 384 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 385 * @throws AssertionError if the actual <code>List</code> is empty. 386 */ 387 public ListAssert isNotEmpty() { 388 isNotNull(); 389 if (!actual.isEmpty()) return this; 390 failIfCustomMessageIsSet(); 391 throw failure("expecting a non-empty list, but it was empty"); 392 } 393 394 /** 395 * Verifies that the actual <code>{@link List}</code> is <code>null</code> or empty. 396 * @throws AssertionError if the actual <code>List</code> is not <code>null</code> or not empty. 397 */ 398 public void isNullOrEmpty() { 399 if (Collections.isEmpty(actual)) return; 400 failIfCustomMessageIsSet(); 401 fail(concat("expecting a null or empty list, but was:", inBrackets(actual))); 402 } 403 404 /** 405 * Verifies that the actual <code>{@link List}</code> is not <code>null</code>. 406 * @return this assertion object. 407 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 408 */ 409 public ListAssert isNotNull() { 410 if (actual != null) return this; 411 failIfCustomMessageIsSet(); 412 throw failure("expecting a non-null list, but it was null"); 413 } 414 415 /** 416 * Verifies that the actual <code>{@link List}</code> contains the given objects, in the same order. This method works 417 * just like <code>{@link #isEqualTo(List)}</code>, with the difference that internally the given array is 418 * converted to a <code>List</code>. 419 * @param objects the objects to look for. 420 * @return this assertion object. 421 * @throws AssertionError if the actual <code>List</code> is <code>null</code>. 422 * @throws NullPointerException if the given array is <code>null</code>. 423 * @throws AssertionError if the actual <code>List</code> does not contain the given objects. 424 */ 425 public ListAssert containsExactly(Object... objects) { 426 validateIsNotNull(objects); 427 return isNotNull().isEqualTo(list(objects)); 428 } 429 430 /** 431 * Verifies that the actual <code>{@link List}</code> is equal to the given one. 432 * @param expected the given <code>List</code> to compare the actual <code>List</code> to. 433 * @return this assertion object. 434 * @throws AssertionError if the actual <code>List</code> is not equal to the given one. 435 */ 436 public ListAssert isEqualTo(List<?> expected) { 437 assertEqualTo(expected); 438 return this; 439 } 440 441 /** 442 * Verifies that the actual <code>{@link List}</code> is not equal to the given one. 443 * @param other the given <code>List</code> to compare the actual <code>List</code> to. 444 * @return this assertion object. 445 * @throws AssertionError if the actual <code>List</code> is equal to the given one. 446 */ 447 public ListAssert isNotEqualTo(List<?> other) { 448 assertNotEqualTo(other); 449 return this; 450 } 451 452 /** 453 * Verifies that the actual <code>{@link List}</code> is the same as the given one. 454 * @param expected the given <code>List</code> to compare the actual <code>List</code> to. 455 * @return this assertion object. 456 * @throws AssertionError if the actual <code>List</code> is not the same as the given one. 457 */ 458 public ListAssert isSameAs(List<?> expected) { 459 assertSameAs(expected); 460 return this; 461 } 462 463 /** 464 * Verifies that the actual <code>{@link List}</code> is not the same as the given one. 465 * @param other the given <code>List</code> to compare the actual <code>List</code> to. 466 * @return this assertion object. 467 * @throws AssertionError if the actual <code>List</code> is the same as the given one. 468 */ 469 public ListAssert isNotSameAs(List<?> other) { 470 assertNotSameAs(other); 471 return this; 472 } 473 474 /** {@inheritDoc} */ 475 public ListAssert overridingErrorMessage(String message) { 476 replaceDefaultErrorMessagesWith(message); 477 return this; 478 } 479 }