Use a unqiue file name for the snapshot during testing. (#2303)

Testing `pub` without a snapshot is slow because many tests
invokes `pub` as a commandline tool. Supplying the snapshot
using a fixed filename is risky as it's easy to forget to
delete/rebuild the snapshot causing test results to be
out-of-date.

By using an environment variable to specify the name of the
`pub` snapshot, we can create a random temporary file for
each test run. This minimizes the risk that we accidentally
run tests with an outdated snapshot of `pub`.
diff --git a/.travis.yml b/.travis.yml
index 6778d50..2ebbac6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,6 +17,7 @@
 env:
   global:
     - SPLIT=`which gsplit || which split`
+    - _PUB_TEST_SNAPSHOT="`pwd`/.dart_tool//pub.dart.snapshot.dart2"
 
 dart_task:
   - test: --preset travis `$SPLIT -n l/1/7 .dart_tool/test_files`
@@ -32,9 +33,8 @@
 # Create a snapshot to improve startup time. Tests will automatically use this
 # snapshot if it's available.
 before_script:
-  - dart --snapshot=bin/pub.dart.snapshot.dart2 bin/pub.dart
+  - dart --snapshot="$_PUB_TEST_SNAPSHOT" bin/pub.dart
   - find test -name "*_test\\.dart" | sort > .dart_tool/test_files
-  -
 
 # Only building these branches means that we don't run two builds for each pull
 # request.
diff --git a/test/test_pub.dart b/test/test_pub.dart
index a5a2d11..c79319c 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -349,14 +349,19 @@
     dartBin = p.absolute(dartBin);
   }
 
-  // If there's a snapshot available, use it. The user is responsible for
-  // ensuring this is up-to-date..
+  var pubPath = p.absolute(p.join(pubRoot, 'bin/pub.dart'));
+
+  // If there's a snapshot for "pub" available we use it. If the snapshot is
+  // out-of-date local source the tests will be useless, therefore it is
+  // recommended to use a temporary file with a unique name for each test run.
+  // Note: running tests without a snapshot is significantly slower.
   //
   // TODO(nweiz): When the test runner supports plugins, create one to
   // auto-generate the snapshot before each run.
-  var pubPath = p.absolute(p.join(pubRoot, 'bin/pub.dart'));
-  var snapshotPath = '$pubPath.snapshot.dart2';
-  if (fileExists(snapshotPath)) pubPath = snapshotPath;
+  final snapshotPath = Platform.environment['_PUB_TEST_SNAPSHOT'] ?? '';
+  if (snapshotPath.isNotEmpty && fileExists(snapshotPath)) {
+    pubPath = snapshotPath;
+  }
 
   var dartArgs = [await PackageResolver.current.processArgument];
   dartArgs..addAll([pubPath, '--verbose'])..addAll(args);
diff --git a/tool/test.sh b/tool/test.sh
index 9485558..c3005f1 100755
--- a/tool/test.sh
+++ b/tool/test.sh
@@ -3,21 +3,21 @@
 ### Test wrapper script.
 # Many of the integration tests runs the `pub` command, this is slow if every
 # invocation requires the dart compiler to load all the sources. This script
-# will create a `bin/pub.dart.snapshot.dart2` which the tests can utilize.
+# will create a `pub.XXX.dart.snapshot.dart2` which the tests can utilize.
 # After creating the snapshot this script will forward arguments to
 # `pub run test`, and ensure that the snapshot is deleted after tests have been
 # run.
-#
-# Notice that it is critical that this file is deleted before running tests
-# again, as tests otherwise won't load the pub sources.
 
 # Find folder containing this script.
 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
 ROOT="$DIR/.."
 
+# PATH to a snapshot file.
+PUB_SNAPSHOT_FILE=`tempfile -p 'pub.' -s '.dart.snapshot.dart2'`;
+
 # Always remove the snapshot
 function cleanup {
-  rm -f "$ROOT/bin/pub.dart.snapshot.dart2"
+  rm -f "$PUB_SNAPSHOT_FILE";
 }
 trap cleanup EXIT;
 
@@ -25,10 +25,11 @@
 echo 'Building snapshot'
 (
   cd "$ROOT/";
-  rm -f "$ROOT/bin/pub.dart.snapshot.dart2"
-  dart --snapshot=bin/pub.dart.snapshot.dart2 bin/pub.dart
+  rm -f "$PUB_SNAPSHOT_FILE"
+  dart --snapshot="$PUB_SNAPSHOT_FILE" bin/pub.dart
 )
 
 # Run tests
 echo 'Running tests'
+export _PUB_TEST_SNAPSHOT="$PUB_SNAPSHOT_FILE"
 pub run test -r expanded "$@"