Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: test/test_pub.dart

Issue 1148443005: Use an auto-generated pub snapshot for tests. (Closed) Base URL: git@github.com:dart-lang/pub_test@master
Patch Set: Code review changes Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/src/io.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// Test infrastructure for testing pub. 5 /// Test infrastructure for testing pub.
6 /// 6 ///
7 /// Unlike typical unit tests, most pub tests are integration tests that stage 7 /// Unlike typical unit tests, most pub tests are integration tests that stage
8 /// some stuff on the file system, run pub, and then validate the results. This 8 /// some stuff on the file system, run pub, and then validate the results. This
9 /// library provides an API to build tests like that. 9 /// library provides an API to build tests like that.
10 library test_pub; 10 library test_pub;
11 11
12 import 'dart:async'; 12 import 'dart:async';
13 import 'dart:convert'; 13 import 'dart:convert';
14 import 'dart:io'; 14 import 'dart:io';
15 import 'dart:math'; 15 import 'dart:math';
16 16
17 import 'package:crypto/crypto.dart';
17 import 'package:http/testing.dart'; 18 import 'package:http/testing.dart';
18 import 'package:path/path.dart' as p; 19 import 'package:path/path.dart' as p;
19 import 'package:pub_semver/pub_semver.dart'; 20 import 'package:pub_semver/pub_semver.dart';
20 import 'package:scheduled_test/scheduled_process.dart'; 21 import 'package:scheduled_test/scheduled_process.dart';
21 import 'package:scheduled_test/scheduled_server.dart'; 22 import 'package:scheduled_test/scheduled_server.dart';
22 import 'package:scheduled_test/scheduled_stream.dart'; 23 import 'package:scheduled_test/scheduled_stream.dart';
23 import 'package:scheduled_test/scheduled_test.dart' hide fail; 24 import 'package:scheduled_test/scheduled_test.dart' hide fail;
24 import 'package:shelf/shelf.dart' as shelf; 25 import 'package:shelf/shelf.dart' as shelf;
25 import 'package:shelf/shelf_io.dart' as shelf_io; 26 import 'package:shelf/shelf_io.dart' as shelf_io;
26 import 'package:unittest/compact_vm_config.dart'; 27 import 'package:unittest/compact_vm_config.dart';
27 import 'package:yaml/yaml.dart'; 28 import 'package:yaml/yaml.dart';
28 29
29 import '../lib/src/entrypoint.dart'; 30 import '../lib/src/entrypoint.dart';
30 import '../lib/src/exit_codes.dart' as exit_codes; 31 import '../lib/src/exit_codes.dart' as exit_codes;
31 // TODO(rnystrom): Using "gitlib" as the prefix here is ugly, but "git" collides 32 // TODO(rnystrom): Using "gitlib" as the prefix here is ugly, but "git" collides
32 // with the git descriptor method. Maybe we should try to clean up the top level 33 // with the git descriptor method. Maybe we should try to clean up the top level
33 // scope a bit? 34 // scope a bit?
34 import '../lib/src/git.dart' as gitlib; 35 import '../lib/src/git.dart' as gitlib;
35 import '../lib/src/http.dart'; 36 import '../lib/src/http.dart';
36 import '../lib/src/io.dart'; 37 import '../lib/src/io.dart';
37 import '../lib/src/lock_file.dart'; 38 import '../lib/src/lock_file.dart';
38 import '../lib/src/log.dart' as log; 39 import '../lib/src/log.dart' as log;
39 import '../lib/src/package.dart'; 40 import '../lib/src/package.dart';
40 import '../lib/src/pubspec.dart'; 41 import '../lib/src/pubspec.dart';
42 import '../lib/src/sdk.dart' as sdk;
41 import '../lib/src/source/hosted.dart'; 43 import '../lib/src/source/hosted.dart';
42 import '../lib/src/source/path.dart'; 44 import '../lib/src/source/path.dart';
43 import '../lib/src/source_registry.dart'; 45 import '../lib/src/source_registry.dart';
44 import '../lib/src/system_cache.dart'; 46 import '../lib/src/system_cache.dart';
45 import '../lib/src/utils.dart'; 47 import '../lib/src/utils.dart';
46 import '../lib/src/validator.dart'; 48 import '../lib/src/validator.dart';
47 import 'descriptor.dart' as d; 49 import 'descriptor.dart' as d;
48 import 'serve_packages.dart'; 50 import 'serve_packages.dart';
49 51
50 export 'serve_packages.dart'; 52 export 'serve_packages.dart';
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 // Find a Dart executable we can use to spawn. Use the same one that was 514 // Find a Dart executable we can use to spawn. Use the same one that was
513 // used to run this script itself. 515 // used to run this script itself.
514 var dartBin = Platform.executable; 516 var dartBin = Platform.executable;
515 517
516 // If the executable looks like a path, get its full path. That way we 518 // If the executable looks like a path, get its full path. That way we
517 // can still find it when we spawn it with a different working directory. 519 // can still find it when we spawn it with a different working directory.
518 if (dartBin.contains(Platform.pathSeparator)) { 520 if (dartBin.contains(Platform.pathSeparator)) {
519 dartBin = p.absolute(dartBin); 521 dartBin = p.absolute(dartBin);
520 } 522 }
521 523
522 // Always run pub from a snapshot. Since we require the SDK to be built, the 524 // Always run pub from a snapshot. Using the snapshot makes running the tests
523 // snapshot should be there. Note that this *does* mean that the snapshot has 525 // much faster, especially when multiple tests are run at once.
524 // to be manually updated when changing code before running the tests. 526 var pubPath = p.absolute(p.join(pubRoot, '.pub/pub.test.snapshot'));
525 // Otherwise, you will test against stale data.
526 //
527 // Using the snapshot makes running the tests much faster, which is why we
528 // make this trade-off.
529 var pubPath = p.join(p.dirname(dartBin), 'snapshots/pub.dart.snapshot');
530 var dartArgs = [pubPath, '--verbose']; 527 var dartArgs = [pubPath, '--verbose'];
531 dartArgs.addAll(args); 528 dartArgs.addAll(args);
532 529
533 if (tokenEndpoint == null) tokenEndpoint = new Future.value(); 530 if (tokenEndpoint == null) tokenEndpoint = new Future.value();
534 var environmentFuture = tokenEndpoint 531 var environmentFuture = tokenEndpoint
535 .then((tokenEndpoint) => getPubTestEnvironment(tokenEndpoint)) 532 .then((tokenEndpoint) => getPubTestEnvironment(tokenEndpoint))
536 .then((pubEnvironment) { 533 .then((pubEnvironment) {
537 if (environment != null) pubEnvironment.addAll(environment); 534 if (environment != null) pubEnvironment.addAll(environment);
538 return pubEnvironment; 535 return pubEnvironment;
539 }); 536 });
540 537
538 _ensureSnapshot();
539
541 return new PubProcess.start(dartBin, dartArgs, environment: environmentFuture, 540 return new PubProcess.start(dartBin, dartArgs, environment: environmentFuture,
542 workingDirectory: _pathInSandbox(appPath), 541 workingDirectory: _pathInSandbox(appPath),
543 description: args.isEmpty ? 'pub' : 'pub ${args.first}'); 542 description: args.isEmpty ? 'pub' : 'pub ${args.first}');
544 } 543 }
545 544
545 /// Ensure that a snapshot of the current pub source exists at
546 /// ".pub/pub.snapshot".
547 void _ensureSnapshot() {
548 ensureDir(p.join(pubRoot, '.pub'));
549
550 var version = sdk.version.toString();
551 var hash = _hashChanges();
552
553 var snapshotPath = p.join(pubRoot, '.pub', 'pub.test.snapshot');
554 var hashPath = p.join(pubRoot, '.pub', 'pub.hash');
555 var versionPath = p.join(pubRoot, '.pub', 'pub.version');
556 if (fileExists(hashPath) && fileExists(versionPath)) {
557 var oldHash = readTextFile(hashPath);
558 var oldVersion = readTextFile(versionPath);
559
560 if (oldHash == hash && oldVersion == version && fileExists(snapshotPath)) {
561 return;
562 }
563 }
564
565 var dartSnapshot = runProcessSync(Platform.executable, [
566 '--snapshot=$snapshotPath',
567 p.join(pubRoot, 'bin', 'pub.dart')
568 ]);
569 if (dartSnapshot.exitCode != 0) throw "Failed to run dart --snapshot.";
570
571 writeTextFile(hashPath, hash);
572 writeTextFile(versionPath, version);
573 }
574
575 /// Returns a hash that encapsulates the current state of the repo.
576 String _hashChanges() {
577 var hash = new SHA1();
578
579 // Include the current Git commit.
580 hash.add(UTF8.encode(gitlib.runSync(['rev-parse', 'HEAD']).first));
581
582 // Include the changes in lib and bin relative to the current Git commit.
583 var tracked = gitlib.runSync(['diff-index', '--patch', 'HEAD', 'lib', 'bin']);
584 for (var line in tracked) {
585 hash.add(UTF8.encode("$line\n"));
586 }
587
588 // Include the full contents of non-ignored files in lib and bin that aren't
589 // tracked by Git.
590 var untracked = gitlib.runSync(
591 ['ls-files', '--others', '--exclude-standard', 'lib', 'bin']);
592 for (var path in untracked) {
593 hash.add(readBinaryFile(path));
594 }
595
596 return CryptoUtils.bytesToHex(hash.close());
597 }
598
546 /// A subclass of [ScheduledProcess] that parses pub's verbose logging output 599 /// A subclass of [ScheduledProcess] that parses pub's verbose logging output
547 /// and makes [stdout] and [stderr] work as though pub weren't running in 600 /// and makes [stdout] and [stderr] work as though pub weren't running in
548 /// verbose mode. 601 /// verbose mode.
549 class PubProcess extends ScheduledProcess { 602 class PubProcess extends ScheduledProcess {
550 Stream<Pair<log.Level, String>> _log; 603 Stream<Pair<log.Level, String>> _log;
551 Stream<String> _stdout; 604 Stream<String> _stdout;
552 Stream<String> _stderr; 605 Stream<String> _stderr;
553 606
554 PubProcess.start(executable, arguments, 607 PubProcess.start(executable, arguments,
555 {workingDirectory, environment, String description, 608 {workingDirectory, environment, String description,
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 _lastMatcher.matches(item.last, matchState); 1020 _lastMatcher.matches(item.last, matchState);
968 } 1021 }
969 1022
970 Description describe(Description description) { 1023 Description describe(Description description) {
971 return description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); 1024 return description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]);
972 } 1025 }
973 } 1026 }
974 1027
975 /// A [StreamMatcher] that matches multiple lines of output. 1028 /// A [StreamMatcher] that matches multiple lines of output.
976 StreamMatcher emitsLines(String output) => inOrder(output.split("\n")); 1029 StreamMatcher emitsLines(String output) => inOrder(output.split("\n"));
OLDNEW
« no previous file with comments | « lib/src/io.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698