| Index: test/codegen_test.dart
|
| diff --git a/test/codegen_test.dart b/test/codegen_test.dart
|
| index 8e13891b9f76236f3e7181f2383ed90e07c2b6b3..c2157088166e8f477da07737f1426546c3f9a2c8 100644
|
| --- a/test/codegen_test.dart
|
| +++ b/test/codegen_test.dart
|
| @@ -3,10 +3,15 @@
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| /// Tests code generation.
|
| +///
|
| /// Runs Dart Dev Compiler on all input in the `codegen` directory and checks
|
| /// that the output is what we expected.
|
| library dev_compiler.test.codegen_test;
|
|
|
| +// TODO(rnystrom): This doesn't actually run any tests any more. It just
|
| +// compiles stuff. This should be changed to not use unittest and just be a
|
| +// regular program that outputs files.
|
| +
|
| import 'dart:convert' show JSON;
|
| import 'dart:io' show Directory, File, Platform;
|
| import 'package:args/args.dart' show ArgParser, ArgResults;
|
| @@ -24,7 +29,7 @@ import 'package:analyzer/src/generated/source.dart' show Source;
|
| import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions;
|
| import 'package:dev_compiler/src/compiler/compiler.dart'
|
| show BuildUnit, CompilerOptions, ModuleCompiler;
|
| -import 'testing.dart' show testDirectory;
|
| +import 'testing.dart' show repoDirectory, testDirectory;
|
| import 'multitest.dart' show extractTestsFromMultitest, isMultiTest;
|
| import '../tool/build_sdk.dart' as build_sdk;
|
| import 'package:dev_compiler/src/compiler/compiler.dart';
|
| @@ -32,12 +37,48 @@ import 'package:dev_compiler/src/compiler/compiler.dart';
|
| final ArgParser argParser = new ArgParser()
|
| ..addOption('dart-sdk', help: 'Dart SDK Path', defaultsTo: null);
|
|
|
| +/// The `test/codegen` directory.
|
| +final codegenDir = path.join(testDirectory, 'codegen');
|
| +
|
| +/// The generated directory where tests, expanded multitests, and other test
|
| +/// support libraries are copied to.
|
| +///
|
| +/// The tests sometimes import utility libraries using a relative path.
|
| +/// Likewise, the multitests do too, and one multitest even imports its own
|
| +/// non-expanded form (!). To make that simpler, we copy the entire test tree
|
| +/// to a generated directory and expand that multitests in there too.
|
| +final codegenTestDir = path.join(repoDirectory, 'gen', 'codegen_tests');
|
| +
|
| +/// The generated directory where tests and packages compiled to JS are
|
| +/// output.
|
| +final codegenOutputDir = path.join(repoDirectory, 'gen', 'codegen_output');
|
| +
|
| +// TODO(jmesserly): switch this to a .packages file.
|
| +final packageUrlMappings = {
|
| + 'package:expect/expect.dart': path.join(codegenDir, 'expect.dart'),
|
| + 'package:async_helper/async_helper.dart':
|
| + path.join(codegenDir, 'async_helper.dart'),
|
| + 'package:js/js.dart': path.join(codegenDir, 'packages', 'js', 'js.dart')
|
| +};
|
| +
|
| +final codeCoverage = Platform.environment.containsKey('COVERALLS_TOKEN');
|
| +
|
| main(arguments) {
|
| if (arguments == null) arguments = [];
|
| ArgResults args = argParser.parse(arguments);
|
| var filePattern = new RegExp(args.rest.length > 0 ? args.rest[0] : '.');
|
|
|
| - var expectDir = path.join(inputDir, 'expect');
|
| + var sdkDir = path.join(repoDirectory, 'gen', 'patched_sdk');
|
| + var sdkSummaryFile =
|
| + path.join(testDirectory, '..', 'lib', 'runtime', 'dart_sdk.sum');
|
| + var analyzerOptions = new AnalyzerOptions(
|
| + customUrlMappings: packageUrlMappings,
|
| + dartSdkSummaryPath: sdkSummaryFile);
|
| + var compiler = new ModuleCompiler(analyzerOptions);
|
| +
|
| + // Build packages tests depend on.
|
| + _buildAllPackages(compiler);
|
| +
|
| var testDirs = [
|
| 'language',
|
| 'corelib',
|
| @@ -47,105 +88,60 @@ main(arguments) {
|
| path.join('lib', 'typed_data')
|
| ];
|
|
|
| - var multitests = expandMultiTests(testDirs, filePattern);
|
| + // Copy all of the test files and expanded multitest files to
|
| + // gen/codegen_tests. We'll compile from there.
|
| + var testFiles = _setUpTests(testDirs, filePattern);
|
|
|
| - // Build packages tests depend on
|
| - var sdkSummaryFile =
|
| - path.join(testDirectory, '..', 'lib', 'runtime', 'dart_sdk.sum');
|
| - var analyzerOptions = new AnalyzerOptions(
|
| - customUrlMappings: packageUrlMappings,
|
| - dartSdkSummaryPath: sdkSummaryFile);
|
| - var compiler = new ModuleCompiler(analyzerOptions);
|
| + // Our default compiler options. Individual tests can override these.
|
| + var defaultOptions = ['--no-source-map', '--no-summarize'];
|
| + var compilerArgParser = CompilerOptions.addArguments(new ArgParser());
|
|
|
| - group('dartdevc package', () {
|
| - _buildPackages(compiler, expectDir);
|
| + // Compile each test file to JS and put the result in gen/codegen_output.
|
| + for (var testFile in testFiles) {
|
| + var relativePath = path.relative(testFile, from: codegenTestDir);
|
|
|
| - test('matcher', () {
|
| - _buildPackage(compiler, expectDir, "matcher");
|
| - });
|
| + // Only compile the top-level files for generating coverage.
|
| + if (codeCoverage && path.dirname(relativePath) != ".") continue;
|
|
|
| - test('unittest', () {
|
| - // Only build files applicable to the web - html_*.dart and its
|
| - // internal dependences.
|
| - _buildPackage(compiler, expectDir, "unittest", packageFiles: [
|
| - 'unittest.dart',
|
| - 'html_config.dart',
|
| - 'html_individual_config.dart',
|
| - 'html_enhanced_config.dart'
|
| - ]);
|
| - });
|
| + var name = path.withoutExtension(relativePath);
|
| + test('dartdevc $name', () {
|
| + var outDir = path.join(codegenOutputDir, path.dirname(relativePath));
|
| + _ensureDirectory(outDir);
|
|
|
| - test('stack_trace', () {
|
| - _buildPackage(compiler, expectDir, "stack_trace");
|
| - });
|
| + // Check if we need to use special compile options.
|
| + var contents = new File(testFile).readAsStringSync();
|
| + var match =
|
| + new RegExp(r'// compile options: (.*)').matchAsPrefix(contents);
|
|
|
| - test('path', () {
|
| - _buildPackage(compiler, expectDir, "path");
|
| - });
|
| - });
|
| -
|
| - test('dartdevc sunflower', () {
|
| - _buildSunflower(compiler, expectDir);
|
| - });
|
| -
|
| - // Our default compiler options. Individual tests can override these.
|
| - var defaultOptions = ['--no-source-map', '--no-summarize'];
|
| - var compilerArgParser = CompilerOptions.addArguments(new ArgParser());
|
| -
|
| - var allDirs = [null];
|
| - allDirs.addAll(testDirs);
|
| - for (var dir in allDirs) {
|
| - if (codeCoverage && dir != null) continue;
|
| -
|
| - group('dartdevc ' + path.join('test', 'codegen', dir), () {
|
| - var outDir = new Directory(path.join(expectDir, dir));
|
| - if (!outDir.existsSync()) outDir.createSync(recursive: true);
|
| -
|
| - var baseDir = path.join(inputDir, dir);
|
| - var testFiles = _findTests(baseDir, filePattern);
|
| - for (var filePath in testFiles) {
|
| - if (multitests.contains(filePath)) continue;
|
| -
|
| - var filename = path.basenameWithoutExtension(filePath);
|
| -
|
| - test('$filename.dart', () {
|
| - // Check if we need to use special compile options.
|
| - var contents = new File(filePath).readAsStringSync();
|
| - var match =
|
| - new RegExp(r'// compile options: (.*)').matchAsPrefix(contents);
|
| -
|
| - var args = new List.from(defaultOptions);
|
| - if (match != null) {
|
| - args.addAll(match.group(1).split(' '));
|
| - }
|
| - var options =
|
| - new CompilerOptions.fromArguments(compilerArgParser.parse(args));
|
| -
|
| - // Collect any other files we've imported.
|
| - var files = new Set<String>();
|
| - _collectTransitiveImports(contents, files, from: filePath);
|
| - var moduleName =
|
| - path.withoutExtension(path.relative(filePath, from: inputDir));
|
| - var unit = new BuildUnit(
|
| - moduleName, baseDir, files.toList(), _moduleForLibrary);
|
| - var module = compiler.compile(unit, options);
|
| - _writeModule(path.join(outDir.path, filename), module);
|
| - });
|
| + var args = defaultOptions.toList();
|
| + if (match != null) {
|
| + args.addAll(match.group(1).split(' '));
|
| }
|
| + var options =
|
| + new CompilerOptions.fromArguments(compilerArgParser.parse(args));
|
| +
|
| + // Collect any other files we've imported.
|
| + var files = new Set<String>();
|
| + _collectTransitiveImports(contents, files, from: testFile);
|
| + var moduleName =
|
| + path.withoutExtension(path.relative(testFile, from: codegenTestDir));
|
| + var unit = new BuildUnit(moduleName, path.dirname(testFile),
|
| + files.toList(), _moduleForLibrary);
|
| + var module = compiler.compile(unit, options);
|
| + _writeModule(
|
| + path.join(outDir, path.basenameWithoutExtension(testFile)), module);
|
| });
|
| }
|
|
|
| if (codeCoverage) {
|
| test('build_sdk code coverage', () {
|
| - var generatedSdkDir =
|
| - path.join(testDirectory, '..', 'tool', 'generated_sdk');
|
| - return build_sdk.main(['--dart-sdk', generatedSdkDir, '-o', expectDir]);
|
| + return build_sdk.main(['--dart-sdk', sdkDir, '-o', codegenOutputDir]);
|
| });
|
| }
|
| }
|
|
|
| void _writeModule(String outPath, JSModuleFile result) {
|
| - new Directory(path.dirname(outPath)).createSync(recursive: true);
|
| + _ensureDirectory(path.dirname(outPath));
|
|
|
| String errors = result.errors.join('\n');
|
| if (errors.isNotEmpty && !errors.endsWith('\n')) errors += '\n';
|
| @@ -177,8 +173,36 @@ void _writeModule(String outPath, JSModuleFile result) {
|
| }
|
| }
|
|
|
| -void _buildSunflower(ModuleCompiler compiler, String expectDir) {
|
| - var baseDir = path.join(inputDir, 'sunflower');
|
| +void _buildAllPackages(ModuleCompiler compiler) {
|
| + group('dartdevc package', () {
|
| + _buildPackages(compiler, codegenOutputDir);
|
| +
|
| + var packages = ['matcher', 'path', 'stack_trace'];
|
| + for (var package in packages) {
|
| + test(package, () {
|
| + _buildPackage(compiler, codegenOutputDir, package);
|
| + });
|
| + }
|
| +
|
| + test('unittest', () {
|
| + // Only build files applicable to the web - html_*.dart and its
|
| + // internal dependences.
|
| + _buildPackage(compiler, codegenOutputDir, "unittest", packageFiles: [
|
| + 'unittest.dart',
|
| + 'html_config.dart',
|
| + 'html_individual_config.dart',
|
| + 'html_enhanced_config.dart'
|
| + ]);
|
| + });
|
| + });
|
| +
|
| + test('dartdevc sunflower', () {
|
| + _buildSunflower(compiler, codegenOutputDir);
|
| + });
|
| +}
|
| +
|
| +void _buildSunflower(ModuleCompiler compiler, String outputDir) {
|
| + var baseDir = path.join(codegenDir, 'sunflower');
|
| var files = ['sunflower', 'circle', 'painter']
|
| .map((f) => path.join(baseDir, '$f.dart'))
|
| .toList();
|
| @@ -186,10 +210,10 @@ void _buildSunflower(ModuleCompiler compiler, String expectDir) {
|
| var options = new CompilerOptions(summarizeApi: false);
|
|
|
| var built = compiler.compile(input, options);
|
| - _writeModule(path.join(expectDir, 'sunflower', 'sunflower'), built);
|
| + _writeModule(path.join(outputDir, 'sunflower', 'sunflower'), built);
|
| }
|
|
|
| -void _buildPackages(ModuleCompiler compiler, String expectDir) {
|
| +void _buildPackages(ModuleCompiler compiler, String outputDir) {
|
| // Note: we don't summarize these, as we're going to rely on our in-memory
|
| // shared analysis context for caching, and `_moduleForLibrary` below
|
| // understands these are from other modules.
|
| @@ -200,33 +224,33 @@ void _buildPackages(ModuleCompiler compiler, String expectDir) {
|
| var uriPath = uri.substring('package:'.length);
|
| var name = path.basenameWithoutExtension(uriPath);
|
| test(name, () {
|
| - var input = new BuildUnit(name, inputDir, [uri], _moduleForLibrary);
|
| + var input = new BuildUnit(name, codegenDir, [uri], _moduleForLibrary);
|
| var built = compiler.compile(input, options);
|
|
|
| - var outPath = path.join(expectDir, path.withoutExtension(uriPath));
|
| + var outPath = path.join(outputDir, path.withoutExtension(uriPath));
|
| _writeModule(outPath, built);
|
| });
|
| }
|
| }
|
|
|
| -void _buildPackage(ModuleCompiler compiler, String expectDir, packageName,
|
| +void _buildPackage(ModuleCompiler compiler, String outputDir, packageName,
|
| {List<String> packageFiles}) {
|
| var options = new CompilerOptions(sourceMap: false, summarizeApi: false);
|
|
|
| - var packageRoot = path.join(inputDir, 'packages');
|
| + var packageRoot = path.join(codegenDir, 'packages');
|
| var packageInputDir = path.join(packageRoot, packageName);
|
| List<String> files;
|
| if (packageFiles != null) {
|
| - // Only collect files transitively reachable from packageFiles
|
| + // Only collect files transitively reachable from packageFiles.
|
| var reachable = new Set<String>();
|
| - for (var f in packageFiles) {
|
| - f = path.join(packageInputDir, f);
|
| - _collectTransitiveImports(new File(f).readAsStringSync(), reachable,
|
| - packageRoot: packageRoot, from: f);
|
| + for (var file in packageFiles) {
|
| + file = path.join(packageInputDir, file);
|
| + _collectTransitiveImports(new File(file).readAsStringSync(), reachable,
|
| + packageRoot: packageRoot, from: file);
|
| }
|
| files = reachable.toList();
|
| } else {
|
| - // Collect all files in the packages directory
|
| + // Collect all files in the packages directory.
|
| files = new Directory(packageInputDir)
|
| .listSync(recursive: true)
|
| .where((entry) => entry.path.endsWith('.dart'))
|
| @@ -238,7 +262,7 @@ void _buildPackage(ModuleCompiler compiler, String expectDir, packageName,
|
| new BuildUnit(packageName, packageInputDir, files, _moduleForLibrary);
|
| var module = compiler.compile(unit, options);
|
|
|
| - var outPath = path.join(expectDir, packageName, packageName);
|
| + var outPath = path.join(outputDir, packageName, packageName);
|
| _writeModule(outPath, module);
|
| }
|
|
|
| @@ -250,62 +274,79 @@ String _moduleForLibrary(Source source) {
|
| throw new Exception('Module not found for library "${source.fullName}"');
|
| }
|
|
|
| -/// Expands wacky multitests into a bunch of test files.
|
| -///
|
| -/// We'll compile each one as if it was an input.
|
| -/// NOTE: this will write the individual test files to disk.
|
| -Set<String> expandMultiTests(List testDirs, RegExp filePattern) {
|
| - var multitests = new Set<String>();
|
| +List<String> _setUpTests(List<String> testDirs, RegExp filePattern) {
|
| + var testFiles = [];
|
|
|
| for (var testDir in testDirs) {
|
| - var fullDir = path.join(inputDir, testDir);
|
| - var testFiles = _findTests(fullDir, filePattern);
|
| -
|
| - for (var filePath in testFiles) {
|
| - if (filePath.endsWith('_multi.dart')) continue;
|
| -
|
| - var contents = new File(filePath).readAsStringSync();
|
| - if (isMultiTest(contents)) {
|
| - multitests.add(filePath);
|
| + for (var file in _listFiles(path.join(codegenDir, testDir), filePattern,
|
| + recursive: true)) {
|
| + var relativePath = path.relative(file, from: codegenDir);
|
| + var outputPath = path.join(codegenTestDir, relativePath);
|
| +
|
| + _ensureDirectory(path.dirname(outputPath));
|
| +
|
| + // Copy it over. We do this even for multitests because import_self_test
|
| + // is a multitest, yet imports its own unexpanded form (!).
|
| + new File(file).copySync(outputPath);
|
| +
|
| + if (file.endsWith("_test.dart")) {
|
| + var contents = new File(file).readAsStringSync();
|
| +
|
| + if (isMultiTest(contents)) {
|
| + // It's a multitest, so expand it and add all of the variants.
|
| + var tests = <String, String>{};
|
| + var outcomes = <String, Set<String>>{};
|
| + extractTestsFromMultitest(file, contents, tests, outcomes);
|
| +
|
| + var fileName = path.basenameWithoutExtension(file);
|
| + var outputDir = path.dirname(outputPath);
|
| + tests.forEach((name, contents) {
|
| + var multiFile =
|
| + path.join(outputDir, '${fileName}_${name}_multi.dart');
|
| + testFiles.add(multiFile);
|
| +
|
| + new File(multiFile).writeAsStringSync(contents);
|
| + });
|
| + } else {
|
| + // It's a single test suite.
|
| + testFiles.add(outputPath);
|
| + }
|
| + }
|
| + }
|
| + }
|
|
|
| - var tests = new Map<String, String>();
|
| - var outcomes = new Map<String, Set<String>>();
|
| - extractTestsFromMultitest(filePath, contents, tests, outcomes);
|
| + // Also include the other special files that live at the top level directory.
|
| + for (var file in _listFiles(codegenDir, filePattern)) {
|
| + var relativePath = path.relative(file, from: codegenDir);
|
| + var outputPath = path.join(codegenTestDir, relativePath);
|
|
|
| - var filename = path.basenameWithoutExtension(filePath);
|
| - tests.forEach((name, contents) {
|
| - new File(path.join(fullDir, '${filename}_${name}_multi.dart'))
|
| - .writeAsStringSync(contents);
|
| - });
|
| - }
|
| + new File(file).copySync(outputPath);
|
| + if (file.endsWith(".dart")) {
|
| + testFiles.add(outputPath);
|
| }
|
| }
|
| - return multitests;
|
| +
|
| + return testFiles;
|
| }
|
|
|
| -// TODO(jmesserly): switch this to a .packages file.
|
| -final packageUrlMappings = {
|
| - 'package:expect/expect.dart': path.join(inputDir, 'expect.dart'),
|
| - 'package:async_helper/async_helper.dart':
|
| - path.join(inputDir, 'async_helper.dart'),
|
| - 'package:js/js.dart': path.join(inputDir, 'packages', 'js', 'js.dart')
|
| -};
|
| +/// Recursively creates [dir] if it doesn't exist.
|
| +void _ensureDirectory(String dir) {
|
| + new Directory(dir).createSync(recursive: true);
|
| +}
|
|
|
| -final codeCoverage = Platform.environment.containsKey('COVERALLS_TOKEN');
|
| +/// Lists all of the files within [dir] that match [filePattern].
|
| +Iterable<String> _listFiles(String dir, RegExp filePattern,
|
| + {bool recursive: false}) {
|
| + return new Directory(dir)
|
| + .listSync(recursive: recursive, followLinks: false)
|
| + .where((entry) {
|
| + if (entry is! File) return false;
|
|
|
| -final inputDir = path.join(testDirectory, 'codegen');
|
| -
|
| -Iterable<String> _findTests(String dir, RegExp filePattern) {
|
| - var files = new Directory(dir)
|
| - .listSync()
|
| - .where((f) => f is File)
|
| - .map((f) => f.path)
|
| - .where((p) => p.endsWith('.dart') && filePattern.hasMatch(p));
|
| - if (dir != inputDir) {
|
| - files = files
|
| - .where((p) => p.endsWith('_test.dart') || p.endsWith('_multi.dart'));
|
| - }
|
| - return files;
|
| + var filePath = entry.path;
|
| + if (!filePattern.hasMatch(filePath)) return false;
|
| +
|
| + return true;
|
| + }).map((file) => file.path);
|
| }
|
|
|
| /// Parse directives from [contents] and find the complete set of transitive
|
|
|