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 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 663 } | 663 } |
| 664 | 664 |
| 665 Command getModifyPubspecCommand(String pubspecYamlFile, Map depsOverrides, | 665 Command getModifyPubspecCommand(String pubspecYamlFile, Map depsOverrides, |
| 666 {String destinationFile: null}) { | 666 {String destinationFile: null}) { |
| 667 if (destinationFile == null) destinationFile = pubspecYamlFile; | 667 if (destinationFile == null) destinationFile = pubspecYamlFile; |
| 668 return _getUniqueCommand(new ModifyPubspecYamlCommand._( | 668 return _getUniqueCommand(new ModifyPubspecYamlCommand._( |
| 669 pubspecYamlFile, destinationFile, depsOverrides)); | 669 pubspecYamlFile, destinationFile, depsOverrides)); |
| 670 } | 670 } |
| 671 | 671 |
| 672 Command _getUniqueCommand(Command command) { | 672 Command _getUniqueCommand(Command command) { |
| 673 // All Command classes have hashCode/operator==, so we check if this command | 673 // All Command classes implement hashCode and operator==. |
| 674 // has already been build, if so we return the cached one, otherwise we | 674 // We check if this command has already been built. |
| 675 // If so, we return the cached one. Otherwise we | |
| 675 // store the one given as [command] argument. | 676 // store the one given as [command] argument. |
| 676 var cachedCommand = _cachedCommands[command]; | 677 var cachedCommand = _cachedCommands[command]; |
| 677 if (cachedCommand != null) { | 678 if (cachedCommand != null) { |
| 678 return cachedCommand; | 679 return cachedCommand; |
| 679 } | 680 } |
| 680 _cachedCommands[command] = command; | 681 _cachedCommands[command] = command; |
| 681 return command; | 682 return command; |
| 682 } | 683 } |
| 683 } | 684 } |
| 684 | 685 |
| (...skipping 982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1667 command, exitCode, timedOut, stdout, stderr, time); | 1668 command, exitCode, timedOut, stdout, stderr, time); |
| 1668 } | 1669 } |
| 1669 | 1670 |
| 1670 return new CommandOutputImpl( | 1671 return new CommandOutputImpl( |
| 1671 command, exitCode, timedOut, stdout, stderr, | 1672 command, exitCode, timedOut, stdout, stderr, |
| 1672 time, compilationSkipped, pid); | 1673 time, compilationSkipped, pid); |
| 1673 } | 1674 } |
| 1674 | 1675 |
| 1675 | 1676 |
| 1676 /** | 1677 /** |
| 1678 * An OutputLog records the output from a test, but truncates it if | |
| 1679 * it is longer than MAX_HEAD characters, and just keeps the head and | |
| 1680 * the last TAIL_LENGTH characters of the output. | |
| 1681 */ | |
| 1682 class OutputLog { | |
| 1683 static const int MAX_HEAD = 100 * 1024; | |
| 1684 static const int TAIL_LENGTH = 10 * 1024; | |
| 1685 List<int> head = <int>[]; | |
| 1686 List<int> tail; | |
| 1687 List<int> complete; | |
| 1688 bool dataDropped = false; | |
| 1689 | |
| 1690 OutputLog(); | |
| 1691 | |
| 1692 void add(List<int> data) { | |
| 1693 if (complete != null) { | |
| 1694 throw new StateError("Cannot add to OutputLog after calling toList"); | |
| 1695 } | |
| 1696 if (tail == null) { | |
| 1697 head.addAll(data); | |
| 1698 if (head.length > MAX_HEAD) { | |
| 1699 tail = head.sublist(MAX_HEAD); | |
| 1700 head.length = MAX_HEAD; | |
|
Ivan Posva
2014/04/10 00:10:44
This is making matters actually worse, ending up u
Bill Hesse
2014/04/11 07:39:48
These variables are only live while the test is ru
| |
| 1701 } | |
| 1702 } else { | |
| 1703 tail.addAll(data); | |
| 1704 } | |
| 1705 if (tail != null && tail.length > 2 * TAIL_LENGTH) { | |
| 1706 tail = _truncatedTail(); | |
| 1707 dataDropped = true; | |
| 1708 } | |
| 1709 } | |
| 1710 | |
| 1711 List<int> _truncatedTail() => | |
| 1712 tail.length > TAIL_LENGTH ? | |
| 1713 tail.sublist(tail.length - TAIL_LENGTH) : | |
| 1714 tail; | |
| 1715 | |
| 1716 List<int> toList() { | |
| 1717 if (complete == null) { | |
| 1718 complete = head; | |
| 1719 if (dataDropped) { | |
| 1720 complete.addAll(""" | |
| 1721 | |
| 1722 ***************************************************************************** | |
| 1723 | |
| 1724 Data removed due to excessive length | |
| 1725 | |
| 1726 ***************************************************************************** | |
| 1727 | |
| 1728 """.codeUnits); | |
| 1729 complete.addAll(_truncatedTail()); | |
| 1730 } else if (tail != null) { | |
| 1731 complete.addAll(tail); | |
| 1732 } | |
| 1733 head = null; | |
| 1734 tail = null; | |
| 1735 } | |
| 1736 return complete; | |
| 1737 } | |
| 1738 } | |
| 1739 | |
| 1740 /** | |
| 1677 * A RunningProcess actually runs a test, getting the command lines from | 1741 * A RunningProcess actually runs a test, getting the command lines from |
| 1678 * its [TestCase], starting the test process (and first, a compilation | 1742 * its [TestCase], starting the test process (and first, a compilation |
| 1679 * process if the TestCase is a [BrowserTestCase]), creating a timeout | 1743 * process if the TestCase is a [BrowserTestCase]), creating a timeout |
| 1680 * timer, and recording the results in a new [CommandOutput] object, which it | 1744 * timer, and recording the results in a new [CommandOutput] object, which it |
| 1681 * attaches to the TestCase. The lifetime of the RunningProcess is limited | 1745 * attaches to the TestCase. The lifetime of the RunningProcess is limited |
| 1682 * to the time it takes to start the process, run the process, and record | 1746 * to the time it takes to start the process, run the process, and record |
| 1683 * the result; there are no pointers to it, so it should be available to | 1747 * the result; there are no pointers to it, so it should be available to |
| 1684 * be garbage collected as soon as it is done. | 1748 * be garbage collected as soon as it is done. |
| 1685 */ | 1749 */ |
| 1686 class RunningProcess { | 1750 class RunningProcess { |
| 1687 ProcessCommand command; | 1751 ProcessCommand command; |
| 1688 int timeout; | 1752 int timeout; |
| 1689 bool timedOut = false; | 1753 bool timedOut = false; |
| 1690 DateTime startTime; | 1754 DateTime startTime; |
| 1691 Timer timeoutTimer; | 1755 Timer timeoutTimer; |
| 1692 int pid; | 1756 int pid; |
| 1693 List<int> stdout = <int>[]; | 1757 OutputLog stdout = new OutputLog(); |
| 1694 List<int> stderr = <int>[]; | 1758 OutputLog stderr = new OutputLog(); |
| 1695 bool compilationSkipped = false; | 1759 bool compilationSkipped = false; |
| 1696 Completer<CommandOutput> completer; | 1760 Completer<CommandOutput> completer; |
| 1697 | 1761 |
| 1698 RunningProcess(this.command, this.timeout); | 1762 RunningProcess(this.command, this.timeout); |
| 1699 | 1763 |
| 1700 Future<CommandOutput> run() { | 1764 Future<CommandOutput> run() { |
| 1701 completer = new Completer<CommandOutput>(); | 1765 completer = new Completer<CommandOutput>(); |
| 1702 startTime = new DateTime.now(); | 1766 startTime = new DateTime.now(); |
| 1703 _runCommand(); | 1767 _runCommand(); |
| 1704 return completer.future; | 1768 return completer.future; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1807 } | 1871 } |
| 1808 var commandOutput = _createCommandOutput(command, exitCode); | 1872 var commandOutput = _createCommandOutput(command, exitCode); |
| 1809 completer.complete(commandOutput); | 1873 completer.complete(commandOutput); |
| 1810 } | 1874 } |
| 1811 | 1875 |
| 1812 CommandOutput _createCommandOutput(ProcessCommand command, int exitCode) { | 1876 CommandOutput _createCommandOutput(ProcessCommand command, int exitCode) { |
| 1813 var commandOutput = createCommandOutput( | 1877 var commandOutput = createCommandOutput( |
| 1814 command, | 1878 command, |
| 1815 exitCode, | 1879 exitCode, |
| 1816 timedOut, | 1880 timedOut, |
| 1817 stdout, | 1881 stdout.toList(), |
| 1818 stderr, | 1882 stderr.toList(), |
| 1819 new DateTime.now().difference(startTime), | 1883 new DateTime.now().difference(startTime), |
| 1820 compilationSkipped, | 1884 compilationSkipped, |
| 1821 pid); | 1885 pid); |
| 1822 return commandOutput; | 1886 return commandOutput; |
| 1823 } | 1887 } |
| 1824 | 1888 |
| 1825 StreamSubscription _drainStream(Stream<List<int>> source, | 1889 StreamSubscription _drainStream(Stream<List<int>> source, |
| 1826 List<int> destination) { | 1890 OutputLog destination) { |
| 1827 return source.listen(destination.addAll); | 1891 return source.listen(destination.add); |
| 1828 } | 1892 } |
| 1829 | 1893 |
| 1830 Map<String, String> _createProcessEnvironment() { | 1894 Map<String, String> _createProcessEnvironment() { |
| 1831 var environment = new Map.from(io.Platform.environment); | 1895 var environment = new Map.from(io.Platform.environment); |
| 1832 | 1896 |
| 1833 if (command.environmentOverrides != null) { | 1897 if (command.environmentOverrides != null) { |
| 1834 for (var key in command.environmentOverrides.keys) { | 1898 for (var key in command.environmentOverrides.keys) { |
| 1835 environment[key] = command.environmentOverrides[key]; | 1899 environment[key] = command.environmentOverrides[key]; |
| 1836 } | 1900 } |
| 1837 } | 1901 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1868 | 1932 |
| 1869 io.Process _process; | 1933 io.Process _process; |
| 1870 Map _processEnvironmentOverrides; | 1934 Map _processEnvironmentOverrides; |
| 1871 Completer _stdoutCompleter; | 1935 Completer _stdoutCompleter; |
| 1872 Completer _stderrCompleter; | 1936 Completer _stderrCompleter; |
| 1873 StreamSubscription<String> _stdoutSubscription; | 1937 StreamSubscription<String> _stdoutSubscription; |
| 1874 StreamSubscription<String> _stderrSubscription; | 1938 StreamSubscription<String> _stderrSubscription; |
| 1875 Function _processExitHandler; | 1939 Function _processExitHandler; |
| 1876 | 1940 |
| 1877 bool _currentlyRunning = false; | 1941 bool _currentlyRunning = false; |
| 1878 List<int> _testStdout; | 1942 OutputLog _testStdout; |
| 1879 List<int> _testStderr; | 1943 OutputLog _testStderr; |
| 1880 String _status; | 1944 String _status; |
| 1881 DateTime _startTime; | 1945 DateTime _startTime; |
| 1882 Timer _timer; | 1946 Timer _timer; |
| 1883 | 1947 |
| 1884 BatchRunnerProcess(); | 1948 BatchRunnerProcess(); |
| 1885 | 1949 |
| 1886 Future<CommandOutput> runCommand(String runnerType, ProcessCommand command, | 1950 Future<CommandOutput> runCommand(String runnerType, ProcessCommand command, |
| 1887 int timeout, List<String> arguments) { | 1951 int timeout, List<String> arguments) { |
| 1888 assert(_completer == null); | 1952 assert(_completer == null); |
| 1889 assert(!_currentlyRunning); | 1953 assert(!_currentlyRunning); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1925 if (killTimer != null) killTimer.cancel(); | 1989 if (killTimer != null) killTimer.cancel(); |
| 1926 terminateCompleter.complete(true); | 1990 terminateCompleter.complete(true); |
| 1927 }; | 1991 }; |
| 1928 _process.kill(); | 1992 _process.kill(); |
| 1929 | 1993 |
| 1930 return terminateCompleter.future; | 1994 return terminateCompleter.future; |
| 1931 } | 1995 } |
| 1932 | 1996 |
| 1933 void doStartTest(Command command, int timeout) { | 1997 void doStartTest(Command command, int timeout) { |
| 1934 _startTime = new DateTime.now(); | 1998 _startTime = new DateTime.now(); |
| 1935 _testStdout = []; | 1999 _testStdout = new OutputLog(); |
| 1936 _testStderr = []; | 2000 _testStderr = new OutputLog(); |
| 1937 _status = null; | 2001 _status = null; |
| 1938 _stdoutCompleter = new Completer(); | 2002 _stdoutCompleter = new Completer(); |
| 1939 _stderrCompleter = new Completer(); | 2003 _stderrCompleter = new Completer(); |
| 1940 _timer = new Timer(new Duration(seconds: timeout), | 2004 _timer = new Timer(new Duration(seconds: timeout), |
| 1941 _timeoutHandler); | 2005 _timeoutHandler); |
| 1942 | 2006 |
| 1943 var line = _createArgumentsLine(_arguments, timeout); | 2007 var line = _createArgumentsLine(_arguments, timeout); |
| 1944 _process.stdin.write(line); | 2008 _process.stdin.write(line); |
| 1945 _stdoutSubscription.resume(); | 2009 _stdoutSubscription.resume(); |
| 1946 _stderrSubscription.resume(); | 2010 _stderrSubscription.resume(); |
| 1947 Future.wait([_stdoutCompleter.future, | 2011 Future.wait([_stdoutCompleter.future, |
| 1948 _stderrCompleter.future]).then((_) => _reportResult()); | 2012 _stderrCompleter.future]).then((_) => _reportResult()); |
| 1949 } | 2013 } |
| 1950 | 2014 |
| 1951 String _createArgumentsLine(List<String> arguments, int timeout) { | 2015 String _createArgumentsLine(List<String> arguments, int timeout) { |
| 1952 return arguments.join(' ') + '\n'; | 2016 return arguments.join(' ') + '\n'; |
| 1953 } | 2017 } |
| 1954 | 2018 |
| 1955 void _reportResult() { | 2019 void _reportResult() { |
| 1956 if (!_currentlyRunning) return; | 2020 if (!_currentlyRunning) return; |
| 1957 // _status == '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' | 2021 // _status == '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' |
| 1958 | 2022 |
| 1959 var outcome = _status.split(" ")[2]; | 2023 var outcome = _status.split(" ")[2]; |
| 1960 var exitCode = 0; | 2024 var exitCode = 0; |
| 1961 if (outcome == "CRASH") exitCode = CRASHING_BROWSER_EXITCODE; | 2025 if (outcome == "CRASH") exitCode = CRASHING_BROWSER_EXITCODE; |
| 1962 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; | 2026 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; |
| 1963 var output = createCommandOutput(_command, | 2027 var output = createCommandOutput(_command, |
| 1964 exitCode, | 2028 exitCode, |
| 1965 (outcome == "TIMEOUT"), | 2029 (outcome == "TIMEOUT"), |
| 1966 _testStdout, | 2030 _testStdout.toList(), |
| 1967 _testStderr, | 2031 _testStderr.toList(), |
| 1968 new DateTime.now().difference(_startTime), | 2032 new DateTime.now().difference(_startTime), |
| 1969 false); | 2033 false); |
| 1970 assert(_completer != null); | 2034 assert(_completer != null); |
| 1971 _completer.complete(output); | 2035 _completer.complete(output); |
| 1972 _completer = null; | 2036 _completer = null; |
| 1973 _currentlyRunning = false; | 2037 _currentlyRunning = false; |
| 1974 } | 2038 } |
| 1975 | 2039 |
| 1976 ExitCodeEvent makeExitHandler(String status) { | 2040 ExitCodeEvent makeExitHandler(String status) { |
| 1977 void handler(int exitCode) { | 2041 void handler(int exitCode) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2013 .transform(UTF8.decoder) | 2077 .transform(UTF8.decoder) |
| 2014 .transform(new LineSplitter()); | 2078 .transform(new LineSplitter()); |
| 2015 _stdoutSubscription = _stdoutStream.listen((String line) { | 2079 _stdoutSubscription = _stdoutStream.listen((String line) { |
| 2016 if (line.startsWith('>>> TEST')) { | 2080 if (line.startsWith('>>> TEST')) { |
| 2017 _status = line; | 2081 _status = line; |
| 2018 } else if (line.startsWith('>>> BATCH')) { | 2082 } else if (line.startsWith('>>> BATCH')) { |
| 2019 // ignore | 2083 // ignore |
| 2020 } else if (line.startsWith('>>> ')) { | 2084 } else if (line.startsWith('>>> ')) { |
| 2021 throw new Exception("Unexpected command from batch runner: '$line'."); | 2085 throw new Exception("Unexpected command from batch runner: '$line'."); |
| 2022 } else { | 2086 } else { |
| 2023 _testStdout.addAll(encodeUtf8(line)); | 2087 _testStdout.add(encodeUtf8(line)); |
| 2024 _testStdout.addAll("\n".codeUnits); | 2088 _testStdout.add("\n".codeUnits); |
| 2025 } | 2089 } |
| 2026 if (_status != null) { | 2090 if (_status != null) { |
| 2027 _stdoutSubscription.pause(); | 2091 _stdoutSubscription.pause(); |
| 2028 _timer.cancel(); | 2092 _timer.cancel(); |
| 2029 _stdoutCompleter.complete(null); | 2093 _stdoutCompleter.complete(null); |
| 2030 } | 2094 } |
| 2031 }); | 2095 }); |
| 2032 _stdoutSubscription.pause(); | 2096 _stdoutSubscription.pause(); |
| 2033 | 2097 |
| 2034 var _stderrStream = | 2098 var _stderrStream = |
| 2035 _process.stderr | 2099 _process.stderr |
| 2036 .transform(UTF8.decoder) | 2100 .transform(UTF8.decoder) |
| 2037 .transform(new LineSplitter()); | 2101 .transform(new LineSplitter()); |
| 2038 _stderrSubscription = _stderrStream.listen((String line) { | 2102 _stderrSubscription = _stderrStream.listen((String line) { |
| 2039 if (line.startsWith('>>> EOF STDERR')) { | 2103 if (line.startsWith('>>> EOF STDERR')) { |
| 2040 _stderrSubscription.pause(); | 2104 _stderrSubscription.pause(); |
| 2041 _stderrCompleter.complete(null); | 2105 _stderrCompleter.complete(null); |
| 2042 } else { | 2106 } else { |
| 2043 _testStderr.addAll(encodeUtf8(line)); | 2107 _testStderr.add(encodeUtf8(line)); |
| 2044 _testStderr.addAll("\n".codeUnits); | 2108 _testStderr.add("\n".codeUnits); |
| 2045 } | 2109 } |
| 2046 }); | 2110 }); |
| 2047 _stderrSubscription.pause(); | 2111 _stderrSubscription.pause(); |
| 2048 | 2112 |
| 2049 _processExitHandler = makeExitHandler(">>> TEST CRASH"); | 2113 _processExitHandler = makeExitHandler(">>> TEST CRASH"); |
| 2050 _process.exitCode.then((exitCode) { | 2114 _process.exitCode.then((exitCode) { |
| 2051 _processExitHandler(exitCode); | 2115 _processExitHandler(exitCode); |
| 2052 }); | 2116 }); |
| 2053 | 2117 |
| 2054 _process.stdin.done.catchError((err) { | 2118 _process.stdin.done.catchError((err) { |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2870 } | 2934 } |
| 2871 } | 2935 } |
| 2872 | 2936 |
| 2873 void eventAllTestsDone() { | 2937 void eventAllTestsDone() { |
| 2874 for (var listener in _eventListener) { | 2938 for (var listener in _eventListener) { |
| 2875 listener.allDone(); | 2939 listener.allDone(); |
| 2876 } | 2940 } |
| 2877 _allDone(); | 2941 _allDone(); |
| 2878 } | 2942 } |
| 2879 } | 2943 } |
| OLD | NEW |