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