OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * This library contains an Expect class with static methods that can be used | 6 * This library contains an Expect class with static methods that can be used |
7 * for simple unit-tests. | 7 * for simple unit-tests. |
8 */ | 8 */ |
9 library expect; | 9 library expect; |
10 | 10 |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 | 343 |
344 for (final val in extraSet) { | 344 for (final val in extraSet) { |
345 sb.write('$val '); | 345 sb.write('$val '); |
346 } | 346 } |
347 _fail(sb.toString()); | 347 _fail(sb.toString()); |
348 } | 348 } |
349 | 349 |
350 /** | 350 /** |
351 * Checks that [expected] is equivalent to [actual]. | 351 * Checks that [expected] is equivalent to [actual]. |
352 * | 352 * |
353 * If the objects are lists or maps, recurses into them. | 353 * If the objects are iterables or maps, recurses into them. |
354 */ | 354 */ |
355 static void deepEquals(Object expected, Object actual) { | 355 static void deepEquals(Object expected, Object actual) { |
356 // Early exit check for equality. | 356 // Early exit check for equality. |
357 if (expected == actual) return; | 357 if (expected == actual) return; |
358 | 358 |
359 if (expected is List && actual is List) { | 359 if (expected is String && actual is String) { |
360 int n = | 360 stringEquals(expected, actual); |
361 (expected.length < actual.length) ? expected.length : actual.length; | 361 } else if (expected is Iterable && actual is Iterable) { |
362 for (int i = 0; i < n; i++) { | 362 var expectedLength = expected.length; |
363 deepEquals(expected[i], actual[i]); | 363 var actualLength = actual.length; |
| 364 |
| 365 var length = |
| 366 expectedLength < actualLength ? expectedLength : actualLength; |
| 367 for (var i = 0; i < length; i++) { |
| 368 deepEquals(expected.elementAt(i), actual.elementAt(i)); |
364 } | 369 } |
365 | 370 |
366 // We check on length at the end in order to provide better error | 371 // We check on length at the end in order to provide better error |
367 // messages when an unexpected item is inserted in a list. | 372 // messages when an unexpected item is inserted in a list. |
368 if (expected.length != actual.length) { | 373 if (expectedLength != actualLength) { |
| 374 var nextElement = |
| 375 (expectedLength > length ? expected : actual).elementAt(length); |
369 _fail('Expect.deepEquals(list length, ' | 376 _fail('Expect.deepEquals(list length, ' |
370 'expected: <${expected.length}>, actual: <${actual.length}>) ' | 377 'expected: <$expectedLength>, actual: <$actualLength>) ' |
371 'fails: Next element <' | 378 'fails: Next element <$nextElement>'); |
372 '${expected.length > n ? expected[n] : actual[n]}>'); | |
373 } | 379 } |
374 } else if (expected is Map && actual is Map) { | 380 } else if (expected is Map && actual is Map) { |
375 // Make sure all of the values are present in both and match. | 381 // Make sure all of the values are present in both and match. |
376 for (final key in expected.keys) { | 382 for (final key in expected.keys) { |
377 if (!actual.containsKey(key)) { | 383 if (!actual.containsKey(key)) { |
378 _fail('Expect.deepEquals(missing expected key: <$key>) fails'); | 384 _fail('Expect.deepEquals(missing expected key: <$key>) fails'); |
379 } | 385 } |
380 | 386 |
381 Expect.deepEquals(expected[key], actual[key]); | 387 Expect.deepEquals(expected[key], actual[key]); |
382 } | 388 } |
383 | 389 |
384 // Make sure the actual map doesn't have any extra keys. | 390 // Make sure the actual map doesn't have any extra keys. |
385 for (final key in actual.keys) { | 391 for (final key in actual.keys) { |
386 if (!expected.containsKey(key)) { | 392 if (!expected.containsKey(key)) { |
387 _fail('Expect.deepEquals(unexpected key: <$key>) fails'); | 393 _fail('Expect.deepEquals(unexpected key: <$key>) fails'); |
388 } | 394 } |
389 } | 395 } |
390 } else if (expected is String && actual is String) { | |
391 String stringDifference = _stringDifference(expected, actual); | |
392 // If we get here, they should not be equal. | |
393 assert(stringDifference != null); | |
394 _fail("Expect.deepEquals($stringDifference) fails."); | |
395 } else { | 396 } else { |
396 _fail("Expect.deepEquals(expected: <$expected>, actual: <$actual>) " | 397 _fail("Expect.deepEquals(expected: <$expected>, actual: <$actual>) " |
397 "fails."); | 398 "fails."); |
398 } | 399 } |
399 } | 400 } |
400 | 401 |
401 /** | 402 /** |
402 * Calls the function [f] and verifies that it throws an exception. | 403 * Calls the function [f] and verifies that it throws an exception. |
403 * The optional [check] function can provide additional validation | 404 * The optional [check] function can provide additional validation |
404 * that the correct exception is being thrown. For example, to check | 405 * that the correct exception is being thrown. For example, to check |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 const TrustTypeAnnotations(); | 467 const TrustTypeAnnotations(); |
467 } | 468 } |
468 | 469 |
469 /// Annotation class for testing of dart2js. Use this as metadata on method | 470 /// Annotation class for testing of dart2js. Use this as metadata on method |
470 /// declarations to disable closed world assumptions on parameters, effectively | 471 /// declarations to disable closed world assumptions on parameters, effectively |
471 /// assuming that the runtime arguments could be any value. Note that the | 472 /// assuming that the runtime arguments could be any value. Note that the |
472 /// constraints due to [TrustTypeAnnotations] still apply. | 473 /// constraints due to [TrustTypeAnnotations] still apply. |
473 class AssumeDynamic { | 474 class AssumeDynamic { |
474 const AssumeDynamic(); | 475 const AssumeDynamic(); |
475 } | 476 } |
OLD | NEW |