Skip to content

Commit

Permalink
Run the Dart CLI tests from app snapshots on CI (#383)
Browse files Browse the repository at this point in the history
This substantially speeds up the test time, and once we re-enable Dart
2 support is should work around dart-lang/sdk#33257.
  • Loading branch information
nex3 authored Jun 27, 2018
1 parent aa9aff8 commit 7e6f03f
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 44 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ install:
- if-specs git -C sass-spec checkout FETCH_HEAD
- if-specs bundle install --gemfile=sass-spec/Gemfile --jobs=3 --retry=3

- if [ "$TASK" = tests ]; then pub run grinder app-snapshot; fi

script: tool/travis/test.sh

## Deployment
Expand Down
4 changes: 4 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ install:
Install-Product node ''
pub run grinder npm-package
}
- ps: >-
If ($env:NODE -eq "false") {
pub run grinder app-snapshot
}
# Run this as CMD because npm's stderr will cause PowerShell to think it failed.
- IF "%NODE%"=="true" npm install
Expand Down
1 change: 1 addition & 0 deletions test/cli/dart/colon_args_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ import '../dart_test.dart';
import '../shared/colon_args.dart';

void main() {
setUpAll(ensureSnapshotUpToDate);
sharedTests(runSass);
}
1 change: 1 addition & 0 deletions test/cli/dart/errors_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ import '../dart_test.dart';
import '../shared/errors.dart';

void main() {
setUpAll(ensureSnapshotUpToDate);
sharedTests(runSass);
}
1 change: 1 addition & 0 deletions test/cli/dart/repl_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ import '../dart_test.dart';
import '../shared/repl.dart';

void main() {
setUpAll(ensureSnapshotUpToDate);
sharedTests(runSass);
}
1 change: 1 addition & 0 deletions test/cli/dart/source_maps_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ import '../dart_test.dart';
import '../shared/source_maps.dart';

void main() {
setUpAll(ensureSnapshotUpToDate);
sharedTests(runSass);
}
1 change: 1 addition & 0 deletions test/cli/dart/update_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ import '../dart_test.dart';
import '../shared/update.dart';

void main() {
setUpAll(ensureSnapshotUpToDate);
sharedTests(runSass);
}
1 change: 1 addition & 0 deletions test/cli/dart/watch_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ import '../dart_test.dart';
import '../shared/watch.dart';

void main() {
setUpAll(ensureSnapshotUpToDate);
sharedTests(runSass);
}
44 changes: 39 additions & 5 deletions test/cli/dart_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,19 @@ import 'package:test/test.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;
import 'package:test_process/test_process.dart';

import '../io.dart';
import 'shared.dart';

/// Paths where snapshots of the Sass binary might exist, in order of
/// preference.
final _snapshotPaths = [
p.absolute("build/sass.dart.app.snapshot"),
p.absolute("build/sass.dart.snapshot")
];

