|  | // 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. | 
|  |  | 
|  | // OtherResources=skipping_dart2js_compilations_helper.dart | 
|  |  | 
|  | /* | 
|  | * This test makes sure that the "skipping Dart2Js compilations if the output is | 
|  | * already up to date" feature does work as it should. | 
|  | * Therefore this test ensures that compilations are only skipped if the last | 
|  | * modified date of the output of a dart2js compilation is newer than | 
|  | *   - the dart application to compile (including it's dependencies) | 
|  | *   - the dart2js snapshot | 
|  | * Furthermore it ensures that a compilation is not skipped if any of the | 
|  | * necessary files could not be found (dart2js snapshots, previous dart2js | 
|  | * output (+deps file), dart application) | 
|  | */ | 
|  |  | 
|  | import 'dart:async'; | 
|  | import 'dart:io'; | 
|  |  | 
|  | import 'package:expect/expect.dart'; | 
|  |  | 
|  | import 'package:test_runner/src/command.dart'; | 
|  | import 'package:test_runner/src/command_output.dart'; | 
|  | import 'package:test_runner/src/path.dart'; | 
|  | import 'package:test_runner/src/repository.dart'; | 
|  | import 'package:test_runner/src/test_case.dart'; | 
|  |  | 
|  | import 'utils.dart'; | 
|  |  | 
|  | /// This class is responsible for setting up the files necessary for this test | 
|  | /// as well as touching a file. | 
|  | class FileUtils { | 
|  | late Directory tempDir; | 
|  | File? testJs; | 
|  | File? testJsDeps; | 
|  | File? testDart; | 
|  | File? testSnapshot; | 
|  |  | 
|  | FileUtils( | 
|  | {required bool createJs, | 
|  | required bool createJsDeps, | 
|  | required bool createDart, | 
|  | required bool createSnapshot}) { | 
|  | tempDir = Directory.systemTemp | 
|  | .createTempSync('dart_skipping_dart2js_compilations'); | 
|  | if (createJs) { | 
|  | testJs = _createFile(testJsFilePath); | 
|  | _writeToFile(testJs!, "test.js content"); | 
|  | } | 
|  | if (createSnapshot) { | 
|  | testSnapshot = _createFile(testSnapshotFilePath); | 
|  | _writeToFile(testSnapshot!, "dart2js snapshot"); | 
|  | } | 
|  | if (createDart) { | 
|  | testDart = _createFile(testDartFilePath); | 
|  | _writeToFile(testDart!, "dart code"); | 
|  | } | 
|  | if (createJsDeps) { | 
|  | testJsDeps = _createFile(testJsDepsFilePath); | 
|  | var path = Path(tempDir.path).append("test.dart").absolute; | 
|  | _writeToFile(testJsDeps!, "file://$path"); | 
|  | } | 
|  | } | 
|  |  | 
|  | void cleanup() { | 
|  | if (testJs != null) testJs!.deleteSync(); | 
|  | if (testJsDeps != null) testJsDeps!.deleteSync(); | 
|  | if (testDart != null) testDart!.deleteSync(); | 
|  | if (testSnapshot != null) testSnapshot!.deleteSync(); | 
|  |  | 
|  | // if the script did run, it created this file, so we need to delete it | 
|  | var file = File(scriptOutputPath.toNativePath()); | 
|  | if (file.existsSync()) { | 
|  | file.deleteSync(); | 
|  | } | 
|  |  | 
|  | tempDir.deleteSync(); | 
|  | } | 
|  |  | 
|  | Path get scriptOutputPath { | 
|  | return Path(tempDir.path).append('created_if_command_did_run.txt').absolute; | 
|  | } | 
|  |  | 
|  | Path get testDartFilePath { | 
|  | return Path(tempDir.path).append('test.dart').absolute; | 
|  | } | 
|  |  | 
|  | Path get testJsFilePath { | 
|  | return Path(tempDir.path).append('test.js').absolute; | 
|  | } | 
|  |  | 
|  | Path get testJsDepsFilePath { | 
|  | return Path(tempDir.path).append('test.js.deps').absolute; | 
|  | } | 
|  |  | 
|  | Path get testSnapshotFilePath { | 
|  | return Path(tempDir.path).append('test_dart2js.snapshot').absolute; | 
|  | } | 
|  |  | 
|  | void touchFile(File file) { | 
|  | _writeToFile(file, _readFile(file)); | 
|  | } | 
|  |  | 
|  | void _writeToFile(File file, String content) { | 
|  | File(file.resolveSymbolicLinksSync()).openSync(mode: FileMode.write) | 
|  | ..writeStringSync(content) | 
|  | ..closeSync(); | 
|  | } | 
|  |  | 
|  | String _readFile(File file) { | 
|  | return file.readAsStringSync(); | 
|  | } | 
|  |  | 
|  | File _createFile(Path path) { | 
|  | var file = File(path.toNativePath()); | 
|  | file.createSync(); | 
|  | return file; | 
|  | } | 
|  | } | 
|  |  | 
|  | class CommandCompletedHandler { | 
|  | FileUtils fileUtils; | 
|  | final bool _shouldHaveRun; | 
|  |  | 
|  | CommandCompletedHandler(this.fileUtils, this._shouldHaveRun); | 
|  |  | 
|  | void processCompletedTest(CommandOutput output) { | 
|  | Expect.equals(0, output.exitCode); | 
|  | Expect.equals(0, output.stderr.length); | 
|  | if (_shouldHaveRun) { | 
|  | Expect.equals(0, output.stdout.length); | 
|  | Expect.isTrue( | 
|  | File(fileUtils.scriptOutputPath.toNativePath()).existsSync()); | 
|  | } else { | 
|  | Expect.isFalse( | 
|  | File(fileUtils.scriptOutputPath.toNativePath()).existsSync()); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | Command makeCompilationCommand(String testName, FileUtils fileUtils) { | 
|  | var createFileScript = Platform.script | 
|  | .resolve('skipping_dart2js_compilations_helper.dart') | 
|  | .toFilePath(); | 
|  | var executable = Platform.executable; | 
|  | var arguments = [ | 
|  | ...Platform.executableArguments, | 
|  | createFileScript, | 
|  | fileUtils.scriptOutputPath.toNativePath(), | 
|  | ]; | 
|  | var bootstrapDeps = [Uri.parse("file://${fileUtils.testSnapshotFilePath}")]; | 
|  | return CompilationCommand('dart2js', fileUtils.testJsFilePath.toNativePath(), | 
|  | bootstrapDeps, executable, arguments, {}, | 
|  | alwaysCompile: false, workingDirectory: Directory.current.path); | 
|  | } | 
|  |  | 
|  | void main() { | 
|  | // This script is in [sdk]/pkg/test_runner/test. | 
|  | Repository.uri = Platform.script.resolve('../../..'); | 
|  |  | 
|  | var fsNoTestJs = FileUtils( | 
|  | createJs: false, | 
|  | createJsDeps: true, | 
|  | createDart: true, | 
|  | createSnapshot: true); | 
|  | var fsNoTestJsDeps = FileUtils( | 
|  | createJs: true, | 
|  | createJsDeps: false, | 
|  | createDart: true, | 
|  | createSnapshot: true); | 
|  | var fsNoTestDart = FileUtils( | 
|  | createJs: true, | 
|  | createJsDeps: true, | 
|  | createDart: false, | 
|  | createSnapshot: true); | 
|  | var fsNoTestSnapshot = FileUtils( | 
|  | createJs: true, | 
|  | createJsDeps: true, | 
|  | createDart: true, | 
|  | createSnapshot: false); | 
|  | var fsNotUpToDateSnapshot = FileUtils( | 
|  | createJs: true, | 
|  | createJsDeps: true, | 
|  | createDart: true, | 
|  | createSnapshot: true); | 
|  | var fsNotUpToDateDart = FileUtils( | 
|  | createJs: true, | 
|  | createJsDeps: true, | 
|  | createDart: true, | 
|  | createSnapshot: true); | 
|  | var fsUpToDate = FileUtils( | 
|  | createJs: true, | 
|  | createJsDeps: true, | 
|  | createDart: true, | 
|  | createSnapshot: true); | 
|  |  | 
|  | void cleanup() { | 
|  | fsNoTestJs.cleanup(); | 
|  | fsNoTestJsDeps.cleanup(); | 
|  | fsNoTestDart.cleanup(); | 
|  | fsNoTestSnapshot.cleanup(); | 
|  | fsNotUpToDateSnapshot.cleanup(); | 
|  | fsNotUpToDateDart.cleanup(); | 
|  | fsUpToDate.cleanup(); | 
|  | } | 
|  |  | 
|  | Future<void> touchFilesAndRunTests() async { | 
|  | fsNotUpToDateSnapshot.touchFile(fsNotUpToDateSnapshot.testSnapshot!); | 
|  | fsNotUpToDateDart.touchFile(fsNotUpToDateDart.testDart!); | 
|  | fsUpToDate.touchFile(fsUpToDate.testJs!); | 
|  |  | 
|  | Future runTest(String name, FileUtils fileUtils, bool shouldRun) { | 
|  | var completedHandler = CommandCompletedHandler(fileUtils, shouldRun); | 
|  | var command = makeCompilationCommand(name, fileUtils) as ProcessCommand; | 
|  | var process = RunningProcess(command, 60, | 
|  | configuration: makeConfiguration([], 'dummy')); | 
|  | return process.run().then((CommandOutput output) { | 
|  | completedHandler.processCompletedTest(output); | 
|  | }); | 
|  | } | 
|  |  | 
|  | try { | 
|  | // We run the tests in sequence, so that if one of them fails we clean up | 
|  | // everything and throw. | 
|  | await runTest("fs_noTestJs", fsNoTestJs, true); | 
|  | await runTest("fs_noTestJsDeps", fsNoTestJsDeps, true); | 
|  | await runTest("fs_noTestDart", fsNoTestDart, true); | 
|  | await runTest("fs_noTestSnapshot", fsNoTestSnapshot, true); | 
|  | await runTest("fs_notUpToDate_snapshot", fsNotUpToDateSnapshot, true); | 
|  | await runTest("fs_notUpToDate_dart", fsNotUpToDateDart, true); | 
|  | // This is the only test where all dependencies are present and the | 
|  | // test.js file is newer than all the others. So we pass 'false' for | 
|  | // shouldRun. | 
|  | await runTest("fs_upToDate", fsUpToDate, false); | 
|  | } finally { | 
|  | cleanup(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // We need to wait some time to make sure that the files we 'touch' get a | 
|  | // bigger timestamp than the old ones | 
|  | Timer(const Duration(seconds: 1), touchFilesAndRunTests); | 
|  | } |