Chromium Code Reviews| 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 * Classes and methods for executing tests. | 6 * Classes and methods for executing tests. |
| 7 * | 7 * |
| 8 * This module includes: | 8 * This module includes: |
| 9 * - Managing parallel execution of tests, including timeout checks. | 9 * - Managing parallel execution of tests, including timeout checks. |
| 10 * - Evaluating the output of each test as pass/fail/crash/timeout. | 10 * - Evaluating the output of each test as pass/fail/crash/timeout. |
| (...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 715 * A list of commands to execute. Most test cases have a single command. | 715 * A list of commands to execute. Most test cases have a single command. |
| 716 * Dart2js tests have two commands, one to compile the source and another | 716 * Dart2js tests have two commands, one to compile the source and another |
| 717 * to execute it. Some isolate tests might even have three, if they require | 717 * to execute it. Some isolate tests might even have three, if they require |
| 718 * compiling multiple sources that are run in isolation. | 718 * compiling multiple sources that are run in isolation. |
| 719 */ | 719 */ |
| 720 List<Command> commands; | 720 List<Command> commands; |
| 721 Map<Command, CommandOutput> commandOutputs = new Map<Command,CommandOutput>(); | 721 Map<Command, CommandOutput> commandOutputs = new Map<Command,CommandOutput>(); |
| 722 | 722 |
| 723 Map configuration; | 723 Map configuration; |
| 724 String displayName; | 724 String displayName; |
| 725 bool isNegative; | 725 static final int IS_NEGATIVE = 1 << 0; |
|
ricow1
2014/04/23 17:49:36
put all these in a seperate section instead of in
| |
| 726 static final int HAS_RUNTIME_ERROR = 1 << 1; | |
| 727 static final int HAS_STATIC_WARNING = 1 << 2; | |
| 728 static final int IS_NEGATIVE_IF_CHECKED = 1 << 3; | |
| 729 static final int HAS_COMPILE_ERROR = 1 << 4; | |
| 730 static final int HAS_COMPILE_ERROR_IF_CHECKED = 1 << 5; | |
| 731 static final int EXPECT_COMPILE_ERROR = 1 << 6; | |
| 732 int _expectations = 0; | |
| 733 int hash = 0; | |
| 726 Set<Expectation> expectedOutcomes; | 734 Set<Expectation> expectedOutcomes; |
| 727 TestInformation info; | |
| 728 | 735 |
| 729 TestCase(this.displayName, | 736 TestCase(this.displayName, |
| 730 this.commands, | 737 this.commands, |
| 731 this.configuration, | 738 this.configuration, |
| 732 this.expectedOutcomes, | 739 this.expectedOutcomes, |
| 733 {this.isNegative: false, | 740 {isNegative: false, |
| 734 this.info: null}) { | 741 TestInformation info: null}) { |
| 735 if (!isNegative) { | 742 if (isNegative || displayName.contains("negative_test")) { |
| 736 this.isNegative = displayName.contains("negative_test"); | 743 _expectations |= IS_NEGATIVE; |
| 744 } | |
| 745 // We don't want to keep the entire (large) TestInformation structure. | |
| 746 if (info != null) { | |
| 747 if (info.hasRuntimeError) _expectations |= HAS_RUNTIME_ERROR; | |
| 748 if (info.hasStaticWarning) _expectations |= HAS_STATIC_WARNING; | |
| 749 if (info.isNegativeIfChecked) _expectations |= IS_NEGATIVE_IF_CHECKED; | |
| 750 if (info.hasCompileError) _expectations |= HAS_COMPILE_ERROR; | |
| 751 if (info.hasCompileErrorIfChecked) { | |
| 752 _expectations |= HAS_COMPILE_ERROR_IF_CHECKED; | |
| 753 } | |
| 754 if (info.hasCompileError || | |
| 755 (configuration['checked'] && info.hasCompileErrorIfChecked)) { | |
| 756 _expectations |= EXPECT_COMPILE_ERROR; | |
| 757 } | |
|
ricow1
2014/04/23 17:49:36
extract the above to a method, setExpectationsFrom
| |
| 758 hash = info.originTestPath.relativeTo(TestUtils.dartDir) | |
| 759 .toString().hashCode; | |
| 737 } | 760 } |
| 738 } | 761 } |
| 739 | 762 |
| 740 /// Returns `true` if this test case should result in a compile-time error, | 763 bool get isNegative => _expectations & IS_NEGATIVE != 0; |
| 741 /// either unconditionally or if the configuration is 'checked'. | 764 bool get hasRuntimeError => _expectations & HAS_RUNTIME_ERROR != 0; |
| 742 bool get expectCompileError { | 765 bool get hasStaticWarning => _expectations & HAS_STATIC_WARNING != 0; |
| 743 if (info == null) return false; | 766 bool get isNegativeIfChecked => _expectations & IS_NEGATIVE_IF_CHECKED != 0; |
| 744 return info.hasCompileError || | 767 bool get hasCompileError => _expectations & HAS_COMPILE_ERROR != 0; |
| 745 (configuration['checked'] && info.hasCompileErrorIfChecked); | 768 bool get hasCompileErrorIfChecked => |
| 746 } | 769 _expectations & HAS_COMPILE_ERROR_IF_CHECKED != 0; |
| 770 bool get expectCompileError => _expectations & EXPECT_COMPILE_ERROR != 0; | |
| 747 | 771 |
| 748 bool get unexpectedOutput { | 772 bool get unexpectedOutput { |
| 749 var outcome = lastCommandOutput.result(this); | 773 var outcome = lastCommandOutput.result(this); |
| 750 return !expectedOutcomes.any((expectation) { | 774 return !expectedOutcomes.any((expectation) { |
| 751 return outcome.canBeOutcomeOf(expectation); | 775 return outcome.canBeOutcomeOf(expectation); |
| 752 }); | 776 }); |
| 753 } | 777 } |
| 754 | 778 |
| 755 Expectation get result => lastCommandOutput.result(this); | 779 Expectation get result => lastCommandOutput.result(this); |
| 756 | 780 |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1013 } | 1037 } |
| 1014 } | 1038 } |
| 1015 | 1039 |
| 1016 Expectation result(TestCase testCase) { | 1040 Expectation result(TestCase testCase) { |
| 1017 // Handle crashes and timeouts first | 1041 // Handle crashes and timeouts first |
| 1018 if (hasCrashed) return Expectation.CRASH; | 1042 if (hasCrashed) return Expectation.CRASH; |
| 1019 if (hasTimedOut) return Expectation.TIMEOUT; | 1043 if (hasTimedOut) return Expectation.TIMEOUT; |
| 1020 | 1044 |
| 1021 var outcome = _getOutcome(); | 1045 var outcome = _getOutcome(); |
| 1022 | 1046 |
| 1023 if (testCase.info != null && testCase.info.hasRuntimeError) { | 1047 if (testCase.hasRuntimeError) { |
| 1024 if (!outcome.canBeOutcomeOf(Expectation.RUNTIME_ERROR)) { | 1048 if (!outcome.canBeOutcomeOf(Expectation.RUNTIME_ERROR)) { |
| 1025 return Expectation.MISSING_RUNTIME_ERROR; | 1049 return Expectation.MISSING_RUNTIME_ERROR; |
| 1026 } | 1050 } |
| 1027 } | 1051 } |
| 1028 if (testCase.isNegative) { | 1052 if (testCase.isNegative) { |
| 1029 if (outcome.canBeOutcomeOf(Expectation.FAIL)) return Expectation.PASS; | 1053 if (outcome.canBeOutcomeOf(Expectation.FAIL)) return Expectation.PASS; |
| 1030 return Expectation.FAIL; | 1054 return Expectation.FAIL; |
| 1031 } | 1055 } |
| 1032 return outcome; | 1056 return outcome; |
| 1033 } | 1057 } |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1356 : super(command, 0, result.didTimeout, stdout, stderr, result.duration, | 1380 : super(command, 0, result.didTimeout, stdout, stderr, result.duration, |
| 1357 false, 0) { | 1381 false, 0) { |
| 1358 _result = result; | 1382 _result = result; |
| 1359 } | 1383 } |
| 1360 | 1384 |
| 1361 Expectation result(TestCase testCase) { | 1385 Expectation result(TestCase testCase) { |
| 1362 // Handle timeouts first | 1386 // Handle timeouts first |
| 1363 if (_result.didTimeout) return Expectation.TIMEOUT; | 1387 if (_result.didTimeout) return Expectation.TIMEOUT; |
| 1364 | 1388 |
| 1365 // Multitests are handled specially | 1389 // Multitests are handled specially |
| 1366 if (testCase.info != null) { | 1390 if (testCase.hasRuntimeError) { |
| 1367 if (testCase.info.hasRuntimeError) { | 1391 if (_rawOutcome == Expectation.RUNTIME_ERROR) return Expectation.PASS; |
| 1368 if (_rawOutcome == Expectation.RUNTIME_ERROR) return Expectation.PASS; | 1392 return Expectation.MISSING_RUNTIME_ERROR; |
| 1369 return Expectation.MISSING_RUNTIME_ERROR; | |
| 1370 } | |
| 1371 } | 1393 } |
| 1372 | 1394 |
| 1373 return _negateOutcomeIfNegativeTest(_rawOutcome, testCase.isNegative); | 1395 return _negateOutcomeIfNegativeTest(_rawOutcome, testCase.isNegative); |
| 1374 } | 1396 } |
| 1375 } | 1397 } |
| 1376 | 1398 |
| 1377 | 1399 |
| 1378 class AnalysisCommandOutputImpl extends CommandOutputImpl { | 1400 class AnalysisCommandOutputImpl extends CommandOutputImpl { |
| 1379 // An error line has 8 fields that look like: | 1401 // An error line has 8 fields that look like: |
| 1380 // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source. | 1402 // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source. |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1407 // Handle crashes and timeouts first | 1429 // Handle crashes and timeouts first |
| 1408 if (hasCrashed) return Expectation.CRASH; | 1430 if (hasCrashed) return Expectation.CRASH; |
| 1409 if (hasTimedOut) return Expectation.TIMEOUT; | 1431 if (hasTimedOut) return Expectation.TIMEOUT; |
| 1410 | 1432 |
| 1411 // Get the errors/warnings from the analyzer | 1433 // Get the errors/warnings from the analyzer |
| 1412 List<String> errors = []; | 1434 List<String> errors = []; |
| 1413 List<String> warnings = []; | 1435 List<String> warnings = []; |
| 1414 parseAnalyzerOutput(errors, warnings); | 1436 parseAnalyzerOutput(errors, warnings); |
| 1415 | 1437 |
| 1416 // Handle errors / missing errors | 1438 // Handle errors / missing errors |
| 1417 if (testCase.info.hasCompileError) { | 1439 if (testCase.hasCompileError) { |
| 1418 // Don't use [TestCase.expectCompileError] since the analyzer does not | 1440 // Don't use [TestCase.expectCompileError] since the analyzer does not |
| 1419 // (currently) report checked-mode only compile time errors. | 1441 // (currently) report checked-mode only compile time errors. |
| 1420 if (errors.length > 0) { | 1442 if (errors.length > 0) { |
| 1421 return Expectation.PASS; | 1443 return Expectation.PASS; |
| 1422 } | 1444 } |
| 1423 return Expectation.MISSING_COMPILETIME_ERROR; | 1445 return Expectation.MISSING_COMPILETIME_ERROR; |
| 1424 } | 1446 } |
| 1425 if (errors.length > 0) { | 1447 if (errors.length > 0) { |
| 1426 return Expectation.COMPILETIME_ERROR; | 1448 return Expectation.COMPILETIME_ERROR; |
| 1427 } | 1449 } |
| 1428 | 1450 |
| 1429 // Handle static warnings / missing static warnings | 1451 // Handle static warnings / missing static warnings |
| 1430 if (testCase.info.hasStaticWarning) { | 1452 if (testCase.hasStaticWarning) { |
| 1431 if (warnings.length > 0) { | 1453 if (warnings.length > 0) { |
| 1432 return Expectation.PASS; | 1454 return Expectation.PASS; |
| 1433 } | 1455 } |
| 1434 return Expectation.MISSING_STATIC_WARNING; | 1456 return Expectation.MISSING_STATIC_WARNING; |
| 1435 } | 1457 } |
| 1436 if (warnings.length > 0) { | 1458 if (warnings.length > 0) { |
| 1437 return Expectation.STATIC_WARNING; | 1459 return Expectation.STATIC_WARNING; |
| 1438 } | 1460 } |
| 1439 | 1461 |
| 1440 assert (errors.length == 0 && warnings.length == 0); | 1462 assert (errors.length == 0 && warnings.length == 0); |
| 1441 assert (!testCase.info.hasCompileError && | 1463 assert (!testCase.hasCompileError && |
| 1442 !testCase.info.hasStaticWarning); | 1464 !testCase.hasStaticWarning); |
| 1443 return Expectation.PASS; | 1465 return Expectation.PASS; |
| 1444 } | 1466 } |
| 1445 | 1467 |
| 1446 void parseAnalyzerOutput(List<String> outErrors, List<String> outWarnings) { | 1468 void parseAnalyzerOutput(List<String> outErrors, List<String> outWarnings) { |
| 1447 AnalysisCommand analysisCommand = command; | 1469 AnalysisCommand analysisCommand = command; |
| 1448 | 1470 |
| 1449 // Parse a line delimited by the | character using \ as an escape charager | 1471 // Parse a line delimited by the | character using \ as an escape charager |
| 1450 // like: FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ | 1472 // like: FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ |
| 1451 List<String> splitMachineError(String line) { | 1473 List<String> splitMachineError(String line) { |
| 1452 StringBuffer field = new StringBuffer(); | 1474 StringBuffer field = new StringBuffer(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1495 List<int> stdout, List<int> stderr, Duration time, | 1517 List<int> stdout, List<int> stderr, Duration time, |
| 1496 int pid) | 1518 int pid) |
| 1497 : super(command, exitCode, timedOut, stdout, stderr, time, false, pid); | 1519 : super(command, exitCode, timedOut, stdout, stderr, time, false, pid); |
| 1498 | 1520 |
| 1499 Expectation result(TestCase testCase) { | 1521 Expectation result(TestCase testCase) { |
| 1500 // Handle crashes and timeouts first | 1522 // Handle crashes and timeouts first |
| 1501 if (hasCrashed) return Expectation.CRASH; | 1523 if (hasCrashed) return Expectation.CRASH; |
| 1502 if (hasTimedOut) return Expectation.TIMEOUT; | 1524 if (hasTimedOut) return Expectation.TIMEOUT; |
| 1503 | 1525 |
| 1504 // Multitests are handled specially | 1526 // Multitests are handled specially |
| 1505 if (testCase.info != null) { | 1527 if (testCase.expectCompileError) { |
| 1506 if (testCase.expectCompileError) { | 1528 if (exitCode == DART_VM_EXITCODE_COMPILE_TIME_ERROR) { |
| 1507 if (exitCode == DART_VM_EXITCODE_COMPILE_TIME_ERROR) { | 1529 return Expectation.PASS; |
| 1508 return Expectation.PASS; | |
| 1509 } | |
| 1510 | |
| 1511 return Expectation.MISSING_COMPILETIME_ERROR; | |
| 1512 } | 1530 } |
| 1513 if (testCase.info.hasRuntimeError) { | 1531 return Expectation.MISSING_COMPILETIME_ERROR; |
| 1514 // TODO(kustermann): Do we consider a "runtimeError" only an uncaught | 1532 } |
| 1515 // exception or does any nonzero exit code fullfil this requirement? | 1533 if (testCase.hasRuntimeError) { |
| 1516 if (exitCode != 0) { | 1534 // TODO(kustermann): Do we consider a "runtimeError" only an uncaught |
| 1517 return Expectation.PASS; | 1535 // exception or does any nonzero exit code fullfil this requirement? |
| 1518 } | 1536 if (exitCode != 0) { |
| 1519 return Expectation.MISSING_RUNTIME_ERROR; | 1537 return Expectation.PASS; |
| 1520 } | 1538 } |
| 1539 return Expectation.MISSING_RUNTIME_ERROR; | |
| 1521 } | 1540 } |
| 1522 | 1541 |
| 1523 // The actual outcome depends on the exitCode | 1542 // The actual outcome depends on the exitCode |
| 1524 Expectation outcome; | 1543 Expectation outcome; |
| 1525 if (exitCode == DART_VM_EXITCODE_COMPILE_TIME_ERROR) { | 1544 if (exitCode == DART_VM_EXITCODE_COMPILE_TIME_ERROR) { |
| 1526 outcome = Expectation.COMPILETIME_ERROR; | 1545 outcome = Expectation.COMPILETIME_ERROR; |
| 1527 } else if (exitCode == DART_VM_EXITCODE_UNCAUGHT_EXCEPTION) { | 1546 } else if (exitCode == DART_VM_EXITCODE_UNCAUGHT_EXCEPTION) { |
| 1528 outcome = Expectation.RUNTIME_ERROR; | 1547 outcome = Expectation.RUNTIME_ERROR; |
| 1529 } else if (exitCode != 0) { | 1548 } else if (exitCode != 0) { |
| 1530 // This is a general fail, in case we get an unknown nonzero exitcode. | 1549 // This is a general fail, in case we get an unknown nonzero exitcode. |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1552 if (hasTimedOut) return Expectation.TIMEOUT; | 1571 if (hasTimedOut) return Expectation.TIMEOUT; |
| 1553 | 1572 |
| 1554 // Handle dart2js/dart2dart specific crash detection | 1573 // Handle dart2js/dart2dart specific crash detection |
| 1555 if (exitCode == DART2JS_EXITCODE_CRASH || | 1574 if (exitCode == DART2JS_EXITCODE_CRASH || |
| 1556 exitCode == VmCommandOutputImpl.DART_VM_EXITCODE_COMPILE_TIME_ERROR || | 1575 exitCode == VmCommandOutputImpl.DART_VM_EXITCODE_COMPILE_TIME_ERROR || |
| 1557 exitCode == VmCommandOutputImpl.DART_VM_EXITCODE_UNCAUGHT_EXCEPTION) { | 1576 exitCode == VmCommandOutputImpl.DART_VM_EXITCODE_UNCAUGHT_EXCEPTION) { |
| 1558 return Expectation.CRASH; | 1577 return Expectation.CRASH; |
| 1559 } | 1578 } |
| 1560 | 1579 |
| 1561 // Multitests are handled specially | 1580 // Multitests are handled specially |
| 1562 if (testCase.info != null) { | |
| 1563 if (testCase.expectCompileError) { | 1581 if (testCase.expectCompileError) { |
| 1564 // Nonzero exit code of the compiler means compilation failed | 1582 // Nonzero exit code of the compiler means compilation failed |
| 1565 // TODO(kustermann): Do we have a special exit code in that case??? | 1583 // TODO(kustermann): Do we have a special exit code in that case??? |
| 1566 if (exitCode != 0) { | 1584 if (exitCode != 0) { |
| 1567 return Expectation.PASS; | 1585 return Expectation.PASS; |
| 1568 } | |
| 1569 return Expectation.MISSING_COMPILETIME_ERROR; | |
| 1570 } | 1586 } |
| 1587 return Expectation.MISSING_COMPILETIME_ERROR; | |
| 1588 } | |
| 1571 | 1589 |
| 1572 // TODO(kustermann): This is a hack, remove it | 1590 // TODO(kustermann): This is a hack, remove it |
| 1573 if (testCase.info.hasRuntimeError && testCase.commands.length > 1) { | 1591 if (testCase.hasRuntimeError && testCase.commands.length > 1) { |
| 1574 // We expected to run the test, but we got an compile time error. | 1592 // We expected to run the test, but we got an compile time error. |
| 1575 // If the compilation succeeded, we wouldn't be in here! | 1593 // If the compilation succeeded, we wouldn't be in here! |
| 1576 assert(exitCode != 0); | 1594 assert(exitCode != 0); |
| 1577 return Expectation.COMPILETIME_ERROR; | 1595 return Expectation.COMPILETIME_ERROR; |
| 1578 } | |
| 1579 } | 1596 } |
| 1580 | 1597 |
| 1581 Expectation outcome = | 1598 Expectation outcome = |
| 1582 exitCode == 0 ? Expectation.PASS : Expectation.COMPILETIME_ERROR; | 1599 exitCode == 0 ? Expectation.PASS : Expectation.COMPILETIME_ERROR; |
| 1583 return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative); | 1600 return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative); |
| 1584 } | 1601 } |
| 1585 } | 1602 } |
| 1586 | 1603 |
| 1587 class JsCommandlineOutputImpl extends CommandOutputImpl | 1604 class JsCommandlineOutputImpl extends CommandOutputImpl |
| 1588 with UnittestSuiteMessagesMixin { | 1605 with UnittestSuiteMessagesMixin { |
| 1589 JsCommandlineOutputImpl(Command command, int exitCode, bool timedOut, | 1606 JsCommandlineOutputImpl(Command command, int exitCode, bool timedOut, |
| 1590 List<int> stdout, List<int> stderr, Duration time) | 1607 List<int> stdout, List<int> stderr, Duration time) |
| 1591 : super(command, exitCode, timedOut, stdout, stderr, time, false, 0); | 1608 : super(command, exitCode, timedOut, stdout, stderr, time, false, 0); |
| 1592 | 1609 |
| 1593 Expectation result(TestCase testCase) { | 1610 Expectation result(TestCase testCase) { |
| 1594 // Handle crashes and timeouts first | 1611 // Handle crashes and timeouts first |
| 1595 if (hasCrashed) return Expectation.CRASH; | 1612 if (hasCrashed) return Expectation.CRASH; |
| 1596 if (hasTimedOut) return Expectation.TIMEOUT; | 1613 if (hasTimedOut) return Expectation.TIMEOUT; |
| 1597 | 1614 |
| 1598 if (testCase.info != null && testCase.info.hasRuntimeError) { | 1615 if (testCase.hasRuntimeError) { |
| 1599 if (exitCode != 0) return Expectation.PASS; | 1616 if (exitCode != 0) return Expectation.PASS; |
| 1600 return Expectation.MISSING_RUNTIME_ERROR; | 1617 return Expectation.MISSING_RUNTIME_ERROR; |
| 1601 } | 1618 } |
| 1602 | 1619 |
| 1603 var outcome = exitCode == 0 ? Expectation.PASS : Expectation.RUNTIME_ERROR; | 1620 var outcome = exitCode == 0 ? Expectation.PASS : Expectation.RUNTIME_ERROR; |
| 1604 outcome = _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout)); | 1621 outcome = _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout)); |
| 1605 return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative); | 1622 return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative); |
| 1606 } | 1623 } |
| 1607 } | 1624 } |
| 1608 | 1625 |
| (...skipping 1338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2947 } | 2964 } |
| 2948 } | 2965 } |
| 2949 | 2966 |
| 2950 void eventAllTestsDone() { | 2967 void eventAllTestsDone() { |
| 2951 for (var listener in _eventListener) { | 2968 for (var listener in _eventListener) { |
| 2952 listener.allDone(); | 2969 listener.allDone(); |
| 2953 } | 2970 } |
| 2954 _allDone(); | 2971 _allDone(); |
| 2955 } | 2972 } |
| 2956 } | 2973 } |
| OLD | NEW |