void main() {
setUpAll(ensureSnapshotUpToDate);

sharedTests(runSass);

test("--version prints the Sass version", () async {
Expand All @@ -24,8 +34,32 @@ void main() {
});
}

Future<TestProcess> runSass(Iterable<String> arguments) => TestProcess.start(
Platform.executable,
["--checked", p.absolute("bin/sass.dart")]..addAll(arguments),
workingDirectory: d.sandbox,
description: "sass");
/// Ensures that the snapshot of the Dart executable used by [runSass] is
/// up-to-date, if one has been generated.
void ensureSnapshotUpToDate() {
for (var path in _snapshotPaths) {
if (new File(path).existsSync()) {
ensureUpToDate(path, "pub run grinder app-snapshot");
return;
}
}
}

Future<TestProcess> runSass(Iterable<String> arguments) {
var executable = _snapshotPaths.firstWhere(
(path) => new File(path).existsSync(),
orElse: () => p.absolute("bin/sass.dart"));

var args = ["--checked"];

// Work around dart-lang/sdk#33622.
if (Platform.isWindows) args.add("--packages=${p.absolute('.packages')}");

return TestProcess.start(
Platform.executable,
args
..add(executable)
..addAll(arguments),
workingDirectory: d.sandbox,
description: "sass");
}
32 changes: 3 additions & 29 deletions test/ensure_npm_package.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,16 @@
// https://opensource.org/licenses/MIT.

import 'dart:async';
import 'dart:io';

import 'package:stream_channel/stream_channel.dart';
import 'package:test/test.dart';

import 'package:sass/src/io.dart';

hybridMain(StreamChannel channel) async {
if (!new Directory("build/npm").existsSync()) {
throw "NPM package is not built. Run pub run grinder npm-package.";
}

var lastModified = new File("build/npm/package.json").lastModifiedSync();
var entriesToCheck = new Directory("lib").listSync(recursive: true).toList();

// If we have a dependency override, "pub run" will touch the lockfile to mark
// it as newer than the pubspec, which makes it unsuitable to use for
// freshness checking.
if (new File("pubspec.yaml")
.readAsStringSync()
.contains("dependency_overrides")) {
entriesToCheck.add(new File("pubspec.yaml"));
} else {
entriesToCheck.add(new File("pubspec.lock"));
}

for (var entry in entriesToCheck) {
if (entry is File) {
var entryLastModified = entry.lastModifiedSync();
if (lastModified.isBefore(entryLastModified)) {
throw "${entry.path} was modified after NPM package was generated.\n"
"Run pub run grinder before-test.";
}
}
}
import 'io.dart';

hybridMain(StreamChannel channel) async {
ensureUpToDate("build/npm/sass.dart.js", "pub run grinder npm-package");
channel.sink.close();
}

Expand Down
45 changes: 45 additions & 0 deletions test/io.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2018 Google Inc. Use of this source code is governed by an
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import 'dart:io';

import 'package:path/path.dart' as p;

/// Ensures that [path] (usually a compilation artifact) has been modified more
/// recently than all this package's source files.
///
/// If [path] isn't up-to-date, this throws an error encouraging the user to run
/// [commandToRun].
void ensureUpToDate(String path, String commandToRun) {
// Ensure path is relative so the error messages are more readable.
path = p.relative(path);
if (!new File(path).existsSync()) {
throw "$path does not exist. Run $commandToRun.";
}

var lastModified = new File(path).lastModifiedSync();
var entriesToCheck = new Directory("lib").listSync(recursive: true).toList();

// If we have a dependency override, "pub run" will touch the lockfile to mark
// it as newer than the pubspec, which makes it unsuitable to use for
// freshness checking.
if (new File("pubspec.yaml")
.readAsStringSync()
.contains("dependency_overrides")) {
entriesToCheck.add(new File("pubspec.yaml"));
} else {
entriesToCheck.add(new File("pubspec.lock"));
}

for (var entry in entriesToCheck) {
if (entry is File) {
var entryLastModified = entry.lastModifiedSync();
if (lastModified.isBefore(entryLastModified)) {
throw "${entry.path} was modified after ${p.prettyUri(p.toUri(path))} "
"was generated.\n"
"Run pub run grinder before_test.";
}
}
}
}
2 changes: 1 addition & 1 deletion tool/grind/benchmark.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import 'standalone.dart';
import 'utils.dart';

@Task('Run benchmarks for Sass compilation speed.')
@Depends(snapshot, appSnapshot, npmPackage)
@Depends(snapshot, releaseAppSnapshot, npmPackage)
benchmark() async {
var libsass = await cloneOrPull('https://github.com/sass/libsass');
var sassc = await cloneOrPull('https://github.com/sass/sassc');
Expand Down
31 changes: 22 additions & 9 deletions tool/grind/standalone.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'dart:io';

import 'package:archive/archive.dart';
import 'package:grinder/grinder.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'package:http/http.dart' as http;

Expand All @@ -21,20 +22,32 @@ snapshot() {
Dart.run('bin/sass.dart', vmArgs: ['--snapshot=build/sass.dart.snapshot']);
}

@Task('Build Dart application snapshot.')
appSnapshot() {
@Task('Build a dev-mode Dart application snapshot.')
appSnapshot() => _appSnapshot(release: false);

@Task('Build a release-mode Dart application snapshot.')
releaseAppSnapshot() => _appSnapshot(release: true);

/// Compiles Sass to an application snapshot.
///
/// If [release] is `true`, this compiles in checked mode. Otherwise, it
/// compiles in unchecked mode.
void _appSnapshot({@required bool release}) {
var args = [
'--snapshot=build/sass.dart.app.snapshot',
'--snapshot-kind=app-jit'
];
// TODO(nweiz): Once we're building with Dart 2 runtime semantics, pass a flag
// to enable assertions rather than a flag to enable checked mode.
if (!release) args..add('--checked');

ensureBuild();
Dart.run('bin/sass.dart',
arguments: ['tool/app-snapshot-input.scss'],
vmArgs: [
'--snapshot=build/sass.dart.app.snapshot',
'--snapshot-kind=app-jit'
],
quiet: true);
arguments: ['tool/app-snapshot-input.scss'], vmArgs: args, quiet: true);
}

@Task('Build standalone packages for all OSes.')
@Depends(snapshot, appSnapshot)
@Depends(snapshot, releaseAppSnapshot)
package() async {
var client = new http.Client();
await Future.wait(["linux", "macos", "windows"].expand((os) => [
Expand Down

0 comments on commit 7e6f03f

Please sign in to comment.