OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 // Create and return an options parser for the test runner. | |
6 ArgParser getOptionParser() { | |
7 var parser = new ArgParser(); | |
8 | |
9 parser.addOption('help', abbr: '?', | |
10 help: 'Show usage information.'); | |
11 | |
12 parser.addOption('runtime', abbr: 'r', defaultsTo: 'vm', | |
13 help: 'Where the tests should be run.', | |
14 allowed: ['vm', 'drt-dart', 'drt-js', 'd8'], | |
15 allowedHelp: { | |
16 'vm': 'Run Dart code natively on the standalone dart vm.', | |
17 'drt-dart': 'Run Dart code natively in the headless version of\n' | |
18 'Chrome, DumpRenderTree.', | |
19 'drt-js': 'Run Dart compiled to JavaScript in the headless version\n' | |
20 'of Chrome, DumpRenderTree.', | |
21 'd8': 'Run Dart compiled to JavaScript from the command line using v8.' | |
22 }); | |
23 | |
24 parser.addFlag('checked', defaultsTo: false, | |
25 help: 'Run tests in checked mode.'); | |
26 | |
27 parser.addOption('timeout', abbr: 't', | |
28 help: 'Timeout in seconds', defaultsTo: '60'); | |
29 | |
30 parser.addOption('tasks', abbr: 'j', | |
31 defaultsTo: Platform.numberOfProcessors.toString(), | |
32 help: 'The number of parallel tasks to run.'); | |
33 | |
34 parser.addOption('out', abbr: 'o', defaultsTo: 'stdout', | |
35 help: 'File to send test results. This should be a ' | |
36 'file name or one of stdout, stderr, or none.'); | |
37 | |
38 parser.addOption('list-format', | |
39 defaultsTo: '${Meta.testfile}${Meta.testGroup}${Meta.testDescription}', | |
40 help: 'Format for test list result output.'); | |
41 | |
42 parser.addOption('pass-format', | |
43 defaultsTo: 'PASS ${Meta.testTime}' | |
44 '${Meta.testfile}${Meta.testGroup}' | |
45 '${Meta.testDescription}${Meta.testMessage}', | |
46 help: 'Format for passing test result output.'); | |
47 | |
48 parser.addOption('fail-format', | |
49 defaultsTo: 'FAIL ${Meta.testTime}' | |
50 '${Meta.testfile}${Meta.testGroup}' | |
51 '${Meta.testDescription}${Meta.testMessage}', | |
52 help: 'Format for failed test result output.'); | |
53 | |
54 parser.addOption('error-format', | |
55 defaultsTo: 'ERROR ${Meta.testTime}' | |
56 '${Meta.testfile}${Meta.testGroup}' | |
57 '${Meta.testDescription}${Meta.testMessage}', | |
58 help: 'Format for tests with errors result output.'); | |
59 | |
60 parser.addFlag('summary', defaultsTo: false, | |
61 help: 'Print a summary of tests passed/failed for each test file.'); | |
62 | |
63 parser.addOption('log', abbr: 'l', defaultsTo: 'none', | |
64 help: 'File to send test log/print output to. This should be a ' | |
65 'file name or one of stdout, stderr, or none.'); | |
66 | |
67 // TODO(gram) - add loglevel once we have switched unittest to use the log | |
68 // library. | |
69 | |
70 parser.addFlag('list-files', defaultsTo: false, | |
71 help: 'List test files only, do not run them.'); | |
72 | |
73 parser.addFlag('list-tests', defaultsTo: false, | |
74 help: 'List tests only, do not run them.'); | |
75 | |
76 parser.addFlag('list-groups', defaultsTo: false, | |
77 help: 'List test groups only, do not run tests.'); | |
78 | |
79 parser.addFlag('keep-generated-tests', defaultsTo: false, | |
80 help: 'Keep the generated files in the temporary directory.'); | |
81 | |
82 parser.addFlag('list-options', defaultsTo: false, | |
83 help: 'Print non-default option settings, usable as a test.config.'); | |
84 | |
85 parser.addFlag('list-all-options', defaultsTo: false, | |
86 help: 'Print all option settings, usable as a test.config.'); | |
87 | |
88 parser.addFlag('time', | |
89 help: 'Print timing information after running tests', | |
90 defaultsTo: false); | |
91 | |
92 parser.addFlag('stop-on-failure', defaultsTo: false, | |
93 help: 'Stop execution upon first failure.'); | |
94 | |
95 parser.addFlag('isolate', defaultsTo: false, | |
96 help: 'Runs each test in a separate isolate.'); | |
97 | |
98 parser.addOption('configfile', help: 'Path to an argument file to load.'); | |
99 | |
100 // The defaults here should be the name of the executable, with | |
101 // the assumption that it is available on the PATH. | |
102 parser.addOption('dart2js', help: 'Path to dart2js executable.', | |
103 defaultsTo: 'dart2js'); | |
104 parser.addOption('dart', help: 'Path to dart executable.', | |
105 defaultsTo: 'dart'); | |
106 parser.addOption('drt', help: 'Path to DumpRenderTree executable.', | |
107 defaultsTo: 'drt'); | |
108 parser.addOption('d8', help: 'Path to d8 executable.', | |
109 defaultsTo: 'd8'); | |
110 | |
111 parser.addOption('tempdir', help: 'Directory to store temp files.', | |
112 defaultsTo: '${Platform.pathSeparator}tmp' | |
113 '${Platform.pathSeparator}testrunner'); | |
114 | |
115 parser.addOption('test-file-pat', | |
116 help: 'A regular expression that test file names must match ' | |
117 'to be considered', defaultsTo: '_test.dart\$'); | |
118 | |
119 parser.addOption('include', | |
120 help: 'Only run tests from the specified group(s).', | |
121 allowMultiple: true); | |
122 | |
123 parser.addOption('exclude', | |
124 help: 'Exclude tests from the specified group(s).', | |
125 allowMultiple: true); | |
126 | |
127 parser.addFlag('recurse', abbr: 'R', | |
128 help: 'Recurse through child directories looking for tests.', | |
129 defaultsTo: false); | |
130 | |
131 parser.addOption('unittest', help: '#import path for unit test library.'); | |
132 | |
133 return parser; | |
134 } | |
135 | |
136 // Print a value option, quoting it if it has embedded spaces. | |
137 _printValueOption(String name, value, OutputStream stream) { | |
138 if (value.indexOf(' ') >= 0) { | |
139 stream.writeString("--$name='$value'\n"); | |
140 } else { | |
141 stream.writeString("--$name=$value\n"); | |
142 } | |
143 } | |
144 | |
145 // Print the current option values. | |
146 printOptions(ArgParser parser, ArgResults arguments, | |
147 bool includeDefaults, OutputStream stream) { | |
148 if (stream == null) return; | |
149 for (var name in arguments.options) { | |
150 if (!name.startsWith('list-')) { | |
151 var value = arguments[name]; | |
152 var defaultValue = parser.getDefault(name); | |
153 if (value is bool) { | |
154 if (includeDefaults || (value != defaultValue)) { | |
155 stream.writeString('--${value ? "" : "no-"}$name\n'); | |
156 } | |
157 } else if (value is List) { | |
158 if (value.length > 0) { | |
159 for (var v in value) { | |
160 _printValueOption(name, v, stream); | |
161 } | |
162 } | |
163 } else if (value != null && (includeDefaults || value != defaultValue)) { | |
164 _printValueOption(name, value, stream); | |
165 } | |
166 } | |
167 } | |
168 } | |
169 | |
170 // Get the test runner configuration. This loads options from multiple | |
171 // sources, in increasing order of priority: a test.config file in the | |
172 // current directory, a test config file specified with --configfile on | |
173 // the command line, and other arguments specified on the command line. | |
174 ArgResults loadConfiguration(optionsParser) { | |
175 var options = new List(); | |
176 // We first load options from a test.config file in the working directory. | |
177 options.addAll(getFileContents('test.config', false). | |
178 filter((e) => e.trim().length > 0 && e[0] != '#')); | |
179 // Next we look to see if the command line included a -testconfig argument, | |
180 // and if so, load options from that file too; where these are not | |
181 // multi-valued they will take precedence over the ones in test.config. | |
182 var commandLineArgs = new Options().arguments; | |
183 var cfgarg = '--configfile'; | |
184 for (var i = 0; i < commandLineArgs.length; i++) { | |
185 if (commandLineArgs[i].startsWith(cfgarg)) { | |
186 if (commandLineArgs[i] == cfgarg) { | |
187 if (i == commandLineArgs.length - 1) { | |
188 throw new Exception('Missing argument to $cfgarg'); | |
189 } | |
190 options.addAll(getFileContents(commandLineArgs[++i], true). | |
191 filter((e) => e.trim().length > 0 && e[0] != '#')); | |
192 } else if (commandLineArgs[i].startsWith('$cfgarg=')) { | |
193 options.addAll( | |
194 getFileContents(commandLineArgs[i].substring(cfgarg.length), true). | |
195 filter((e) => e.trim().length > 0 && e[0] != '#')); | |
196 } else { | |
197 throw new Exception('Missing argument to $cfgarg'); | |
198 } | |
199 } | |
200 } | |
201 // Finally, we add options from the command line. These have the highest | |
202 // precedence of all. | |
203 options.addAll(commandLineArgs); | |
204 // Now try parse the whole collection of options, and if this fails, | |
205 // issue a usage message. | |
206 try { | |
207 return optionsParser.parse(options); | |
208 } catch (var e) { | |
209 print(e); | |
210 print('Usage: testrunner <options> [<directory or file> ...]'); | |
211 print(optionsParser.getUsage()); | |
212 return null; | |
213 } | |
214 } | |
215 | |
216 // Perform some sanity checking of the configuration. | |
217 bool sane(ArgResults config) { | |
Siggi Cherem (dart-lang)
2012/08/29 01:05:55
rename: sane => isSane, or isSaneConfig
gram
2012/08/29 20:12:26
Done.
| |
218 if (config == null) { | |
219 return false; | |
220 } | |
221 if (config['runtime'] == null) { | |
222 print('Missing required option --runtime'); | |
223 return false; | |
224 } | |
225 if (config['unittest'] == null) { | |
226 print('Missing required option --unittest'); | |
227 return false; | |
228 } | |
229 if (config['include'].length > 0 && | |
230 config['exclude'].length > 0) { | |
231 print('--include and --exclude are mutually exclusive.'); | |
232 return false; | |
233 } | |
234 return true; | |
235 } | |
236 | |
237 | |
OLD | NEW |