Do resolution before publishing. (#3565)

Also change publishing with dependency_overrides to be a warning instead of an error.

Otherwise it would be impossible to publish breaking changes to packages with a cyclic dependency.

This caused a lot of tests to fail (they were not set up to resolve with the default test sdk version).
diff --git a/lib/src/command/lish.dart b/lib/src/command/lish.dart
index 7926d92..e45a735 100644
--- a/lib/src/command/lish.dart
+++ b/lib/src/command/lish.dart
@@ -16,6 +16,7 @@
 import '../io.dart';
 import '../log.dart' as log;
 import '../oauth2.dart' as oauth2;
+import '../solver/type.dart';
 import '../source/hosted.dart' show validateAndNormalizeHostedUrl;
 import '../utils.dart';
 import '../validator.dart';
@@ -219,6 +220,8 @@
           'pubspec.');
     }
 
+    await entrypoint.acquireDependencies(SolveType.get, analytics: analytics);
+
     var files = entrypoint.root.listFiles();
     log.fine('Archiving and publishing ${entrypoint.root.name}.');
 
diff --git a/lib/src/validator/dependency_override.dart b/lib/src/validator/dependency_override.dart
index b6a49a0..a16367a 100644
--- a/lib/src/validator/dependency_override.dart
+++ b/lib/src/validator/dependency_override.dart
@@ -16,10 +16,15 @@
     var overridden = MapKeySet(entrypoint.root.dependencyOverrides);
     var dev = MapKeySet(entrypoint.root.devDependencies);
     if (overridden.difference(dev).isNotEmpty) {
-      errors.add('Your pubspec.yaml must not override non-dev dependencies.\n'
-          'This ensures you test your package against the same versions of '
-          'its dependencies\n'
-          'that users will have when they use it.');
+      warnings.add('''
+Your pubspec.yaml is overriding non-dev dependencies.
+
+This indicates you are not testing your package against the same versions of its
+dependencies that users will have when they use it.
+
+This might be necessary for packages with cyclic dependencies.
+
+Please be extra careful when publising.''');
     }
     return Future.value();
   }
