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 1787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1798 } else if (tail != null) { | 1798 } else if (tail != null) { |
1799 complete.addAll(tail); | 1799 complete.addAll(tail); |
1800 } | 1800 } |
1801 head = null; | 1801 head = null; |
1802 tail = null; | 1802 tail = null; |
1803 } | 1803 } |
1804 return complete; | 1804 return complete; |
1805 } | 1805 } |
1806 } | 1806 } |
1807 | 1807 |
| 1808 // Helper to get a list of all child pids for a parent process. |
| 1809 // The first element of the list is the parent pid. |
| 1810 Future<List<int>> _getPidList(pid, diagnostics) async { |
| 1811 var pid_list = [pid]; |
| 1812 var lines; |
| 1813 var start_line = 0; |
| 1814 if (io.Platform.isLinux || io.Platform.isMacOS) { |
| 1815 var result = await io.Process.run("pgrep", |
| 1816 ["-P", "${pid_list[0]}"], |
| 1817 runInShell: true); |
| 1818 lines = result.stdout.split('\n'); |
| 1819 } else if (io.Platform.isWindows) { |
| 1820 var result = await io.Process.run("wmic", |
| 1821 ["process", "where" , "(ParentProcessId=${pid_list[0]})", |
| 1822 "get", "ProcessId"], |
| 1823 runInShell: true); |
| 1824 lines = result.stdout.split('\n'); |
| 1825 // Skip first line containing header "ProcessId". |
| 1826 start_line = 1; |
| 1827 } else { |
| 1828 assert(false); |
| 1829 } |
| 1830 if (lines.length > start_line) { |
| 1831 for (int i = start_line; i < lines.length; ++i) { |
| 1832 var pid = int.parse(lines[i], onError: (source) => null); |
| 1833 if (pid != null) pid_list.add(pid); |
| 1834 } |
| 1835 } else { |
| 1836 diagnostics.add("Could not find child pids"); |
| 1837 diagnostics.addAll(lines); |
| 1838 } |
| 1839 return pid_list; |
| 1840 } |
| 1841 |
1808 /** | 1842 /** |
1809 * A RunningProcess actually runs a test, getting the command lines from | 1843 * A RunningProcess actually runs a test, getting the command lines from |
1810 * its [TestCase], starting the test process (and first, a compilation | 1844 * its [TestCase], starting the test process (and first, a compilation |
1811 * process if the TestCase is a [BrowserTestCase]), creating a timeout | 1845 * process if the TestCase is a [BrowserTestCase]), creating a timeout |
1812 * timer, and recording the results in a new [CommandOutput] object, which it | 1846 * timer, and recording the results in a new [CommandOutput] object, which it |
1813 * attaches to the TestCase. The lifetime of the RunningProcess is limited | 1847 * attaches to the TestCase. The lifetime of the RunningProcess is limited |
1814 * to the time it takes to start the process, run the process, and record | 1848 * to the time it takes to start the process, run the process, and record |
1815 * the result; there are no pointers to it, so it should be available to | 1849 * the result; there are no pointers to it, so it should be available to |
1816 * be garbage collected as soon as it is done. | 1850 * be garbage collected as soon as it is done. |
1817 */ | 1851 */ |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1893 watchdogTimer.cancel(); | 1927 watchdogTimer.cancel(); |
1894 } | 1928 } |
1895 } | 1929 } |
1896 } | 1930 } |
1897 | 1931 |
1898 // Close stdin so that tests that try to block on input will fail. | 1932 // Close stdin so that tests that try to block on input will fail. |
1899 process.stdin.close(); | 1933 process.stdin.close(); |
1900 timeoutHandler() async { | 1934 timeoutHandler() async { |
1901 timedOut = true; | 1935 timedOut = true; |
1902 if (process != null) { | 1936 if (process != null) { |
1903 var executable, arguments; | 1937 var executable; |
1904 if (io.Platform.isLinux) { | 1938 if (io.Platform.isLinux) { |
1905 executable = 'eu-stack'; | 1939 executable = 'eu-stack'; |
1906 arguments = ['-p ${process.pid}']; | |
1907 } else if (io.Platform.isMacOS) { | 1940 } else if (io.Platform.isMacOS) { |
1908 // Try to print stack traces of the timed out process. | 1941 // Try to print stack traces of the timed out process. |
1909 // `sample` is a sampling profiler but we ask it sample for 1 | 1942 // `sample` is a sampling profiler but we ask it sample for 1 |
1910 // second with a 4 second delay between samples so that we only | 1943 // second with a 4 second delay between samples so that we only |
1911 // sample the threads once. | 1944 // sample the threads once. |
1912 executable = '/usr/bin/sample'; | 1945 executable = '/usr/bin/sample'; |
1913 arguments = ['${process.pid}', '1', '4000', '-mayDie']; | |
1914 } else if (io.Platform.isWindows) { | 1946 } else if (io.Platform.isWindows) { |
1915 bool is_x64 = command.executable.contains("X64") || | 1947 bool is_x64 = command.executable.contains("X64") || |
1916 command.executable.contains("SIMARM64"); | 1948 command.executable.contains("SIMARM64"); |
1917 var win_sdk_path = configuration['win_sdk_path']; | 1949 var win_sdk_path = configuration['win_sdk_path']; |
1918 if (win_sdk_path != null) { | 1950 if (win_sdk_path != null) { |
1919 executable = win_sdk_path + | 1951 executable = win_sdk_path + |
1920 "\\Debuggers\\" + (is_x64 ? "x64" : "x86") + "\\cdb.exe"; | 1952 "\\Debuggers\\" + (is_x64 ? "x64" : "x86") + "\\cdb.exe"; |
1921 diagnostics.add("Using $executable to print stack traces"); | 1953 diagnostics.add("Using $executable to print stack traces"); |
1922 arguments = ['-p', '${process.pid}', '-c', '!uniqstack;qd']; | 1954 arguments = ['-p', '${process.pid}', '-c', '!uniqstack;qd']; |
1923 } else { | 1955 } else { |
1924 diagnostics.add("win_sdk path not found"); | 1956 diagnostics.add("win_sdk path not found"); |
1925 } | 1957 } |
| 1958 } else { |
| 1959 diagnostics.add("Capturing stack traces on" |
| 1960 "${io.Platform.operatingSystem} not supported"); |
1926 } | 1961 } |
1927 | |
1928 if (executable != null) { | 1962 if (executable != null) { |
1929 try { | 1963 var pid_list = await _getPidList(process.pid, diagnostics); |
1930 var result = await io.Process.run(executable, arguments); | 1964 diagnostics.add("Process list including children: $pid_list"); |
1931 diagnostics.addAll(result.stdout.split('\n')); | 1965 for (pid in pid_list) { |
1932 diagnostics.addAll(result.stderr.split('\n')); | 1966 var arguments; |
1933 } catch (error) { | 1967 if (io.Platform.isLinux) { |
1934 diagnostics.add("Unable to capture stack traces: $error"); | 1968 arguments = ['-p $pid']; |
| 1969 } else if (io.Platform.isMacOS) { |
| 1970 arguments = ['$pid', '1', '4000', '-mayDie']; |
| 1971 } else if (io.Platform.isWindows) { |
| 1972 arguments = ['-p', '$pid', '-c', '!uniqstack;qd']; |
| 1973 } else { |
| 1974 assert(false); |
| 1975 } |
| 1976 diagnostics.add("Trying to capture stack trace for pid $pid"); |
| 1977 try { |
| 1978 var result = await io.Process.run(executable, arguments); |
| 1979 diagnostics.addAll(result.stdout.split('\n')); |
| 1980 diagnostics.addAll(result.stderr.split('\n')); |
| 1981 } catch (error) { |
| 1982 diagnostics.add("Unable to capture stack traces: $error"); |
| 1983 } |
1935 } | 1984 } |
1936 } | 1985 } |
1937 | 1986 |
1938 if (!process.kill()) { | 1987 if (!process.kill()) { |
1939 diagnostics.add("Unable to kill ${process.pid}"); | 1988 diagnostics.add("Unable to kill ${process.pid}"); |
1940 } | 1989 } |
1941 } | 1990 } |
1942 } | 1991 } |
1943 | 1992 |
1944 stdoutSubscription.asFuture().then(closeStdout); | 1993 stdoutSubscription.asFuture().then(closeStdout); |
(...skipping 1314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3259 } | 3308 } |
3260 } | 3309 } |
3261 | 3310 |
3262 void eventAllTestsDone() { | 3311 void eventAllTestsDone() { |
3263 for (var listener in _eventListener) { | 3312 for (var listener in _eventListener) { |
3264 listener.allDone(); | 3313 listener.allDone(); |
3265 } | 3314 } |
3266 _allDone(); | 3315 _allDone(); |
3267 } | 3316 } |
3268 } | 3317 } |
OLD | NEW |