| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library testrunner_test; |
| |
| import 'dart:async'; |
| import 'dart:io'; |
| import 'package:unittest/unittest.dart'; |
| |
| var dart; |
| var debug = false; |
| |
| Future runTestrunner(command, List<String> args, |
| List<String> stdout, List<String> stderr) { |
| if (debug) { |
| print("Running $command ${args.join(' ')}"); |
| } |
| return Process.run(command, args).then((ProcessResult result) { |
| var lineEndings = new RegExp("\r\n|\n"); |
| stdout.addAll(result.stdout.trim().split(lineEndings)); |
| stderr.addAll(result.stderr.trim().split(lineEndings)); |
| }) |
| .catchError((e) { |
| stderr.add("Error starting process:"); |
| stderr.add(" Command: $command"); |
| stderr.add(" Error: ${e}"); |
| completer.complete(-1); |
| }); |
| } |
| |
| // Useful utility for debugging test failures. |
| void dump(label, list) { |
| if (!debug) return; |
| print('\n@=[ $label ]=============================\n'); |
| for (var i = 0; i < list.length; i++) |
| print('@ ${list[i]}\n'); |
| print('------------------------------------------\n'); |
| } |
| |
| int stringCompare(String s1, String s2) => s1.compareTo(s2); |
| |
| Future runTest( |
| List<String> args, |
| List<String> expected_stdout, |
| {List<String> expected_stderr, sort: false}) { |
| var stdout = new List<String>(); |
| var stderr = new List<String>(); |
| for (var i = 0; i < expected_stdout.length; i++) { |
| expected_stdout[i] = expected_stdout[i]. |
| replaceAll('/', Platform.pathSeparator); |
| } |
| if (debug) { |
| args.insert(1, "--log=stderr"); |
| } |
| var rtn = runTestrunner(dart, args, stdout, stderr); |
| rtn.then((_) { |
| dump('stderr', stderr); |
| dump('stdout', stdout); |
| |
| if (expected_stderr != null) { |
| expect(stderr.length, orderedEquals(expected_stderr)); |
| } |
| var i, l = 0, matched = 0; |
| if (sort) { |
| stdout.sort(stringCompare); |
| expected_stdout.sort(stringCompare); |
| } |
| for (i = 0; i < stdout.length; i++) { |
| if (!stdout[i].startsWith('@')) { |
| if (expected_stdout.length <= l) { |
| fail("Extra text in output: ${stdout[i]}"); |
| return; |
| } |
| var actual = stdout[i].trim(); |
| if (debug) { |
| print("Compare <$actual> and <${expected_stdout[l]}>"); |
| } |
| if (expected_stdout[l].startsWith('*')) { |
| expect(actual, endsWith(expected_stdout[l].substring(1))); |
| } else if (expected_stdout[l].startsWith('?')) { |
| var pat = expected_stdout[l].substring(1); |
| if (Platform.operatingSystem == 'windows') { |
| // The joys of Windows... |
| pat = pat.replaceAll('\\','\\\\'); |
| } |
| expect(actual, matches(pat)); |
| } else { |
| expect(actual, expected_stdout[l]); |
| } |
| ++l; |
| } |
| } |
| if (l < expected_stdout.length) { |
| fail("Only matched $l of ${expected_stdout.length} lines"); |
| } |
| }); |
| return rtn; |
| } |
| |
| // A useful function to quickly disable a group of tests; just |
| // replace group() with skip_group(). |
| skip_group(_1,_2) {} |
| |
| main() { |
| var opt = new Options(); |
| dart = opt.executable; |
| var idx = dart.indexOf('dart-sdk'); |
| if (idx < 0) { |
| print("Please run using the dart executable from the Dart SDK"); |
| exit(-1); |
| } |
| var _ = Platform.pathSeparator; |
| var testrunner = '../../testrunner/testrunner.dart' |
| .replaceAll('/', Platform.pathSeparator); |
| |
| group("list tests", () { |
| test('list file', () { |
| return runTest( |
| [ testrunner, |
| '--list-files', |
| 'non_browser_tests' ], |
| [ '?.*/non_browser_tests/non_browser_test.dart' ]); |
| }); |
| test('list files', () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--sort', |
| '--list-files', |
| '--test-file-pattern=.dart\$' ], |
| [ '*browser_tests/web/browser_test.dart', |
| '*http_client_tests/http_client_test.dart', |
| '*layout_tests/web/layout_test.dart', |
| '*non_browser_tests/non_browser_test.dart', |
| '*non_browser_tests/non_browser_toast.dart', |
| '*/testrunner_test.dart' ] |
| ); |
| }); |
| test('list files', () { |
| return runTest( |
| [ testrunner, |
| '--list-files', |
| '--test-file-pattern=.dart\$', |
| 'non_browser_tests' ], |
| [ '*non_browser_tests/non_browser_test.dart', |
| '*non_browser_tests/non_browser_toast.dart' ], |
| sort:true |
| ); |
| }); |
| test('list groups', () { |
| return runTest( |
| [ testrunner, |
| '--list-groups', |
| 'non_browser_tests' ], |
| [ '*non_browser_tests/non_browser_test.dart group1', |
| '*non_browser_tests/non_browser_test.dart group2']); |
| }); |
| test('list tests', () { |
| return runTest( |
| [ testrunner, |
| '--list-tests', |
| 'non_browser_tests' ], |
| [ '*non_browser_tests/non_browser_test.dart group1 test1', |
| '*non_browser_tests/non_browser_test.dart group2 test2' ]); |
| }); |
| }); |
| |
| group("vm", () { |
| test("vm without timing info", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| 'non_browser_tests' ], |
| [ '?FAIL .*/non_browser_tests/non_browser_test.dart group1 test1' |
| ' Expected: false', |
| '?PASS .*/non_browser_tests/non_browser_test.dart group2 test2' ]); |
| }); |
| |
| test("vm with timing info", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--time', |
| 'non_browser_tests' ], |
| [ '?FAIL [0-9.]+s .*/non_browser_tests/non_browser_test.dart group1' |
| ' test1 Expected: false', |
| '?PASS [0-9.]+s .*/non_browser_tests/non_browser_test.dart group2' |
| ' test2' ]); |
| }); |
| }); |
| |
| group("selection", () { |
| test("--include", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--include=group1', |
| 'non_browser_tests' ], |
| [ '?FAIL .*/non_browser_tests/non_browser_test.dart group1 test1 ' |
| 'Expected: false' ]); |
| }); |
| |
| test("--exclude", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--exclude=group1', |
| 'non_browser_tests' ], |
| [ '?PASS .*/non_browser_tests/non_browser_test.dart group2 test2' ]); |
| }); |
| |
| test("test file pattern", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--test-file-pattern=toast', |
| 'non_browser_tests' ], |
| [ '?PASS .*/non_browser_tests/non_browser_toast.dart foo bar' ]); |
| }); |
| }); |
| |
| group("stop on failure tests", () { |
| test("without stop", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--sort', |
| '--tasks=1', |
| '--test-file-pattern=.dart\$', |
| 'non_browser_tests' ], |
| [ '?FAIL .*/non_browser_tests/non_browser_test.dart group1 test1 ' |
| 'Expected: false', |
| '?PASS .*/non_browser_tests/non_browser_test.dart group2 test2', |
| '?PASS .*/non_browser_tests/non_browser_toast.dart foo bar' ]); |
| }); |
| test("with stop", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--sort', |
| '--tasks=1', |
| '--test-file-pattern=.dart\$', |
| '--stop-on-failure', |
| 'non_browser_tests' ], |
| [ '?FAIL .*/non_browser_tests/non_browser_test.dart group1 test1 ' |
| 'Expected: false', |
| '?PASS .*/non_browser_tests/non_browser_test.dart group2 test2' ]); |
| }); |
| }); |
| |
| group("output control", () { |
| test("summary test", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--summary', |
| 'non_browser_tests' ], |
| [ '?FAIL .*/non_browser_tests/non_browser_test.dart group1 test1 ' |
| 'Expected: false', |
| '?PASS .*/non_browser_tests/non_browser_test.dart group2 test2', |
| '', |
| '?.*/non_browser_tests/non_browser_test.dart: ' |
| '1 PASSED, 1 FAILED, 0 ERRORS' ]); |
| }); |
| |
| test('list tests with custom format', () { |
| return runTest( |
| [ testrunner, |
| '--list-tests', |
| '--list-format="<FILENAME><TESTNAME>"', |
| 'non_browser_tests' ], |
| [ '?.*/non_browser_tests/non_browser_test.dart test1', |
| '?.*/non_browser_tests/non_browser_test.dart test2' ]); |
| }); |
| |
| test("custom message formatting", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--pass-format=YIPPEE! <GROUPNAME><TESTNAME>', |
| '--fail-format=EPIC FAIL! <GROUPNAME><TESTNAME>', |
| 'non_browser_tests' ], |
| [ 'EPIC FAIL! group1 test1', 'YIPPEE! group2 test2' ]); |
| }); |
| }); |
| |
| test("checked mode test", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--checked', |
| 'non_browser_tests' ], |
| [ '?FAIL .*/non_browser_tests/non_browser_test.dart group1 test1 ' |
| 'Expected: false', |
| "?FAIL .*/non_browser_tests/non_browser_test.dart group2 test2 " |
| "Caught type 'int' is not a subtype of type 'bool' of 'x'." ]); |
| }); |
| |
| group("browser", () { |
| test("native test", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--runtime=drt-dart', |
| 'browser_tests' ], |
| [ '?FAIL .*/browser_tests/web/browser_test.dart group1 test1 ' |
| 'Expected: false', |
| '?PASS .*/browser_tests/web/browser_test.dart group2 test2' ]); |
| }); |
| |
| test("compiled test", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--runtime=drt-js', |
| 'browser_tests' ], |
| [ '?FAIL .*/browser_tests/web/browser_test.dart group1 test1 ' |
| 'Expected: false', |
| '?PASS .*/browser_tests/web/browser_test.dart group2 test2' ]); |
| }); |
| }); |
| |
| group("textual layout tests", () { |
| group("drt-dart", () { |
| test("no baseline", () { |
| var f = new File("layout_tests/web/layout_test/layout.txt"); |
| if (f.existsSync()) { |
| f.deleteSync(); |
| } |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-dart', |
| '--recurse', |
| '--layout-text', |
| 'layout_tests' ], |
| [ '?FAIL .*/layout_tests/web/layout_test.dart layout ' |
| 'No expectation file' ]); |
| }); |
| test("create baseline", () { |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-dart', |
| '--recurse', |
| '--layout-text', |
| '--regenerate', |
| 'layout_tests' ], |
| [ '?PASS .*/layout_tests/web/layout_test.dart layout' ]); |
| }); |
| test("test baseline", () { |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-dart', |
| '--recurse', |
| '--layout-text', |
| 'layout_tests' ], |
| [ '?PASS .*/layout_tests/web/layout_test.dart layout' ]); |
| }); |
| }); |
| group("drt-js", () { |
| test("no baseline", () { |
| var f = new File("layout_tests/web/layout_test/layout.txt"); |
| if (f.existsSync()) { |
| f.deleteSync(); |
| } |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-js', |
| '--recurse', |
| '--layout-text', |
| 'layout_tests' ], |
| [ '?FAIL .*/layout_tests/web/layout_test.dart layout ' |
| 'No expectation file' ]); |
| }); |
| test("create baseline", () { |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-js', |
| '--recurse', |
| '--layout-text', |
| '--regenerate', |
| 'layout_tests' ], |
| [ '?PASS .*/layout_tests/web/layout_test.dart layout' ]); |
| }); |
| test("test baseline", () { |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-js', |
| '--recurse', |
| '--layout-text', |
| 'layout_tests' ], |
| [ '?PASS .*/layout_tests/web/layout_test.dart layout' ]); |
| }); |
| }); |
| }); |
| |
| group("pixel layout tests", () { |
| group("drt-dart", () { |
| test("no baseline", () { |
| var f = new File("layout_tests/web/layout_test/layout.png"); |
| if (f.existsSync()) { |
| f.deleteSync(); |
| } |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-dart', |
| '--recurse', |
| '--layout-pixel', |
| 'layout_tests' ], |
| [ '?FAIL .*/layout_tests/web/layout_test.dart layout ' |
| 'No expectation file' ]); |
| }); |
| test("create baseline", () { |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-dart', |
| '--recurse', |
| '--layout-pixel', |
| '--regenerate', |
| 'layout_tests' ], |
| [ '?PASS .*/layout_tests/web/layout_test.dart layout' ]); |
| }); |
| test("test baseline", () { |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-dart', |
| '--recurse', |
| '--layout-pixel', |
| 'layout_tests' ], |
| [ '?PASS .*/layout_tests/web/layout_test.dart layout' ]); |
| }); |
| // TODO(gram): Should add a test that changes a byte of the |
| // expectation .png. |
| }); |
| group("drt-js", () { |
| test("no baseline", () { |
| var f = new File("layout_tests/web/layout_test/layout.png"); |
| if (f.existsSync()) { |
| f.deleteSync(); |
| } |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-js', |
| '--recurse', |
| '--layout-pixel', |
| 'layout_tests' ], |
| [ '?FAIL .*/layout_tests/web/layout_test.dart layout ' |
| 'No expectation file' ]); |
| }); |
| test("create baseline", () { |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-js', |
| '--recurse', |
| '--layout-pixel', |
| '--regenerate', |
| 'layout_tests' ], |
| [ '?PASS .*/layout_tests/web/layout_test.dart layout' ]); |
| }); |
| test("test baseline", () { |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-js', |
| '--recurse', |
| '--layout-pixel', |
| 'layout_tests' ], |
| [ '?PASS .*/layout_tests/web/layout_test.dart layout' ]); |
| }); |
| }); |
| }); |
| |
| group("run in isolate", () { |
| test("vm", () { |
| return runTest( |
| [ testrunner, |
| '--runtime=vm', |
| '--recurse', |
| '--isolate', |
| 'non_browser_tests' ], |
| [ '?FAIL .*/non_browser_tests/non_browser_test.dart group1 test1' |
| ' Expected: false', |
| '?PASS .*/non_browser_tests/non_browser_test.dart group2 test2' ]); |
| }); |
| test("drt-dart", () { |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-dart', |
| '--recurse', |
| '--isolate', |
| 'non_browser_tests' ], |
| [ '?FAIL .*/non_browser_tests/non_browser_test.dart group1 test1' |
| ' Expected: false', |
| '?PASS .*/non_browser_tests/non_browser_test.dart group2 test2' ]); |
| }); |
| test("drt-js", () { |
| return runTest( |
| [ testrunner, |
| '--runtime=drt-js', |
| '--recurse', |
| '--isolate', |
| 'non_browser_tests' ], |
| [ '?FAIL .*/non_browser_tests/non_browser_test.dart group1 test1 ' |
| 'Expected: false', |
| '?PASS .*/non_browser_tests/non_browser_test.dart group2 test2' ]); |
| }); |
| }); |
| |
| group("embedded server", () { |
| test("get test", () { |
| return runTest( |
| [ testrunner, |
| '--recurse', |
| '--server', |
| '--port=3456', |
| '--root=${Directory.current.path}', |
| 'http_client_tests' ], |
| [ '?PASS .*/http_client_tests/http_client_test.dart test1', |
| '?PASS .*/http_client_tests/http_client_test.dart test2' ]); |
| }); |
| }); |
| } |
| |