diff --git a/test/descriptor.dart b/test/descriptor.dart
index 0b11de9..669d8ef 100644
--- a/test/descriptor.dart
+++ b/test/descriptor.dart
@@ -33,7 +33,7 @@
 
 /// Describes a package that passes all validation.
 DirectoryDescriptor get validPackage => dir(appPath, [
-      libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'),
+      libPubspec('test_pkg', '1.0.0', sdk: '>=0.1.2 <=0.2.0'),
       file('LICENSE', 'Eh, do what you want.'),
       file('README.md', "This package isn't real."),
       file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
diff --git a/test/directory_option_test.dart b/test/directory_option_test.dart
index 65193bf..5a483d9 100644
--- a/test/directory_option_test.dart
+++ b/test/directory_option_test.dart
@@ -34,13 +34,13 @@
     await dir(appPath, [
       dir('bin', [
         file('app.dart', '''
-main() => print('Hi');    
+main() => print('Hi');
 ''')
       ]),
       dir('example', [
         pubspec({
           'name': 'example',
-          'environment': {'sdk': '>=1.2.0 <2.0.0'},
+          'environment': {'sdk': '>=0.1.2 <0.2.0'},
           'dependencies': {
             'test_pkg': {'path': '../'}
           }
@@ -49,7 +49,7 @@
       dir('example2', [
         pubspec({
           'name': 'example',
-          'environment': {'sdk': '>=1.2.0 <2.0.0'},
+          'environment': {'sdk': '>=0.1.2 <0.2.0'},
           'dependencies': {
             'myapp': {'path': '../'} // Wrong name of dependency
           }
@@ -82,7 +82,6 @@
       await ctx.run(
         cases[i],
         workingDirectory: sandbox,
-        environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'},
       );
     }
   });
diff --git a/test/lish/archives_and_uploads_a_package_test.dart b/test/lish/archives_and_uploads_a_package_test.dart
index 41db57c..da7fdf7 100644
--- a/test/lish/archives_and_uploads_a_package_test.dart
+++ b/test/lish/archives_and_uploads_a_package_test.dart
@@ -15,10 +15,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('archives and uploads a package', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
@@ -39,6 +38,7 @@
 
   test('archives and uploads a package using token', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.tokensFile({
       'version': 1,
       'hosted': [
@@ -64,6 +64,7 @@
 
   test('publishes to hosted-url with path', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.tokensFile({
       'version': 1,
       'hosted': [
@@ -98,7 +99,7 @@
   test('with an empty Git submodule', () async {
     await d.git('empty').create();
 
-    var repo = d.git(appPath);
+    var repo = d.git(appPath, d.validPackage.contents);
     await repo.create();
 
     await repo.runGit(['submodule', 'add', '../empty', 'empty']);
diff --git a/test/lish/cloud_storage_upload_doesnt_redirect_test.dart b/test/lish/cloud_storage_upload_doesnt_redirect_test.dart
index 0f792d5..19b8761 100644
--- a/test/lish/cloud_storage_upload_doesnt_redirect_test.dart
+++ b/test/lish/cloud_storage_upload_doesnt_redirect_test.dart
@@ -10,10 +10,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test("cloud storage upload doesn't redirect", () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/cloud_storage_upload_provides_an_error_test.dart b/test/lish/cloud_storage_upload_provides_an_error_test.dart
index 5dec03d..85e55af 100644
--- a/test/lish/cloud_storage_upload_provides_an_error_test.dart
+++ b/test/lish/cloud_storage_upload_provides_an_error_test.dart
@@ -10,10 +10,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('cloud storage upload provides an error', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/dot_folder_name_test.dart b/test/lish/dot_folder_name_test.dart
index e48c541..d709f77 100644
--- a/test/lish/dot_folder_name_test.dart
+++ b/test/lish/dot_folder_name_test.dart
@@ -16,7 +16,6 @@
       d.dir('.vscode', [d.file('a')]),
       d.file('.pubignore', '!.vscode/')
     ]).create();
-
     await runPub(
       args: ['lish', '--dry-run'],
       output: contains('''
diff --git a/test/lish/preview_errors_if_private_test.dart b/test/lish/dry_run_errors_if_private_test.dart
similarity index 91%
rename from test/lish/preview_errors_if_private_test.dart
rename to test/lish/dry_run_errors_if_private_test.dart
index fb7160a..10dd739 100644
--- a/test/lish/preview_errors_if_private_test.dart
+++ b/test/lish/dry_run_errors_if_private_test.dart
@@ -10,7 +10,7 @@
 import '../test_pub.dart';
 
 void main() {
-  test('preview shows an error if the package is private', () async {
+  test('dry-run shows an error if the package is private', () async {
     var pkg = packageMap('test_pkg', '1.0.0');
     pkg['publish_to'] = 'none';
     await d.dir(appPath, [d.pubspec(pkg)]).create();
diff --git a/test/lish/dry_run_package_validation_has_a_warning_test.dart b/test/lish/dry_run_package_validation_has_a_warning_test.dart
new file mode 100644
index 0000000..1edd48d
--- /dev/null
+++ b/test/lish/dry_run_package_validation_has_a_warning_test.dart
@@ -0,0 +1,30 @@
+// 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.
+
+import 'package:pub/src/exit_codes.dart' as exit_codes;
+
+import 'package:test/test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+void main() {
+  test('dry-run package validation gives a warning', () async {
+    (await servePackages()).serve('foo', '1.0.0');
+    await d.validPackage.create();
+
+    var pkg =
+        packageMap('test_pkg', '1.0.0', null, null, {'sdk': '>=0.1.2 <0.2.0'});
+    pkg['dependencies'] = {'foo': 'any'};
+    await d.dir(appPath, [d.pubspec(pkg)]).create();
+
+    var pub = await startPublish(globalServer, args: ['--dry-run']);
+
+    await pub.shouldExit(exit_codes.DATA);
+    expect(
+      pub.stderr,
+      emitsThrough('Package has 1 warning.'),
+    );
+  });
+}
diff --git a/test/lish/preview_package_validation_has_no_warnings_test.dart b/test/lish/dry_run_package_validation_has_no_warnings_test.dart
similarity index 71%
rename from test/lish/preview_package_validation_has_no_warnings_test.dart
rename to test/lish/dry_run_package_validation_has_no_warnings_test.dart
index 179c648..13ed386 100644
--- a/test/lish/preview_package_validation_has_no_warnings_test.dart
+++ b/test/lish/dry_run_package_validation_has_no_warnings_test.dart
@@ -10,12 +10,9 @@
 import '../test_pub.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
-  test('preview package validation has no warnings', () async {
-    var pkg =
-        packageMap('test_pkg', '1.0.0', null, null, {'sdk': '>=1.8.0 <2.0.0'});
-    await d.dir(appPath, [d.pubspec(pkg)]).create();
+  test('--dry-run package validation on valid package has no warnings',
+      () async {
+    await d.validPackage.create();
 
     await servePackages();
     var pub = await startPublish(globalServer, args: ['--dry-run']);
diff --git a/test/lish/force_cannot_be_combined_with_dry_run_test.dart b/test/lish/force_cannot_be_combined_with_dry_run_test.dart
index 9d2233c..b82e7ce 100644
--- a/test/lish/force_cannot_be_combined_with_dry_run_test.dart
+++ b/test/lish/force_cannot_be_combined_with_dry_run_test.dart
@@ -9,9 +9,9 @@
 import '../test_pub.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('--force cannot be combined with --dry-run', () async {
+    await d.validPackage.create();
+
     await runPub(
       args: ['lish', '--force', '--dry-run'],
       error: contains('Cannot use both --force and --dry-run.'),
diff --git a/test/lish/force_does_not_publish_if_there_are_errors_test.dart b/test/lish/force_does_not_publish_if_there_are_errors_test.dart
index c949828..69c770a 100644
--- a/test/lish/force_does_not_publish_if_there_are_errors_test.dart
+++ b/test/lish/force_does_not_publish_if_there_are_errors_test.dart
@@ -2,6 +2,9 @@
 // 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.
 
+import 'dart:io';
+
+import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -9,24 +12,20 @@
 import '../test_pub.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('--force does not publish if there are errors', () async {
-    await d.dir(appPath, [
-      d.rawPubspec({
-        'name': 'test_pkg',
-        'homepage': 'https://pub.dartlang.org',
-        'version': '1.0.0',
-      }),
-    ]).create();
+    await servePackages();
+    await d.validPackage.create();
+    // It is an error to publish without a LICENSE file.
+    File(d.path(p.join(appPath, 'LICENSE'))).deleteSync();
 
     await servePackages();
     var pub = await startPublish(globalServer, args: ['--force']);
 
     await pub.shouldExit(exit_codes.DATA);
     expect(
-        pub.stderr,
-        emitsThrough('Sorry, your package is missing some '
-            "requirements and can't be published yet."));
+      pub.stderr,
+      emitsThrough(
+          "Sorry, your package is missing a requirement and can't be published yet."),
+    );
   });
 }
diff --git a/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart b/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart
index c5d8957..5b25f48 100644
--- a/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart
+++ b/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart
@@ -13,10 +13,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('--force publishes if there are no warnings or errors', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer, args: ['--force']);
 
diff --git a/test/lish/force_publishes_if_there_are_warnings_test.dart b/test/lish/force_publishes_if_there_are_warnings_test.dart
index 9fb3d53..41a115c 100644
--- a/test/lish/force_publishes_if_there_are_warnings_test.dart
+++ b/test/lish/force_publishes_if_there_are_warnings_test.dart
@@ -13,15 +13,15 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('--force publishes if there are warnings', () async {
+    await d.validPackage.create();
     var pkg =
-        packageMap('test_pkg', '1.0.0', null, null, {'sdk': '>=1.8.0 <2.0.0'});
+        packageMap('test_pkg', '1.0.0', null, null, {'sdk': '>=0.1.2 <0.2.0'});
     pkg['dependencies'] = {'foo': 'any'};
     await d.dir(appPath, [d.pubspec(pkg)]).create();
 
-    await servePackages();
+    (await servePackages()).serve('foo', '1.0.0');
+
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer, args: ['--force']);
 
@@ -35,15 +35,14 @@
     });
 
     await pub.shouldExit(exit_codes.SUCCESS);
+    final stderrLines = await pub.stderr.rest.toList();
     expect(
-      pub.stderr,
-      emitsThrough('Package validation found the following potential issue:'),
-    );
-    expect(
-        pub.stderr,
-        emitsLines(
-            '* Your dependency on "foo" should have a version constraint.\n'
-            '  Without a constraint, you\'re promising to support all future versions of "foo".'));
+        stderrLines,
+        allOf([
+          contains('Package validation found the following potential issue:'),
+          contains(
+              '* Your dependency on "foo" should have a version constraint. For example:'),
+        ]));
     expect(pub.stdout, emitsThrough('Package test_pkg 1.0.0 uploaded!'));
   });
 }
diff --git a/test/lish/package_creation_provides_a_malformed_error_test.dart b/test/lish/package_creation_provides_a_malformed_error_test.dart
index 7ab0bcd..cb18e56 100644
--- a/test/lish/package_creation_provides_a_malformed_error_test.dart
+++ b/test/lish/package_creation_provides_a_malformed_error_test.dart
@@ -12,10 +12,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('package creation provides a malformed error', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/package_creation_provides_a_malformed_success_test.dart b/test/lish/package_creation_provides_a_malformed_success_test.dart
index 089d09e..b65317c 100644
--- a/test/lish/package_creation_provides_a_malformed_success_test.dart
+++ b/test/lish/package_creation_provides_a_malformed_success_test.dart
@@ -12,10 +12,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('package creation provides a malformed success', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/package_creation_provides_an_error_test.dart b/test/lish/package_creation_provides_an_error_test.dart
index f5ff128..a4fde1b 100644
--- a/test/lish/package_creation_provides_an_error_test.dart
+++ b/test/lish/package_creation_provides_an_error_test.dart
@@ -12,10 +12,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('package creation provides an error', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/package_creation_provides_invalid_json_test.dart b/test/lish/package_creation_provides_invalid_json_test.dart
index 2cd6212..7181d8e 100644
--- a/test/lish/package_creation_provides_invalid_json_test.dart
+++ b/test/lish/package_creation_provides_invalid_json_test.dart
@@ -10,10 +10,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('package creation provides invalid JSON', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/package_validation_has_a_warning_and_continues_test.dart b/test/lish/package_validation_has_a_warning_and_continues_test.dart
index c39dbc4..92c74de 100644
--- a/test/lish/package_validation_has_a_warning_and_continues_test.dart
+++ b/test/lish/package_validation_has_a_warning_and_continues_test.dart
@@ -3,7 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:convert';
+import 'dart:io';
 
+import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
@@ -13,17 +15,16 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('package validation has a warning and continues', () async {
-    var pkg =
-        packageMap('test_pkg', '1.0.0', null, null, {'sdk': '>=1.8.0 <2.0.0'});
-    pkg['author'] = 'Natalie Weizenbaum';
-    await d.dir(appPath, [d.pubspec(pkg)]).create();
+    await servePackages();
+    await d.validPackage.create();
+    // Publishing without a README.md gives a warning.
+    File(d.path(p.join(appPath, 'README.md'))).deleteSync();
 
     await servePackages();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
+    expect(pub.stdout, emitsThrough(startsWith('Package has 1 warning.')));
     pub.stdin.writeln('y');
     handleUploadForm(globalServer);
     handleUpload(globalServer);
diff --git a/test/lish/package_validation_has_a_warning_and_is_canceled_test.dart b/test/lish/package_validation_has_a_warning_and_is_canceled_test.dart
index 0d5a563..b552a25 100644
--- a/test/lish/package_validation_has_a_warning_and_is_canceled_test.dart
+++ b/test/lish/package_validation_has_a_warning_and_is_canceled_test.dart
@@ -9,13 +9,14 @@
 import '../test_pub.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('package validation has a warning and is canceled', () async {
+    await d.validPackage.create();
     var pkg =
-        packageMap('test_pkg', '1.0.0', null, null, {'sdk': '>=1.8.0 <2.0.0'});
+        packageMap('test_pkg', '1.0.0', null, null, {'sdk': '>=0.1.2 <0.2.0'});
     pkg['author'] = 'Natalie Weizenbaum';
-    await d.dir(appPath, [d.pubspec(pkg)]).create();
+    await d.dir(appPath, [
+      d.pubspec(pkg),
+    ]).create();
 
     await servePackages();
     var pub = await startPublish(globalServer);
diff --git a/test/lish/package_validation_has_an_error_test.dart b/test/lish/package_validation_has_an_error_test.dart
index 3605670..aa0e6f6 100644
--- a/test/lish/package_validation_has_an_error_test.dart
+++ b/test/lish/package_validation_has_an_error_test.dart
@@ -9,14 +9,13 @@
 import '../test_pub.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('package validation has an error', () async {
     await d.dir(appPath, [
       d.rawPubspec({
         'name': 'test_pkg',
         'homepage': 'https://pub.dev',
         'version': '1.0.0',
+        'environment': {'sdk': '>=0.1.2 <0.2.0'}
       }),
     ]).create();
 
diff --git a/test/lish/preview_package_validation_has_a_warning_test.dart b/test/lish/preview_package_validation_has_a_warning_test.dart
deleted file mode 100644
index 69f59af..0000000
--- a/test/lish/preview_package_validation_has_a_warning_test.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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.
-
-import 'package:pub/src/exit_codes.dart' as exit_codes;
-
-import 'package:test/test.dart';
-
-import '../descriptor.dart' as d;
-import '../test_pub.dart';
-
-void main() {
-  setUp(d.validPackage.create);
-
-  test('preview package validation has a warning', () async {
-    var pkg =
-        packageMap('test_pkg', '1.0.0', null, null, {'sdk': '>=1.8.0 <2.0.0'});
-    pkg['dependencies'] = {'foo': 'any'};
-    await d.dir(appPath, [d.pubspec(pkg)]).create();
-
-    await servePackages();
-    var pub = await startPublish(globalServer, args: ['--dry-run']);
-
-    await pub.shouldExit(exit_codes.DATA);
-    expect(
-      pub.stderr,
-      emitsThrough('Package validation found the following potential issue:'),
-    );
-    expect(
-        pub.stderr,
-        emitsLines(
-            '* Your dependency on "foo" should have a version constraint.\n'
-            '  Without a constraint, you\'re promising to support all future versions of "foo".\n'
-            '\n'
-            'Package has 1 warning.'));
-  });
-}
diff --git a/test/lish/requires_resolution_before_publishing_test.dart b/test/lish/requires_resolution_before_publishing_test.dart
new file mode 100644
index 0000000..e3294bc
--- /dev/null
+++ b/test/lish/requires_resolution_before_publishing_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2022, 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.
+
+import 'package:pub/src/exit_codes.dart' as exit_codes;
+import 'package:test/test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+void main() {
+  test('does not publish if no resolution can be found', () async {
+    await servePackages(); // No packages.
+    await d.validPackage.create();
+    await d.appDir({'foo': '1.0.0'}).create();
+    await runPub(
+      args: ['lish'],
+      error: contains("Because myapp depends on foo any which doesn't exist"),
+      exitCode: exit_codes.UNAVAILABLE,
+    );
+  });
+}
diff --git a/test/lish/server_arg_overrides_publish_to_url_test.dart b/test/lish/server_arg_overrides_publish_to_url_test.dart
index 1597146..fcfdf14 100644
--- a/test/lish/server_arg_overrides_publish_to_url_test.dart
+++ b/test/lish/server_arg_overrides_publish_to_url_test.dart
@@ -18,7 +18,6 @@
     var pkg = packageMap('test_pkg', '1.0.0');
     pkg['publish_to'] = 'http://pubspec.com';
     await d.dir(appPath, [d.pubspec(pkg)]).create();
-
     await runPub(
         args: ['lish', '--dry-run', '--server', packageServer.url],
         output: contains(packageServer.url),
diff --git a/test/lish/upload_form_fields_has_a_non_string_value_test.dart b/test/lish/upload_form_fields_has_a_non_string_value_test.dart
index 78a54fa..8758bca 100644
--- a/test/lish/upload_form_fields_has_a_non_string_value_test.dart
+++ b/test/lish/upload_form_fields_has_a_non_string_value_test.dart
@@ -11,10 +11,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('upload form fields has a non-string value', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/upload_form_fields_is_not_a_map_test.dart b/test/lish/upload_form_fields_is_not_a_map_test.dart
index d18c1ee..dc41511 100644
--- a/test/lish/upload_form_fields_is_not_a_map_test.dart
+++ b/test/lish/upload_form_fields_is_not_a_map_test.dart
@@ -11,10 +11,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('upload form fields is not a map', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/upload_form_is_missing_fields_test.dart b/test/lish/upload_form_is_missing_fields_test.dart
index b0032f8..e909c0a 100644
--- a/test/lish/upload_form_is_missing_fields_test.dart
+++ b/test/lish/upload_form_is_missing_fields_test.dart
@@ -11,10 +11,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('upload form is missing fields', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/upload_form_is_missing_url_test.dart b/test/lish/upload_form_is_missing_url_test.dart
index eae43ea..418813f 100644
--- a/test/lish/upload_form_is_missing_url_test.dart
+++ b/test/lish/upload_form_is_missing_url_test.dart
@@ -11,10 +11,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('upload form is missing url', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/upload_form_provides_an_error_test.dart b/test/lish/upload_form_provides_an_error_test.dart
index 35932b8..68a6c66 100644
--- a/test/lish/upload_form_provides_an_error_test.dart
+++ b/test/lish/upload_form_provides_an_error_test.dart
@@ -11,10 +11,9 @@
 import '../test_pub.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('upload form provides an error', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/upload_form_provides_invalid_json_test.dart b/test/lish/upload_form_provides_invalid_json_test.dart
index a046755..73ffb9a 100644
--- a/test/lish/upload_form_provides_invalid_json_test.dart
+++ b/test/lish/upload_form_provides_invalid_json_test.dart
@@ -9,10 +9,10 @@
 import '../test_pub.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('upload form provides invalid JSON', () async {
     await servePackages();
+    await d.validPackage.create();
+    await servePackages();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/upload_form_url_is_not_a_string_test.dart b/test/lish/upload_form_url_is_not_a_string_test.dart
index f69fd1f..b37d24f 100644
--- a/test/lish/upload_form_url_is_not_a_string_test.dart
+++ b/test/lish/upload_form_url_is_not_a_string_test.dart
@@ -11,10 +11,9 @@
 import 'utils.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('upload form url is not a string', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPublish(globalServer);
 
diff --git a/test/lish/uses_publish_to_url_test.dart b/test/lish/uses_publish_to_url_test.dart
index 47496f7..d9408c4 100644
--- a/test/lish/uses_publish_to_url_test.dart
+++ b/test/lish/uses_publish_to_url_test.dart
@@ -14,7 +14,6 @@
     var pkg = packageMap('test_pkg', '1.0.0');
     pkg['publish_to'] = 'http://example.com';
     await d.dir(appPath, [d.pubspec(pkg)]).create();
-
     await runPub(
         args: ['lish', '--dry-run'],
         output: contains('Publishing test_pkg 1.0.0 to http://example.com'),
diff --git a/test/oauth2/with_an_expired_credentials_without_a_refresh_token_authenticates_again_test.dart b/test/oauth2/with_an_expired_credentials_without_a_refresh_token_authenticates_again_test.dart
index 803c529..fb63cde 100644
--- a/test/oauth2/with_an_expired_credentials_without_a_refresh_token_authenticates_again_test.dart
+++ b/test/oauth2/with_an_expired_credentials_without_a_refresh_token_authenticates_again_test.dart
@@ -13,9 +13,9 @@
   test(
       'with an expired credentials.json without a refresh token, '
       'authenticates again and saves credentials.json', () async {
+    await servePackages();
     await d.validPackage.create();
 
-    await servePackages();
     await d
         .credentialsFile(globalServer, 'access token',
             expiration: DateTime.now().subtract(Duration(hours: 1)))
diff --git a/test/oauth2/with_no_credentials_authenticates_and_saves_credentials_test.dart b/test/oauth2/with_no_credentials_authenticates_and_saves_credentials_test.dart
index 961a465..2fdb7a4 100644
--- a/test/oauth2/with_no_credentials_authenticates_and_saves_credentials_test.dart
+++ b/test/oauth2/with_no_credentials_authenticates_and_saves_credentials_test.dart
@@ -14,7 +14,6 @@
       'with no credentials.json, authenticates and saves '
       'credentials.json', () async {
     await d.validPackage.create();
-
     await servePackages();
     var pub = await startPublish(globalServer);
     await confirmPublish(pub);
diff --git a/test/pubspec_overrides_test.dart b/test/pubspec_overrides_test.dart
index 514d52f..9f48c23 100644
--- a/test/pubspec_overrides_test.dart
+++ b/test/pubspec_overrides_test.dart
@@ -2,7 +2,6 @@
 // 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.
 
-import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
 import 'descriptor.dart' as d;
@@ -47,18 +46,4 @@
       ]).validate();
     });
   });
-
-  test('is ignored by publish command', () async {
-    await d.validPackage.create();
-    await d.dir(appPath, [
-      d.pubspecOverrides({
-        'dependency_overrides': {'lib': '1.0.0'}
-      }),
-    ]).create();
-
-    await runPub(
-      args: ['lish', '--dry-run'],
-      exitCode: exit_codes.SUCCESS,
-    );
-  });
 }
diff --git a/test/test_pub.dart b/test/test_pub.dart
index c5b2d60..7fb445d 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -74,7 +74,7 @@
         orElse: () => null) as Map<String, dynamic>;
 
 /// The suffix appended to a built snapshot.
-final versionSuffix = testVersion;
+const versionSuffix = testVersion;
 
 /// Enum identifying a pub command that can be run with a well-defined success
 /// output.
@@ -391,7 +391,7 @@
   // TODO(rnystrom): This is overly specific and inflexible regarding different
   // test packages. Should validate this a little more loosely.
   await expectLater(
-      pub.stdout, emits(startsWith('Publishing test_pkg 1.0.0 to ')));
+      pub.stdout, emitsThrough(startsWith('Publishing test_pkg 1.0.0 to ')));
   await expectLater(
       pub.stdout,
       emitsThrough(matches(
@@ -407,7 +407,7 @@
 /// sandbox.
 String _pathInSandbox(String relPath) => p.join(d.sandbox, relPath);
 
-String testVersion = '0.1.2+3';
+const String testVersion = '0.1.2+3';
 
 /// Gets the environment variables used to run pub in a test context.
 Map<String, String> getPubTestEnvironment([String? tokenEndpoint]) => {
diff --git a/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt b/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt
index c536b72..577a0a5 100644
--- a/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt
+++ b/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt
@@ -53,7 +53,7 @@
 Resolving dependencies in myapp/example2...
 [STDERR] Error on line 1, column 9 of myapp/pubspec.yaml: "name" field doesn't match expected name "myapp".
 [STDERR]   â•·
-[STDERR] 1 │ {"name":"test_pkg","version":"1.0.0","homepage":"http://pub.dev","description":"A package, I guess.","environment":{"sdk":">=1.8.0 <=2.0.0"}, dependencies: { foo: ^1.0.0}}
+[STDERR] 1 │ {"name":"test_pkg","version":"1.0.0","homepage":"http://pub.dev","description":"A package, I guess.","environment":{"sdk":">=0.1.2 <=0.2.0"}, dependencies: { foo: ^1.0.0}}
 [STDERR]   │         ^^^^^^^^^^
 [STDERR]   ╵
 [EXIT CODE] 65
@@ -93,6 +93,8 @@
 
 ## Section 11
 $ pub publish -C myapp --dry-run
+Resolving dependencies in myapp...
+Got dependencies in myapp!
 Publishing test_pkg 1.0.0 to http://localhost:$PORT:
 ├── CHANGELOG.md (<1 KB)
 ├── LICENSE (<1 KB)
@@ -106,9 +108,15 @@
 ├── lib
 │   └── test_pkg.dart (<1 KB)
 └── pubspec.yaml (<1 KB)
-The server may enforce additional checks.
-[STDERR] 
-[STDERR] Package has 0 warnings.
+[STDERR] Package validation found the following error:
+[STDERR] * Older versions of pub don't support ^ version constraints.
+[STDERR]   Make sure your SDK constraint excludes old versions:
+[STDERR]   
+[STDERR]   environment:
+[STDERR]     sdk: ">=1.8.0 <2.0.0"
+[STDERR] Sorry, your package is missing a requirement and can't be published yet.
+[STDERR] For more information, see: https://dart.dev/tools/pub/cmd/pub-lish.
+[EXIT CODE] 65
 
 -------------------------------- END OF OUTPUT ---------------------------------
 
@@ -124,7 +132,7 @@
 
 ## Section 13
 $ pub deps -C myapp
-Dart SDK 1.12.0
+Dart SDK 0.1.2+3
 test_pkg 1.0.0
 └── foo 1.0.0
 
diff --git a/test/testdata/goldens/lish/many_files_test/displays all files.txt b/test/testdata/goldens/lish/many_files_test/displays all files.txt
index 00caea4..7171f66 100644
--- a/test/testdata/goldens/lish/many_files_test/displays all files.txt
+++ b/test/testdata/goldens/lish/many_files_test/displays all files.txt
@@ -1,5 +1,7 @@
 # GENERATED BY: test/lish/many_files_test.dart
 
+Resolving dependencies...
+Got dependencies!
 Publishing test_pkg 1.0.0 to http://localhost:$PORT:
 ├── CHANGELOG.md (<1 KB)
 ├── LICENSE (<1 KB)
diff --git a/test/token/token_authentication_test.dart b/test/token/token_authentication_test.dart
index 350bca4..d0b89c9 100644
--- a/test/token/token_authentication_test.dart
+++ b/test/token/token_authentication_test.dart
@@ -9,10 +9,9 @@
 import '../test_pub.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('with a pre existing environment token authenticates', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.tokensFile({
       'version': 1,
       'hosted': [
@@ -33,6 +32,7 @@
 
   test('with a pre existing opaque token authenticates', () async {
     await servePackages();
+    await d.validPackage.create();
     await d.tokensFile({
       'version': 1,
       'hosted': [
diff --git a/test/token/when_receives_401_removes_token_test.dart b/test/token/when_receives_401_removes_token_test.dart
index add619b..6ab0700 100644
--- a/test/token/when_receives_401_removes_token_test.dart
+++ b/test/token/when_receives_401_removes_token_test.dart
@@ -9,10 +9,9 @@
 import '../test_pub.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('when receives 401 response removes saved token', () async {
     final server = await servePackages();
+    await d.validPackage.create();
     await d.tokensFile({
       'version': 1,
       'hosted': [
diff --git a/test/token/when_receives_403_persists_saved_token_test.dart b/test/token/when_receives_403_persists_saved_token_test.dart
index 6db5538..3fef9a5 100644
--- a/test/token/when_receives_403_persists_saved_token_test.dart
+++ b/test/token/when_receives_403_persists_saved_token_test.dart
@@ -9,9 +9,8 @@
 import '../test_pub.dart';
 
 void main() {
-  setUp(d.validPackage.create);
-
   test('when receives 403 response persists saved token', () async {
+    await d.validPackage.create();
     final server = await servePackages();
     await d.tokensFile({
       'version': 1,
diff --git a/test/validator/dependency_override_test.dart b/test/validator/dependency_override_test.dart
index b801ad9..60af87d 100644
--- a/test/validator/dependency_override_test.dart
+++ b/test/validator/dependency_override_test.dart
@@ -36,7 +36,7 @@
         })
       ]).create();
 
-      await expectValidation(dependencyOverride, errors: isNotEmpty);
+      await expectValidation(dependencyOverride, warnings: isNotEmpty);
     });
 
     test('it has any non-dev dependency overrides', () async {
@@ -51,7 +51,7 @@
         })
       ]).create();
 
-      await expectValidation(dependencyOverride, errors: isNotEmpty);
+      await expectValidation(dependencyOverride, warnings: isNotEmpty);
     });
   });
 }
diff --git a/test/validator/dependency_test.dart b/test/validator/dependency_test.dart
index 93d2bc9..69fc4a8 100644
--- a/test/validator/dependency_test.dart
+++ b/test/validator/dependency_test.dart
@@ -25,29 +25,38 @@
   ]);
 }
 
-Future<void> expectValidation({error, int exitCode = 0}) async {
+Future<void> expectValidation(
+    {error,
+    int exitCode = 0,
+    Map<String, String> environment = const {}}) async {
   await runPub(
     error: error ?? contains('Package has 0 warnings.'),
     args: ['publish', '--dry-run'],
     // workingDirectory: d.path(appPath),
     exitCode: exitCode,
+    environment: environment,
   );
 }
 
-Future<void> expectValidationWarning(error) async {
+Future<void> expectValidationWarning(error,
+    {Map<String, String> environment = const {}}) async {
   if (error is String) error = contains(error);
   await expectValidation(
-      error: allOf([error, contains('Package has 1 warning.')]),
-      exitCode: DATA);
+    error: allOf([error, contains('Package has 1 warning.')]),
+    exitCode: DATA,
+    environment: environment,
+  );
 }
 
-Future<void> expectValidationError(String text) async {
+Future<void> expectValidationError(String text,
+    {Map<String, String> environment = const {}}) async {
   await expectValidation(
       error: allOf([
         contains(text),
         contains('Package validation found the following error:')
       ]),
-      exitCode: DATA);
+      exitCode: DATA,
+      environment: environment);
 }
 
 Future<void> setUpDependency(dep,
@@ -56,6 +65,7 @@
   for (final version in hostedVersions) {
     server.serve('foo', version);
   }
+
   await package(deps: {'foo': dep}).create();
 }
 
@@ -63,206 +73,186 @@
   group('should consider a package valid if it', () {
     test('looks normal', () async {
       await package().create();
-      await expectValidation();
+      await expectValidation(environment: {'_PUB_TEST_SDK_VERSION': '1.18.0'});
     });
 
     test('has a ^ constraint with an appropriate SDK constraint', () async {
+      (await servePackages()).serve('foo', '1.2.3');
       await package(deps: {'foo': '^1.2.3'}).create();
-      await expectValidation();
+      await expectValidation(environment: {'_PUB_TEST_SDK_VERSION': '1.18.0'});
     });
 
     test('with a dependency on a pre-release while being one', () async {
+      (await servePackages()).serve('foo', '1.2.3-dev');
       await package(version: '1.0.0-dev', deps: {'foo': '^1.2.3-dev'}).create();
 
-      await expectValidation();
+      await expectValidation(environment: {'_PUB_TEST_SDK_VERSION': '1.18.0'});
     });
 
     test('has a git path dependency with an appropriate SDK constraint',
         () async {
       await servePackages();
+      await d.git('foo', [
+        d.dir('subdir', [d.libPubspec('foo', '1.0.0', sdk: '^2.0.0')]),
+      ]).create();
       await package(deps: {
         'foo': {
-          'git': {'url': 'git://github.com/dart-lang/foo', 'path': 'subdir'}
+          'git': {'url': '../foo', 'path': 'subdir'}
         }
       }, sdk: '>=2.0.0 <3.0.0')
           .create();
 
       // We should get a warning for using a git dependency, but not an error.
-      await expectValidationWarning('  foo: any');
+      await expectValidationWarning(
+          allOf([
+            contains('  foo: any'),
+          ]),
+          environment: {'_PUB_TEST_SDK_VERSION': '2.0.0'});
     });
 
     test('depends on Flutter from an SDK source', () async {
+      await d.dir('flutter', [d.file('version', '1.2.3')]).create();
+      await flutterPackage('flutter', sdk: '>=1.19.0 <2.0.0').create();
       await package(deps: {
         'flutter': {'sdk': 'flutter'}
       }, sdk: '>=1.19.0 <2.0.0')
           .create();
 
-      await expectValidation();
-    });
-
-    test(
-        'depends on a package from Flutter with an appropriate Dart SDK '
-        'constraint', () async {
-      await package(
-        deps: {
-          'foo': {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'},
+      await expectValidation(
+        environment: {
+          '_PUB_TEST_SDK_VERSION': '1.19.0',
+          'FLUTTER_ROOT': path.join(d.sandbox, 'flutter')
         },
-        sdk: '>=1.19.0 <2.0.0',
-      ).create();
-
-      await expectValidation();
+      );
     });
 
     test(
-        'depends on a package from Fuchsia with an appropriate Dart SDK '
-        'constraint', () async {
-      await package(sdk: '>=2.0.0-dev.51.0 <2.0.0', deps: {
-        'foo': {'sdk': 'fuchsia', 'version': '>=1.2.3 <2.0.0'}
-      }).create();
-      await d.validPackage.create();
+      'depends on a package from Flutter with an appropriate Dart SDK constraint',
+      () async {
+        await d.dir('flutter', [d.file('version', '1.2.3')]).create();
+        await flutterPackage('foo', sdk: '^1.0.0').create();
+        await d.dir('flutter', [d.file('version', '1.2.3')]).create();
+        await package(
+          deps: {
+            'foo': {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'},
+          },
+          sdk: '>=1.19.0 <2.0.0',
+        ).create();
 
-      await expectValidation();
-    });
+        await expectValidation(
+          environment: {
+            '_PUB_TEST_SDK_VERSION': '1.19.0',
+            'FLUTTER_ROOT': path.join(d.sandbox, 'flutter'),
+          },
+        );
+      },
+    );
+
+    test(
+      'depends on a package from Fuchsia with an appropriate Dart SDK constraint',
+      () async {
+        await fuschiaPackage('foo', sdk: '>=2.0.0 <3.0.0').create();
+        await package(sdk: '>=2.0.0 <3.0.0', deps: {
+          'foo': {'sdk': 'fuchsia', 'version': '>=1.2.3 <2.0.0'}
+        }).create();
+
+        await expectValidation(environment: {
+          'FUCHSIA_DART_SDK_ROOT': path.join(d.sandbox, 'fuchsia'),
+          '_PUB_TEST_SDK_VERSION': '2.12.0',
+        });
+      },
+    );
   });
 
   group('should consider a package invalid if it', () {
     setUp(package().create);
-    group('has a git dependency', () {
-      group('where a hosted version exists', () {
-        test('and should suggest the hosted primary version', () async {
-          await setUpDependency({'git': 'git://github.com/dart-lang/foo'},
-              hostedVersions: ['3.0.0-pre', '2.0.0', '1.0.0']);
-          await expectValidationWarning('  foo: ^2.0.0');
-        });
-
-        test(
-            'and should suggest the hosted prerelease version if '
-            "it's the only version available", () async {
-          await setUpDependency({'git': 'git://github.com/dart-lang/foo'},
-              hostedVersions: ['3.0.0-pre', '2.0.0-pre']);
-          await expectValidationWarning('  foo: ^3.0.0-pre');
-        });
-
-        test(
-            'and should suggest a tighter constraint if primary is '
-            'pre-1.0.0', () async {
-          await setUpDependency({'git': 'git://github.com/dart-lang/foo'},
-              hostedVersions: ['0.0.1', '0.0.2']);
-          await expectValidationWarning('  foo: ^0.0.2');
-        });
-      });
-
-      group('where no hosted version exists', () {
-        test("and should use the other source's version", () async {
-          await setUpDependency({
-            'git': 'git://github.com/dart-lang/foo',
-            'version': '>=1.0.0 <2.0.0'
-          });
-          await expectValidationWarning('  foo: ">=1.0.0 <2.0.0"');
-        });
-
-        test(
-            "and should use the other source's unquoted version if "
-            'concrete', () async {
-          await setUpDependency(
-              {'git': 'git://github.com/dart-lang/foo', 'version': '0.2.3'});
-          await expectValidationWarning('  foo: 0.2.3');
-        });
-      });
-    });
 
     group('has a path dependency', () {
       group('where a hosted version exists', () {
         test('and should suggest the hosted primary version', () async {
+          await d.dir('foo', [
+            d.libPubspec('foo', '1.2.3', sdk: 'any'),
+          ]).create();
           await setUpDependency({'path': path.join(d.sandbox, 'foo')},
               hostedVersions: ['3.0.0-pre', '2.0.0', '1.0.0']);
-          await expectValidationError('  foo: ^2.0.0');
+          await expectValidationError(
+            '  foo: ^2.0.0',
+            environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
+          );
         });
 
         test(
             'and should suggest the hosted prerelease version if '
             "it's the only version available", () async {
-          await setUpDependency({'path': path.join(d.sandbox, 'foo')},
-              hostedVersions: ['3.0.0-pre', '2.0.0-pre']);
-          await expectValidationError('  foo: ^3.0.0-pre');
+          await d.dir('foo', [
+            d.libPubspec('foo', '1.2.3', sdk: 'any'),
+          ]).create();
+          await setUpDependency(
+            {'path': path.join(d.sandbox, 'foo')},
+            hostedVersions: ['3.0.0-pre', '2.0.0-pre'],
+          );
+          await expectValidationError(
+            '  foo: ^3.0.0-pre',
+            environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
+          );
         });
 
         test(
             'and should suggest a tighter constraint if primary is '
             'pre-1.0.0', () async {
-          await setUpDependency({'path': path.join(d.sandbox, 'foo')},
-              hostedVersions: ['0.0.1', '0.0.2']);
-          await expectValidationError('  foo: ^0.0.2');
+          await d.dir('foo', [
+            d.libPubspec('foo', '1.2.3', sdk: 'any'),
+          ]).create();
+          await setUpDependency(
+            {'path': path.join(d.sandbox, 'foo')},
+            hostedVersions: ['0.0.1', '0.0.2'],
+          );
+          await expectValidationError(
+            '  foo: ^0.0.2',
+            environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
+          );
         });
       });
 
       group('where no hosted version exists', () {
         test("and should use the other source's version", () async {
+          await d.dir('foo', [
+            d.libPubspec('foo', '1.2.3', sdk: 'any'),
+          ]).create();
           await setUpDependency({
             'path': path.join(d.sandbox, 'foo'),
             'version': '>=1.0.0 <2.0.0'
           });
-          await expectValidationError('  foo: ">=1.0.0 <2.0.0"');
+          await expectValidationError(
+            '  foo: ">=1.0.0 <2.0.0"',
+            environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
+          );
         });
 
         test(
             "and should use the other source's unquoted version if "
             'concrete', () async {
+          await d.dir('foo', [
+            d.libPubspec('foo', '0.2.3', sdk: '^1.8.0'),
+          ]).create();
           await setUpDependency(
               {'path': path.join(d.sandbox, 'foo'), 'version': '0.2.3'});
-          await expectValidationError('  foo: 0.2.3');
+          await expectValidationError(
+            '  foo: 0.2.3',
+            environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
+          );
         });
       });
     });
 
     group('has an unconstrained dependency', () {
-      group('and it should not suggest a version', () {
-        test("if there's no lockfile", () async {
-          await d.dir(appPath, [
-            d.libPubspec('test_pkg', '1.0.0', deps: {'foo': 'any'})
-          ]).create();
-
-          await expectValidationWarning(isNot(contains('\n  foo:')));
-        });
-
-        test("if the lockfile doesn't have an entry for the dependency",
-            () async {
-          await d.dir(appPath, [
-            d.libPubspec('test_pkg', '1.0.0', deps: {'foo': 'any'}),
-            d.file(
-                'pubspec.lock',
-                jsonEncode({
-                  'packages': {
-                    'bar': {
-                      'version': '1.2.3',
-                      'source': 'hosted',
-                      'description': {'name': 'bar', 'url': 'https://pub.dev'}
-                    }
-                  }
-                }))
-          ]).create();
-
-          await expectValidationWarning(isNot(contains('\n  foo:')));
-        });
-      });
-
       group('with a lockfile', () {
         test(
             'and it should suggest a constraint based on the locked '
             'version', () async {
+          (await servePackages()).serve('foo', '1.2.3');
           await d.dir(appPath, [
             d.libPubspec('test_pkg', '1.0.0', deps: {'foo': 'any'}),
-            d.file(
-                'pubspec.lock',
-                jsonEncode({
-                  'packages': {
-                    'foo': {
-                      'version': '1.2.3',
-                      'source': 'hosted',
-                      'description': {'name': 'foo', 'url': 'https://pub.dev'}
-                    }
-                  }
-                }))
           ]).create();
 
           await expectValidationWarning('  foo: ^1.2.3');
@@ -271,6 +261,8 @@
         test(
             'and it should suggest a concrete constraint if the locked '
             'version is pre-1.0.0', () async {
+          (await servePackages()).serve('foo', '0.1.2');
+
           await d.dir(appPath, [
             d.libPubspec('test_pkg', '1.0.0', deps: {'foo': 'any'}),
             d.file(
@@ -292,20 +284,24 @@
     });
 
     test('with a dependency on a pre-release without being one', () async {
+      (await servePackages()).serve('foo', '1.2.3-dev');
+
       await d.dir(appPath, [
         d.libPubspec(
           'test_pkg',
           '1.0.0',
           deps: {'foo': '^1.2.3-dev'},
-          sdk: '>=1.19.0 <2.0.0',
+          sdk: '>=1.8.0 <2.0.0',
         )
       ]).create();
 
-      await expectValidationWarning('Packages dependent on a pre-release');
+      await expectValidationWarning('Packages dependent on a pre-release',
+          environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'});
     });
     test(
         'with a single-version dependency and it should suggest a '
         'constraint based on the version', () async {
+      (await servePackages()).serve('foo', '1.2.3');
       await d.dir(appPath, [
         d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '1.2.3'})
       ]).create();
@@ -314,104 +310,69 @@
     });
 
     group('has a dependency without a lower bound', () {
-      group('and it should not suggest a version', () {
-        test("if there's no lockfile", () async {
-          await d.dir(appPath, [
-            d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '<3.0.0'})
-          ]).create();
+      test(
+          'and it should suggest a constraint based on the locked '
+          'version', () async {
+        (await servePackages()).serve('foo', '1.2.3');
 
-          await expectValidationWarning(isNot(contains('\n  foo:')));
-        });
+        await d.dir(appPath, [
+          d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '<3.0.0'}),
+          d.file(
+            'pubspec.lock',
+          )
+        ]).create();
 
-        test(
-            "if the lockfile doesn't have an entry for the "
-            'dependency', () async {
-          await d.dir(appPath, [
-            d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '<3.0.0'}),
-            d.file(
-                'pubspec.lock',
-                jsonEncode({
-                  'packages': {
-                    'bar': {
-                      'version': '1.2.3',
-                      'source': 'hosted',
-                      'description': {'name': 'bar', 'url': 'https://pub.dev'}
-                    }
-                  }
-                }))
-          ]).create();
-
-          await expectValidationWarning(isNot(contains('\n  foo:')));
-        });
+        await expectValidationWarning('  foo: ">=1.2.3 <3.0.0"');
       });
 
-      group('with a lockfile', () {
-        test(
-            'and it should suggest a constraint based on the locked '
-            'version', () async {
-          await d.dir(appPath, [
-            d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '<3.0.0'}),
-            d.file(
-                'pubspec.lock',
-                jsonEncode({
-                  'packages': {
-                    'foo': {
-                      'version': '1.2.3',
-                      'source': 'hosted',
-                      'description': {'name': 'foo', 'url': 'https://pub.dev'}
-                    }
+      test('and it should preserve the upper-bound operator', () async {
+        (await servePackages()).serve('foo', '1.2.3');
+        await d.dir(appPath, [
+          d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '<=3.0.0'}),
+          d.file(
+              'pubspec.lock',
+              jsonEncode({
+                'packages': {
+                  'foo': {
+                    'version': '1.2.3',
+                    'source': 'hosted',
+                    'description': {'name': 'foo', 'url': 'https://pub.dev'}
                   }
-                }))
-          ]).create();
+                }
+              }))
+        ]).create();
 
-          await expectValidationWarning('  foo: ">=1.2.3 <3.0.0"');
-        });
+        await expectValidationWarning('  foo: ">=1.2.3 <=3.0.0"');
+      });
 
-        test('and it should preserve the upper-bound operator', () async {
-          await d.dir(appPath, [
-            d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '<=3.0.0'}),
-            d.file(
-                'pubspec.lock',
-                jsonEncode({
-                  'packages': {
-                    'foo': {
-                      'version': '1.2.3',
-                      'source': 'hosted',
-                      'description': {'name': 'foo', 'url': 'https://pub.dev'}
-                    }
+      test(
+          'and it should expand the suggested constraint if the '
+          'locked version matches the upper bound', () async {
+        (await servePackages()).serve('foo', '1.2.3');
+
+        await d.dir(appPath, [
+          d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '<=1.2.3'}),
+          d.file(
+              'pubspec.lock',
+              jsonEncode({
+                'packages': {
+                  'foo': {
+                    'version': '1.2.3',
+                    'source': 'hosted',
+                    'description': {'name': 'foo', 'url': 'https://pub.dev'}
                   }
-                }))
-          ]).create();
+                }
+              }))
+        ]).create();
 
-          await expectValidationWarning('  foo: ">=1.2.3 <=3.0.0"');
-        });
-
-        test(
-            'and it should expand the suggested constraint if the '
-            'locked version matches the upper bound', () async {
-          await d.dir(appPath, [
-            d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '<=1.2.3'}),
-            d.file(
-                'pubspec.lock',
-                jsonEncode({
-                  'packages': {
-                    'foo': {
-                      'version': '1.2.3',
-                      'source': 'hosted',
-                      'description': {'name': 'foo', 'url': 'https://pub.dev'}
-                    }
-                  }
-                }))
-          ]).create();
-
-          await expectValidationWarning('  foo: ^1.2.3');
-        });
+        await expectValidationWarning('  foo: ^1.2.3');
       });
     });
 
     group('with a dependency without an upper bound', () {
       test('and it should suggest a constraint based on the lower bound',
           () async {
+        (await servePackages()).serve('foo', '1.2.3');
         await d.dir(appPath, [
           d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '>=1.2.3'})
         ]).create();
@@ -420,6 +381,7 @@
       });
 
       test('and it should preserve the lower-bound operator', () async {
+        (await servePackages()).serve('foo', '1.2.4');
         await d.dir(appPath, [
           d.libPubspec('test_pkg', '1.0.0', deps: {'foo': '>1.2.3'})
         ]).create();
@@ -429,21 +391,17 @@
     });
 
     group('has a ^ dependency', () {
-      test('without an SDK constraint', () async {
-        await d.dir(appPath, [
-          d.libPubspec('integration_pkg', '1.0.0', deps: {'foo': '^1.2.3'})
-        ]).create();
-
-        await expectValidationError('  sdk: ">=1.8.0 <2.0.0"');
-      });
-
       test('with a too-broad SDK constraint', () async {
+        (await servePackages()).serve('foo', '1.2.3');
         await d.dir(appPath, [
           d.libPubspec('test_pkg', '1.0.0',
               deps: {'foo': '^1.2.3'}, sdk: '>=1.5.0 <2.0.0')
         ]).create();
 
-        await expectValidationError('  sdk: ">=1.8.0 <2.0.0"');
+        await expectValidationError(
+          '  sdk: ">=1.8.0 <2.0.0"',
+          environment: {'_PUB_TEST_SDK_VERSION': '1.5.0'},
+        );
       });
     });
 
@@ -451,17 +409,22 @@
       test('without an SDK constraint', () async {
         // Ensure we don't report anything from the real pub.dev.
         await setUpDependency({});
+        await d.git('foo', [
+          d.dir('subdir', [d.libPubspec('foo', '1.0.0')]),
+        ]).create();
         await d.dir(appPath, [
           d.libPubspec('integration_pkg', '1.0.0', deps: {
             'foo': {
-              'git': {'url': 'git://github.com/dart-lang/foo', 'path': 'subdir'}
+              'git': {'url': d.path('foo'), 'path': 'subdir'}
             }
           })
         ]).create();
 
         await expectValidation(
           error: allOf(
-              contains('  sdk: ">=2.0.0 <3.0.0"'), contains('  foo: any')),
+            contains('  sdk: ">=2.0.0 <3.0.0"'),
+            contains('  foo: any'),
+          ),
           exitCode: DATA,
         );
       });
@@ -469,14 +432,15 @@
       test('with a too-broad SDK constraint', () async {
         // Ensure we don't report anything from the real pub.dev.
         await setUpDependency({});
+        await d.git('foo', [
+          d.dir(
+              'subdir', [d.libPubspec('foo', '1.0.0', sdk: '>=0.0.0 <3.0.0')]),
+        ]).create();
         await d.dir(appPath, [
           d.libPubspec('integration_pkg', '1.0.0',
               deps: {
                 'foo': {
-                  'git': {
-                    'url': 'git://github.com/dart-lang/foo',
-                    'path': 'subdir'
-                  }
+                  'git': {'url': d.path('foo'), 'path': 'subdir'}
                 }
               },
               sdk: '>=1.24.0 <3.0.0')
@@ -487,12 +451,14 @@
             contains('  sdk: ">=2.0.0 <3.0.0"'),
             contains('  foo: any'),
           ]),
+          environment: {'_PUB_TEST_SDK_VERSION': '1.24.0'},
           exitCode: DATA,
         );
       });
     });
 
     test('depends on Flutter from a non-SDK source', () async {
+      (await servePackages()).serve('flutter', '1.5.0');
       await d.dir(appPath, [
         d.libPubspec('test_pkg', '1.0.0', deps: {'flutter': '>=1.2.3 <2.0.0'})
       ]).create();
@@ -500,16 +466,10 @@
       await expectValidationError('sdk: >=1.2.3 <2.0.0');
     });
 
-    test('depends on a Flutter package from an unknown SDK', () async {
-      await package(deps: {
-        'foo': {'sdk': 'fblthp', 'version': '>=1.2.3 <2.0.0'}
-      }).create();
-
-      await expectValidationError('Unknown SDK "fblthp" for dependency "foo".');
-    });
-
     test('depends on a Flutter package with a too-broad SDK constraint',
         () async {
+      await d.dir('flutter', [d.file('version', '1.2.3')]).create();
+      await flutterPackage('foo', sdk: 'any').create();
       await package(
         deps: {
           'foo': {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}
@@ -517,35 +477,79 @@
         sdk: '>=1.18.0 <2.0.0',
       ).create();
 
-      await expectValidationError('sdk: ">=1.19.0 <2.0.0"');
+      await expectValidationError('sdk: ">=1.19.0 <2.0.0"', environment: {
+        '_PUB_TEST_SDK_VERSION': '1.19.0',
+        'FLUTTER_ROOT': path.join(d.sandbox, 'flutter'),
+      });
     });
 
     test('depends on a Flutter package with no SDK constraint', () async {
+      await d.dir('flutter', [d.file('version', '1.2.3')]).create();
+      await flutterPackage('foo', sdk: '>=0.0.0 <1.0.0').create();
       await package(sdk: '>=0.0.0 <=0.0.1', deps: {
         'foo': {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}
       }).create();
 
-      await expectValidationError('sdk: ">=1.19.0 <2.0.0"');
+      await expectValidationError(
+        'sdk: ">=1.19.0 <2.0.0"',
+        environment: {
+          '_PUB_TEST_SDK_VERSION': '0.0.0',
+          'FLUTTER_ROOT': path.join(d.sandbox, 'flutter'),
+        },
+      );
     });
 
     test('depends on a Fuchsia package with a too-broad SDK constraint',
         () async {
+      await fuschiaPackage('foo', sdk: '>=0.0.0 <3.0.0').create();
+
       await package(
-        sdk: '>=2.0.0-dev.50.0 <2.0.0',
+        sdk: '>=2.0.0-dev.50.0 <2.0.1',
         deps: {
           'foo': {'sdk': 'fuchsia', 'version': '>=1.2.3 <2.0.0'}
         },
       ).create();
 
-      await expectValidationError('sdk: ">=2.0.0 <3.0.0"');
+      await expectValidationError('sdk: ">=2.0.0 <2.0.1"', environment: {
+        'FUCHSIA_DART_SDK_ROOT': path.join(d.sandbox, 'fuchsia'),
+        '_PUB_TEST_SDK_VERSION': '2.0.1-dev.51.0',
+      });
     });
 
     test('depends on a Fuchsia package with no SDK constraint', () async {
+      await fuschiaPackage('foo').create();
       await package(sdk: '>=0.0.0 <1.0.0', deps: {
         'foo': {'sdk': 'fuchsia', 'version': '>=1.2.3 <2.0.0'}
       }).create();
 
-      await expectValidationError('sdk: ">=2.0.0 <3.0.0"');
+      await expectValidationError(
+        'sdk: ">=2.0.0 <3.0.0"',
+        environment: {'FUCHSIA_DART_SDK_ROOT': path.join(d.sandbox, 'fuchsia')},
+      );
     });
   });
 }
+
+d.Descriptor fuschiaPackage(String name,
+    {Map<String, String> deps = const {}, String? sdk}) {
+  return d.dir('fuchsia', [
+    d.dir('packages', [
+      d.dir(name, [
+        d.libDir(name, 'f(x) => 2 * x;'),
+        d.libPubspec(name, '1.5.0', deps: deps, sdk: sdk),
+      ]),
+    ]),
+  ]);
+}
+
+d.Descriptor flutterPackage(String name,
+    {Map<String, String> deps = const {}, String? sdk}) {
+  return d.dir('flutter', [
+    d.dir('packages', [
+      d.dir(name, [
+        d.libDir(name, 'f(x) => 2 * x;'),
+        d.libPubspec(name, '1.5.0', deps: deps, sdk: sdk),
+      ]),
+    ]),
+  ]);
+}
diff --git a/test/validator/flutter_constraint_test.dart b/test/validator/flutter_constraint_test.dart
index b7bdf7c..9e73ef6 100644
--- a/test/validator/flutter_constraint_test.dart
+++ b/test/validator/flutter_constraint_test.dart
@@ -11,17 +11,21 @@
   await runPub(
     error: error,
     args: ['publish', '--dry-run'],
-    environment: {'_PUB_TEST_SDK_VERSION': '2.12.0'},
+    environment: {
+      '_PUB_TEST_SDK_VERSION': '2.12.0',
+      'FLUTTER_ROOT': fakeFlutterRoot.io.path,
+    },
     workingDirectory: d.path(appPath),
     exitCode: exitCode,
   );
 }
 
+late d.DirectoryDescriptor fakeFlutterRoot;
+
 Future<void> setup({
   String? flutterConstraint,
 }) async {
-  final fakeFlutterRoot =
-      d.dir('fake_flutter_root', [d.file('version', '1.23.0')]);
+  fakeFlutterRoot = d.dir('fake_flutter_root', [d.file('version', '1.23.0')]);
   await fakeFlutterRoot.create();
   await d.validPackage.create();
   await d.dir(appPath, [
diff --git a/test/validator/gitignore_test.dart b/test/validator/gitignore_test.dart
index 3cd4a11..f4ec65c 100644
--- a/test/validator/gitignore_test.dart
+++ b/test/validator/gitignore_test.dart
@@ -20,7 +20,7 @@
   await runPub(
     error: error,
     args: ['publish', '--dry-run'],
-    environment: {'_PUB_TEST_SDK_VERSION': '2.12.0', ...environment},
+    environment: environment,
     workingDirectory: workingDirectory ?? d.path(appPath),
     exitCode: exitCode,
   );
@@ -35,8 +35,6 @@
       d.file('foo.txt'),
     ]).create();
 
-    await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
     await expectValidation(contains('Package has 0 warnings.'), 0);
 
     await d.dir('myapp', [
@@ -60,7 +58,7 @@
       d.file('foo.txt'),
     ]).create();
 
-    await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
+    await pubGet();
     await setUpFakeGitScript(bash: 'echo "Not git"', batch: 'echo "Not git"');
     await expectValidation(
         allOf([contains('Package has 0 warnings.')]), exit_codes.SUCCESS,
@@ -78,9 +76,7 @@
       ),
     ]).create();
     final packageRoot = p.join(d.sandbox, 'reporoot', 'myapp');
-    await pubGet(
-        environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'},
-        workingDirectory: packageRoot);
+    await pubGet(workingDirectory: packageRoot);
 
     await expectValidation(contains('Package has 0 warnings.'), 0,
         workingDirectory: packageRoot);
@@ -105,9 +101,7 @@
       ...d.validPackage.contents,
     ]).create();
     final packageRoot = p.join(d.sandbox, 'myapp');
-    await pubGet(
-        environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'},
-        workingDirectory: packageRoot);
+    await pubGet(workingDirectory: packageRoot);
 
     Link(p.join(packageRoot, '.abc', 'itself')).createSync(
       packageRoot,
diff --git a/test/validator/readme_test.dart b/test/validator/readme_test.dart
index 17b0602..934feae 100644
--- a/test/validator/readme_test.dart
+++ b/test/validator/readme_test.dart
@@ -15,8 +15,6 @@
 Validator readme() => ReadmeValidator();
 
 void main() {
-  setUp(d.validPackage.create);
-
   group('should consider a package valid if it', () {
     test('looks normal', () async {
       await d.validPackage.create();