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 972 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1657 command, exitCode, timedOut, stdout, stderr, time); | 1658 command, exitCode, timedOut, stdout, stderr, time); |
| 1658 } | 1659 } |
| 1659 | 1660 |
| 1660 return new CommandOutputImpl( | 1661 return new CommandOutputImpl( |
| 1661 command, exitCode, timedOut, stdout, stderr, | 1662 command, exitCode, timedOut, stdout, stderr, |
| 1662 time, compilationSkipped, pid); | 1663 time, compilationSkipped, pid); |
| 1663 } | 1664 } |
| 1664 | 1665 |
| 1665 | 1666 |
| 1666 /** | 1667 /** |
| 1668 * An OutputLog records the output from a test, but truncates it if | |
| 1669 * it is longer than MAX_HEAD characters, and just keeps the head and | |
| 1670 * the last TAIL_LENGTH characters of the output. | |
| 1671 */ | |
| 1672 class OutputLog { | |
| 1673 static const int MAX_HEAD = 100000; | |
| 1674 static const int TAIL_LENGTH = 20000; | |
|
kustermann
2014/04/08 15:23:47
I would make the limit lower and use 20 * 1024, so
Bill Hesse
2014/04/09 10:40:27
Done.
| |
| 1675 List<int> head = <int>[]; | |
| 1676 List<int> tail; | |
| 1677 bool dataDropped = false; | |
| 1678 | |
| 1679 OutputLog(); | |
| 1680 | |
| 1681 void add(List<int> data) { | |
| 1682 if (tail == null) { | |
| 1683 head.addAll(data); | |
| 1684 if (head.length > MAX_HEAD) { | |
| 1685 tail = head.sublist(MAX_HEAD); | |
| 1686 head.length = MAX_HEAD; | |
| 1687 } | |
| 1688 } else { | |
| 1689 tail.addAll(data); | |
| 1690 } | |
| 1691 if (tail != null && tail.length > 2 * TAIL_LENGTH) { | |
| 1692 tail = _truncatedTail(); | |
| 1693 dataDropped = true; | |
| 1694 } | |
| 1695 } | |
| 1696 | |
| 1697 List<int> _truncatedTail() => | |
| 1698 tail.length > TAIL_LENGTH ? | |
| 1699 tail.sublist(tail.length - TAIL_LENGTH) : | |
| 1700 tail; | |
| 1701 | |
| 1702 List<int> toList() { | |
| 1703 if (dataDropped) { | |
| 1704 head.addAll(""" | |
| 1705 | |
| 1706 ***************************************************************************** | |
| 1707 | |
| 1708 Data removed due to excessive length | |
| 1709 | |
| 1710 ***************************************************************************** | |
| 1711 | |
| 1712 """.codeUnits); | |
| 1713 head.addAll(_truncatedTail()); | |
| 1714 } else if (tail != null) { | |
| 1715 head.addAll(tail); | |
| 1716 } | |
| 1717 return head; | |
|
kustermann
2014/04/08 15:23:47
This will get confusing if you call toList() sever
Bill Hesse
2014/04/09 10:40:27
Done.
| |
| 1718 } | |
| 1719 } | |
| 1720 | |
| 1721 /** | |
| 1667 * A RunningProcess actually runs a test, getting the command lines from | 1722 * A RunningProcess actually runs a test, getting the command lines from |
| 1668 * its [TestCase], starting the test process (and first, a compilation | 1723 * its [TestCase], starting the test process (and first, a compilation |
| 1669 * process if the TestCase is a [BrowserTestCase]), creating a timeout | 1724 * process if the TestCase is a [BrowserTestCase]), creating a timeout |
| 1670 * timer, and recording the results in a new [CommandOutput] object, which it | 1725 * timer, and recording the results in a new [CommandOutput] object, which it |
| 1671 * attaches to the TestCase. The lifetime of the RunningProcess is limited | 1726 * attaches to the TestCase. The lifetime of the RunningProcess is limited |
| 1672 * to the time it takes to start the process, run the process, and record | 1727 * to the time it takes to start the process, run the process, and record |
| 1673 * the result; there are no pointers to it, so it should be available to | 1728 * the result; there are no pointers to it, so it should be available to |
| 1674 * be garbage collected as soon as it is done. | 1729 * be garbage collected as soon as it is done. |
| 1675 */ | 1730 */ |
| 1676 class RunningProcess { | 1731 class RunningProcess { |
| 1677 ProcessCommand command; | 1732 ProcessCommand command; |
| 1678 int timeout; | 1733 int timeout; |
| 1679 bool timedOut = false; | 1734 bool timedOut = false; |
| 1680 DateTime startTime; | 1735 DateTime startTime; |
| 1681 Timer timeoutTimer; | 1736 Timer timeoutTimer; |
| 1682 int pid; | 1737 int pid; |
| 1683 List<int> stdout = <int>[]; | 1738 OutputLog stdout = new OutputLog(); |
| 1684 List<int> stderr = <int>[]; | 1739 OutputLog stderr = new OutputLog(); |
| 1685 bool compilationSkipped = false; | 1740 bool compilationSkipped = false; |
| 1686 Completer<CommandOutput> completer; | 1741 Completer<CommandOutput> completer; |
| 1687 | 1742 |
| 1688 RunningProcess(this.command, this.timeout); | 1743 RunningProcess(this.command, this.timeout); |
| 1689 | 1744 |
| 1690 Future<CommandOutput> run() { | 1745 Future<CommandOutput> run() { |
| 1691 completer = new Completer<CommandOutput>(); | 1746 completer = new Completer<CommandOutput>(); |
| 1692 startTime = new DateTime.now(); | 1747 startTime = new DateTime.now(); |
| 1693 _runCommand(); | 1748 _runCommand(); |
| 1694 return completer.future; | 1749 return completer.future; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1797 } | 1852 } |
| 1798 var commandOutput = _createCommandOutput(command, exitCode); | 1853 var commandOutput = _createCommandOutput(command, exitCode); |
| 1799 completer.complete(commandOutput); | 1854 completer.complete(commandOutput); |
| 1800 } | 1855 } |
| 1801 | 1856 |
| 1802 CommandOutput _createCommandOutput(ProcessCommand command, int exitCode) { | 1857 CommandOutput _createCommandOutput(ProcessCommand command, int exitCode) { |
| 1803 var commandOutput = createCommandOutput( | 1858 var commandOutput = createCommandOutput( |
| 1804 command, | 1859 command, |
| 1805 exitCode, | 1860 exitCode, |
| 1806 timedOut, | 1861 timedOut, |
| 1807 stdout, | 1862 stdout.toList(), |
| 1808 stderr, | 1863 stderr.toList(), |
| 1809 new DateTime.now().difference(startTime), | 1864 new DateTime.now().difference(startTime), |
| 1810 compilationSkipped, | 1865 compilationSkipped, |
| 1811 pid); | 1866 pid); |
| 1812 return commandOutput; | 1867 return commandOutput; |
| 1813 } | 1868 } |
| 1814 | 1869 |
| 1815 StreamSubscription _drainStream(Stream<List<int>> source, | 1870 StreamSubscription _drainStream(Stream<List<int>> source, |
| 1816 List<int> destination) { | 1871 OutputLog destination) { |
| 1817 return source.listen(destination.addAll); | 1872 return source.listen(destination.add); |
| 1818 } | 1873 } |
| 1819 | 1874 |
| 1820 Map<String, String> _createProcessEnvironment() { | 1875 Map<String, String> _createProcessEnvironment() { |
| 1821 var environment = new Map.from(io.Platform.environment); | 1876 var environment = new Map.from(io.Platform.environment); |
| 1822 | 1877 |
| 1823 if (command.environmentOverrides != null) { | 1878 if (command.environmentOverrides != null) { |
| 1824 for (var key in command.environmentOverrides.keys) { | 1879 for (var key in command.environmentOverrides.keys) { |
| 1825 environment[key] = command.environmentOverrides[key]; | 1880 environment[key] = command.environmentOverrides[key]; |
| 1826 } | 1881 } |
| 1827 } | 1882 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1858 | 1913 |
| 1859 io.Process _process; | 1914 io.Process _process; |
| 1860 Map _processEnvironmentOverrides; | 1915 Map _processEnvironmentOverrides; |
| 1861 Completer _stdoutCompleter; | 1916 Completer _stdoutCompleter; |
| 1862 Completer _stderrCompleter; | 1917 Completer _stderrCompleter; |
| 1863 StreamSubscription<String> _stdoutSubscription; | 1918 StreamSubscription<String> _stdoutSubscription; |
| 1864 StreamSubscription<String> _stderrSubscription; | 1919 StreamSubscription<String> _stderrSubscription; |
| 1865 Function _processExitHandler; | 1920 Function _processExitHandler; |
| 1866 | 1921 |
| 1867 bool _currentlyRunning = false; | 1922 bool _currentlyRunning = false; |
| 1868 List<int> _testStdout; | 1923 OutputLog _testStdout; |
| 1869 List<int> _testStderr; | 1924 OutputLog _testStderr; |
| 1870 String _status; | 1925 String _status; |
| 1871 DateTime _startTime; | 1926 DateTime _startTime; |
| 1872 Timer _timer; | 1927 Timer _timer; |
| 1873 | 1928 |
| 1874 BatchRunnerProcess(); | 1929 BatchRunnerProcess(); |
| 1875 | 1930 |
| 1876 Future<CommandOutput> runCommand(String runnerType, ProcessCommand command, | 1931 Future<CommandOutput> runCommand(String runnerType, ProcessCommand command, |
| 1877 int timeout, List<String> arguments) { | 1932 int timeout, List<String> arguments) { |
| 1878 assert(_completer == null); | 1933 assert(_completer == null); |
| 1879 assert(!_currentlyRunning); | 1934 assert(!_currentlyRunning); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1915 if (killTimer != null) killTimer.cancel(); | 1970 if (killTimer != null) killTimer.cancel(); |
| 1916 terminateCompleter.complete(true); | 1971 terminateCompleter.complete(true); |
| 1917 }; | 1972 }; |
| 1918 _process.kill(); | 1973 _process.kill(); |
| 1919 | 1974 |
| 1920 return terminateCompleter.future; | 1975 return terminateCompleter.future; |
| 1921 } | 1976 } |
| 1922 | 1977 |
| 1923 void doStartTest(Command command, int timeout) { | 1978 void doStartTest(Command command, int timeout) { |
| 1924 _startTime = new DateTime.now(); | 1979 _startTime = new DateTime.now(); |
| 1925 _testStdout = []; | 1980 _testStdout = new OutputLog(); |
| 1926 _testStderr = []; | 1981 _testStderr = new OutputLog(); |
| 1927 _status = null; | 1982 _status = null; |
| 1928 _stdoutCompleter = new Completer(); | 1983 _stdoutCompleter = new Completer(); |
| 1929 _stderrCompleter = new Completer(); | 1984 _stderrCompleter = new Completer(); |
| 1930 _timer = new Timer(new Duration(seconds: timeout), | 1985 _timer = new Timer(new Duration(seconds: timeout), |
| 1931 _timeoutHandler); | 1986 _timeoutHandler); |
| 1932 | 1987 |
| 1933 var line = _createArgumentsLine(_arguments, timeout); | 1988 var line = _createArgumentsLine(_arguments, timeout); |
| 1934 _process.stdin.write(line); | 1989 _process.stdin.write(line); |
| 1935 _stdoutSubscription.resume(); | 1990 _stdoutSubscription.resume(); |
| 1936 _stderrSubscription.resume(); | 1991 _stderrSubscription.resume(); |
| 1937 Future.wait([_stdoutCompleter.future, | 1992 Future.wait([_stdoutCompleter.future, |
| 1938 _stderrCompleter.future]).then((_) => _reportResult()); | 1993 _stderrCompleter.future]).then((_) => _reportResult()); |
| 1939 } | 1994 } |
| 1940 | 1995 |
| 1941 String _createArgumentsLine(List<String> arguments, int timeout) { | 1996 String _createArgumentsLine(List<String> arguments, int timeout) { |
| 1942 return arguments.join(' ') + '\n'; | 1997 return arguments.join(' ') + '\n'; |
| 1943 } | 1998 } |
| 1944 | 1999 |
| 1945 void _reportResult() { | 2000 void _reportResult() { |
| 1946 if (!_currentlyRunning) return; | 2001 if (!_currentlyRunning) return; |
| 1947 // _status == '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' | 2002 // _status == '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' |
| 1948 | 2003 |
| 1949 var outcome = _status.split(" ")[2]; | 2004 var outcome = _status.split(" ")[2]; |
| 1950 var exitCode = 0; | 2005 var exitCode = 0; |
| 1951 if (outcome == "CRASH") exitCode = CRASHING_BROWSER_EXITCODE; | 2006 if (outcome == "CRASH") exitCode = CRASHING_BROWSER_EXITCODE; |
| 1952 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; | 2007 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; |
| 1953 var output = createCommandOutput(_command, | 2008 var output = createCommandOutput(_command, |
| 1954 exitCode, | 2009 exitCode, |
| 1955 (outcome == "TIMEOUT"), | 2010 (outcome == "TIMEOUT"), |
| 1956 _testStdout, | 2011 _testStdout.toList(), |
| 1957 _testStderr, | 2012 _testStderr.toList(), |
| 1958 new DateTime.now().difference(_startTime), | 2013 new DateTime.now().difference(_startTime), |
| 1959 false); | 2014 false); |
| 1960 assert(_completer != null); | 2015 assert(_completer != null); |
| 1961 _completer.complete(output); | 2016 _completer.complete(output); |
| 1962 _completer = null; | 2017 _completer = null; |
| 1963 _currentlyRunning = false; | 2018 _currentlyRunning = false; |
| 1964 } | 2019 } |
| 1965 | 2020 |
| 1966 ExitCodeEvent makeExitHandler(String status) { | 2021 ExitCodeEvent makeExitHandler(String status) { |
| 1967 void handler(int exitCode) { | 2022 void handler(int exitCode) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2003 .transform(UTF8.decoder) | 2058 .transform(UTF8.decoder) |
| 2004 .transform(new LineSplitter()); | 2059 .transform(new LineSplitter()); |
| 2005 _stdoutSubscription = _stdoutStream.listen((String line) { | 2060 _stdoutSubscription = _stdoutStream.listen((String line) { |
| 2006 if (line.startsWith('>>> TEST')) { | 2061 if (line.startsWith('>>> TEST')) { |
| 2007 _status = line; | 2062 _status = line; |
| 2008 } else if (line.startsWith('>>> BATCH')) { | 2063 } else if (line.startsWith('>>> BATCH')) { |
| 2009 // ignore | 2064 // ignore |
| 2010 } else if (line.startsWith('>>> ')) { | 2065 } else if (line.startsWith('>>> ')) { |
| 2011 throw new Exception("Unexpected command from batch runner: '$line'."); | 2066 throw new Exception("Unexpected command from batch runner: '$line'."); |
| 2012 } else { | 2067 } else { |
| 2013 _testStdout.addAll(encodeUtf8(line)); | 2068 _testStdout.add(encodeUtf8(line)); |
| 2014 _testStdout.addAll("\n".codeUnits); | 2069 _testStdout.add("\n".codeUnits); |
| 2015 } | 2070 } |
| 2016 if (_status != null) { | 2071 if (_status != null) { |
| 2017 _stdoutSubscription.pause(); | 2072 _stdoutSubscription.pause(); |
| 2018 _timer.cancel(); | 2073 _timer.cancel(); |
| 2019 _stdoutCompleter.complete(null); | 2074 _stdoutCompleter.complete(null); |
| 2020 } | 2075 } |
| 2021 }); | 2076 }); |
| 2022 _stdoutSubscription.pause(); | 2077 _stdoutSubscription.pause(); |
| 2023 | 2078 |
| 2024 var _stderrStream = | 2079 var _stderrStream = |
| 2025 _process.stderr | 2080 _process.stderr |
| 2026 .transform(UTF8.decoder) | 2081 .transform(UTF8.decoder) |
| 2027 .transform(new LineSplitter()); | 2082 .transform(new LineSplitter()); |
| 2028 _stderrSubscription = _stderrStream.listen((String line) { | 2083 _stderrSubscription = _stderrStream.listen((String line) { |
| 2029 if (line.startsWith('>>> EOF STDERR')) { | 2084 if (line.startsWith('>>> EOF STDERR')) { |
| 2030 _stderrSubscription.pause(); | 2085 _stderrSubscription.pause(); |
| 2031 _stderrCompleter.complete(null); | 2086 _stderrCompleter.complete(null); |
| 2032 } else { | 2087 } else { |
| 2033 _testStderr.addAll(encodeUtf8(line)); | 2088 _testStderr.add(encodeUtf8(line)); |
| 2034 _testStderr.addAll("\n".codeUnits); | 2089 _testStderr.add("\n".codeUnits); |
| 2035 } | 2090 } |
| 2036 }); | 2091 }); |
| 2037 _stderrSubscription.pause(); | 2092 _stderrSubscription.pause(); |
| 2038 | 2093 |
| 2039 _processExitHandler = makeExitHandler(">>> TEST CRASH"); | 2094 _processExitHandler = makeExitHandler(">>> TEST CRASH"); |
| 2040 _process.exitCode.then((exitCode) { | 2095 _process.exitCode.then((exitCode) { |
| 2041 _processExitHandler(exitCode); | 2096 _processExitHandler(exitCode); |
| 2042 }); | 2097 }); |
| 2043 | 2098 |
| 2044 _process.stdin.done.catchError((err) { | 2099 _process.stdin.done.catchError((err) { |
| (...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2857 } | 2912 } |
| 2858 } | 2913 } |
| 2859 | 2914 |
| 2860 void eventAllTestsDone() { | 2915 void eventAllTestsDone() { |
| 2861 for (var listener in _eventListener) { | 2916 for (var listener in _eventListener) { |
| 2862 listener.allDone(); | 2917 listener.allDone(); |
| 2863 } | 2918 } |
| 2864 _allDone(); | 2919 _allDone(); |
| 2865 } | 2920 } |
| 2866 } | 2921 } |
| OLD | NEW |