Merge remote-tracking branch 'origin/cherry-pick2-for-2.15.0'
diff --git a/analysis_options.yaml b/analysis_options.yaml
index f469a93..f07a060 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,4 +1,4 @@
-include: package:pedantic/analysis_options.yaml
+include: package:lints/recommended.yaml
 
 analyzer:
   errors:
@@ -12,52 +12,26 @@
 linter:
   rules:
     - avoid_catching_errors
-    - avoid_function_literals_in_foreach_calls
     - avoid_private_typedef_functions
     - avoid_redundant_argument_values
-    - avoid_renaming_method_parameters
     - avoid_returning_null_for_future
-    - avoid_returning_null_for_void
     - avoid_unused_constructor_parameters
     - avoid_void_async
-    - await_only_futures
-    - camel_case_types
     - cancel_subscriptions
-    - control_flow_in_finally
     - directives_ordering
-    - empty_statements
-    - file_names
-    - implementation_imports
-    - iterable_contains_unrelated_type
-    - list_remove_unrelated_type
     - missing_whitespace_between_adjacent_strings
     - no_adjacent_strings_in_list
     - no_runtimeType_toString
-    - non_constant_identifier_names
     - only_throw_errors
-    - overridden_fields
     - package_api_docs
-    - package_names
-    - package_prefixed_library_names
     - prefer_asserts_in_initializer_lists
     - prefer_const_declarations
-    - prefer_function_declarations_over_variables
-    - prefer_initializing_formals
-    - prefer_inlined_adds
-    - prefer_is_not_operator
-    - prefer_null_aware_operators
     - prefer_relative_imports
-    - prefer_typing_uninitialized_variables
-    - prefer_void_to_null
+    - prefer_single_quotes
     - sort_pub_dependencies
     - test_types_in_equals
     - throw_in_finally
-    - unnecessary_brace_in_string_interps
-    - unnecessary_getters_setters
     - unnecessary_lambdas
     - unnecessary_null_aware_assignments
-    - unnecessary_overrides
     - unnecessary_parenthesis
     - unnecessary_statements
-    - unnecessary_string_interpolations
-    - void_checks
diff --git a/doc/repository-spec-v2.md b/doc/repository-spec-v2.md
index 6db7763..aa65e14 100644
--- a/doc/repository-spec-v2.md
+++ b/doc/repository-spec-v2.md
@@ -371,7 +371,9 @@
 archive size, or enforce any other repository specific constraints.
 
 This upload flow allows for archives to be uploaded directly to a signed POST
-URL for S3, GCS or similar blob storage service. Both the
+URL for [S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/HTTPPOSTExamples.html),
+[GCS](https://cloud.google.com/storage/docs/xml-api/post-object-forms) or
+similar blob storage service. Both the
 `<multipart-upload-url>` and `<finalize-upload-url>` is allowed to contain
 query-string parameters, and both of these URLs need only be temporary.
 
diff --git a/lib/src/authentication/client.dart b/lib/src/authentication/client.dart
index 1f37149..a6001ec 100644
--- a/lib/src/authentication/client.dart
+++ b/lib/src/authentication/client.dart
@@ -8,7 +8,6 @@
 import 'package:http/http.dart' as http;
 import 'package:http_parser/http_parser.dart';
 
-import '../exceptions.dart';
 import '../http.dart';
 import '../log.dart' as log;
 import '../system_cache.dart';
@@ -22,14 +21,17 @@
   /// Constructs Http client wrapper that injects `authorization` header to
   /// requests and handles authentication errors.
   ///
-  /// [credential] might be `null`. In that case `authorization` header will not
+  /// [_credential] might be `null`. In that case `authorization` header will not
   /// be injected to requests.
-  _AuthenticatedClient(this._inner, this.credential);
+  _AuthenticatedClient(this._inner, this._credential);
 
   final http.BaseClient _inner;
 
   /// Authentication scheme that could be used for authenticating requests.
-  final Credential? credential;
+  final Credential? _credential;
+
+  /// Detected that [_credential] are invalid, happens when server responds 401.
+  bool _detectInvalidCredentials = false;
 
   @override
   Future<http.StreamedResponse> send(http.BaseRequest request) async {
@@ -40,15 +42,16 @@
     // to given serverBaseUrl. Otherwise credential leaks might ocurr when
     // archive_url hosted on 3rd party server that should not receive
     // credentials of the first party.
-    if (credential != null &&
-        credential!.canAuthenticate(request.url.toString())) {
+    if (_credential != null &&
+        _credential!.canAuthenticate(request.url.toString())) {
       request.headers[HttpHeaders.authorizationHeader] =
-          await credential!.getAuthorizationHeaderValue();
+          await _credential!.getAuthorizationHeaderValue();
     }
 
     try {
       final response = await _inner.send(request);
       if (response.statusCode == 401) {
+        _detectInvalidCredentials = true;
         _throwAuthException(response);
       }
       return response;
@@ -124,31 +127,17 @@
   Future<T> Function(http.Client) fn,
 ) async {
   final credential = systemCache.tokenStore.findCredential(hostedUrl);
-  final http.Client client = _AuthenticatedClient(httpClient, credential);
+  final client = _AuthenticatedClient(httpClient, credential);
 
   try {
     return await fn(client);
-  } on AuthenticationException catch (error) {
-    var message = '';
-
-    if (error.statusCode == 401) {
-      if (systemCache.tokenStore.removeCredential(hostedUrl)) {
+  } finally {
+    if (client._detectInvalidCredentials) {
+      // try to remove the credential, if we detected that it is invalid!
+      final removed = systemCache.tokenStore.removeCredential(hostedUrl);
+      if (removed) {
         log.warning('Invalid token for $hostedUrl deleted.');
       }
-      message = '$hostedUrl package repository requested authentication! '
-          'You can provide credential using:\n'
-          '    pub token add $hostedUrl';
     }
-    if (error.statusCode == 403) {
-      message = 'Insufficient permissions to the resource in $hostedUrl '
-          'package repository. You can modify credential using:\n'
-          '    pub token add $hostedUrl';
-    }
-
-    if (error.serverMessage?.isNotEmpty == true) {
-      message += '\n${error.serverMessage}';
-    }
-
-    throw DataException(message);
   }
 }
diff --git a/lib/src/command.dart b/lib/src/command.dart
index 53b301a..3f06db1 100644
--- a/lib/src/command.dart
+++ b/lib/src/command.dart
@@ -212,13 +212,13 @@
 
   /// Returns the appropriate exit code for [exception], falling back on 1 if no
   /// appropriate exit code could be found.
-  int _chooseExitCode(exception) {
+  int _chooseExitCode(Object exception) {
     if (exception is SolveFailure) {
       var packageNotFound = exception.packageNotFound;
       if (packageNotFound != null) exception = packageNotFound;
     }
     while (exception is WrappedException && exception.innerError is Exception) {
-      exception = exception.innerError;
+      exception = exception.innerError!;
     }
 
     if (exception is HttpException ||
diff --git a/lib/src/command/add.dart b/lib/src/command/add.dart
index 09cc426..f268381 100644
--- a/lib/src/command/add.dart
+++ b/lib/src/command/add.dart
@@ -111,7 +111,7 @@
       /// that a resolution exists before we update pubspec.yaml.
       // TODO(sigurdm): We should really use a spinner here.
       solveResult = await resolveVersions(
-          SolveType.UPGRADE, cache, Package.inMemory(updatedPubSpec));
+          SolveType.upgrade, cache, Package.inMemory(updatedPubSpec));
     } on GitException {
       dataError('Unable to resolve package "${package.name}" with the given '
           'git parameters.');
@@ -149,7 +149,7 @@
       // TODO(jonasfj): Stop abusing Entrypoint.global for dry-run output
       await Entrypoint.global(newRoot, entrypoint.lockFile, cache,
               solveResult: solveResult)
-          .acquireDependencies(SolveType.GET,
+          .acquireDependencies(SolveType.get,
               dryRun: true,
               precompile: argResults['precompile'],
               analytics: analytics);
@@ -164,14 +164,14 @@
       /// pubspec file.
       final updatedEntrypoint = Entrypoint(directory, cache);
       await updatedEntrypoint.acquireDependencies(
-        SolveType.GET,
+        SolveType.get,
         precompile: argResults['precompile'],
         analytics: analytics,
       );
 
       if (argResults['example'] && entrypoint.example != null) {
         await entrypoint.example!.acquireDependencies(
-          SolveType.GET,
+          SolveType.get,
           precompile: argResults['precompile'],
           onlyReportSuccessOrFailure: true,
           analytics: analytics,
diff --git a/lib/src/command/downgrade.dart b/lib/src/command/downgrade.dart
index 5dd9d41..274ab48 100644
--- a/lib/src/command/downgrade.dart
+++ b/lib/src/command/downgrade.dart
@@ -53,7 +53,7 @@
     var dryRun = argResults['dry-run'];
 
     await entrypoint.acquireDependencies(
-      SolveType.DOWNGRADE,
+      SolveType.downgrade,
       unlock: argResults.rest,
       dryRun: dryRun,
       analytics: analytics,
@@ -61,7 +61,7 @@
     var example = entrypoint.example;
     if (argResults['example'] && example != null) {
       await example.acquireDependencies(
-        SolveType.GET,
+        SolveType.get,
         unlock: argResults.rest,
         dryRun: dryRun,
         onlyReportSuccessOrFailure: true,
diff --git a/lib/src/command/get.dart b/lib/src/command/get.dart
index 9255e1e..302bb93 100644
--- a/lib/src/command/get.dart
+++ b/lib/src/command/get.dart
@@ -50,7 +50,7 @@
           'The --packages-dir flag is no longer used and does nothing.'));
     }
     await entrypoint.acquireDependencies(
-      SolveType.GET,
+      SolveType.get,
       dryRun: argResults['dry-run'],
       precompile: argResults['precompile'],
       analytics: analytics,
@@ -58,7 +58,7 @@
 
     var example = entrypoint.example;
     if (argResults['example'] && example != null) {
-      await example.acquireDependencies(SolveType.GET,
+      await example.acquireDependencies(SolveType.get,
           dryRun: argResults['dry-run'],
           precompile: argResults['precompile'],
           onlyReportSuccessOrFailure: true,
diff --git a/lib/src/command/global_run.dart b/lib/src/command/global_run.dart
index b8f7f1b..71e0a9d 100644
--- a/lib/src/command/global_run.dart
+++ b/lib/src/command/global_run.dart
@@ -17,8 +17,7 @@
   String get name => 'run';
   @override
   String get description =>
-      'Run an executable from a globally activated package.\n'
-      "NOTE: We are currently optimizing this command's startup time.";
+      'Run an executable from a globally activated package.';
   @override
   String get argumentsDescription => '<package>:<executable> [args...]';
   @override
diff --git a/lib/src/command/lish.dart b/lib/src/command/lish.dart
index 24bdea9..c927e07 100644
--- a/lib/src/command/lish.dart
+++ b/lib/src/command/lish.dart
@@ -120,6 +120,22 @@
         handleJsonSuccess(
             await client.get(Uri.parse(location), headers: pubApiHeaders));
       });
+    } on AuthenticationException catch (error) {
+      var msg = '';
+      if (error.statusCode == 401) {
+        msg += '$server package repository requested authentication!\n'
+            'You can provide credentials using:\n'
+            '    pub token add $server\n';
+      }
+      if (error.statusCode == 403) {
+        msg += 'Insufficient permissions to the resource at the $server '
+            'package repository.\nYou can modify credentials using:\n'
+            '    pub token add $server\n';
+      }
+      if (error.serverMessage != null) {
+        msg += '\n' + error.serverMessage! + '\n';
+      }
+      dataError(msg + log.red('Authentication failed!'));
     } on PubHttpException catch (error) {
       var url = error.response.request!.url;
       if (url == cloudStorageUrl) {
diff --git a/lib/src/command/outdated.dart b/lib/src/command/outdated.dart
index cedbadf..609b7ae 100644
--- a/lib/src/command/outdated.dart
+++ b/lib/src/command/outdated.dart
@@ -392,7 +392,7 @@
 /// resolution was found.
 Future<List<PackageId>?> _tryResolve(Pubspec pubspec, SystemCache cache) async {
   final solveResult = await tryResolveVersions(
-    SolveType.UPGRADE,
+    SolveType.upgrade,
     cache,
     Package.inMemory(pubspec),
   );
@@ -833,6 +833,9 @@
           _overridden == other._overridden &&
           _id.source == other._id.source &&
           _pubspec.version == other._pubspec.version;
+
+  @override
+  int get hashCode => Object.hash(_pubspec.version, _id.source, _overridden);
 }
 
 class _PackageDetails implements Comparable<_PackageDetails> {
diff --git a/lib/src/command/remove.dart b/lib/src/command/remove.dart
index c7c674a..af91d8c 100644
--- a/lib/src/command/remove.dart
+++ b/lib/src/command/remove.dart
@@ -66,7 +66,7 @@
       final newRoot = Package.inMemory(newPubspec);
 
       await Entrypoint.global(newRoot, entrypoint.lockFile, cache)
-          .acquireDependencies(SolveType.GET,
+          .acquireDependencies(SolveType.get,
               precompile: argResults['precompile'],
               dryRun: true,
               analytics: null);
@@ -78,7 +78,7 @@
       /// pubspec file.
       final updatedEntrypoint = Entrypoint(directory, cache);
       await updatedEntrypoint.acquireDependencies(
-        SolveType.GET,
+        SolveType.get,
         precompile: argResults['precompile'],
         analytics: analytics,
       );
@@ -86,7 +86,7 @@
       var example = entrypoint.example;
       if (argResults['example'] && example != null) {
         await example.acquireDependencies(
-          SolveType.GET,
+          SolveType.get,
           precompile: argResults['precompile'],
           onlyReportSuccessOrFailure: true,
           analytics: analytics,
diff --git a/lib/src/command/upgrade.dart b/lib/src/command/upgrade.dart
index 8e44abf..34e061d 100644
--- a/lib/src/command/upgrade.dart
+++ b/lib/src/command/upgrade.dart
@@ -121,7 +121,7 @@
 
   Future<void> _runUpgrade(Entrypoint e, {bool onlySummary = false}) async {
     await e.acquireDependencies(
-      SolveType.UPGRADE,
+      SolveType.upgrade,
       unlock: argResults.rest,
       dryRun: _dryRun,
       precompile: _precompile,
@@ -179,7 +179,7 @@
     final resolvedPackages = <String, PackageId>{};
     final solveResult = await log.spinner('Resolving dependencies', () async {
       return await resolveVersions(
-        SolveType.UPGRADE,
+        SolveType.upgrade,
         cache,
         Package.inMemory(resolvablePubspec),
       );
@@ -229,7 +229,7 @@
         cache,
         solveResult: solveResult,
       ).acquireDependencies(
-        SolveType.UPGRADE,
+        SolveType.upgrade,
         dryRun: true,
         precompile: _precompile,
         analytics: null, // No analytics for dry-run
@@ -241,7 +241,7 @@
       //       we can show the changes when not in --dry-run mode. For now we only show
       //       the changes made to pubspec.yaml in dry-run mode.
       await Entrypoint(directory, cache).acquireDependencies(
-        SolveType.UPGRADE,
+        SolveType.upgrade,
         precompile: _precompile,
         analytics: analytics,
       );
@@ -276,7 +276,7 @@
     final resolvedPackages = <String, PackageId>{};
     final solveResult = await log.spinner('Resolving dependencies', () async {
       return await resolveVersions(
-        SolveType.UPGRADE,
+        SolveType.upgrade,
         cache,
         Package.inMemory(nullsafetyPubspec),
       );
@@ -323,7 +323,7 @@
         cache,
         solveResult: solveResult,
       ).acquireDependencies(
-        SolveType.UPGRADE,
+        SolveType.upgrade,
         dryRun: true,
         precompile: _precompile,
         analytics: null,
@@ -335,7 +335,7 @@
       //       we can show the changes in --dry-run mode. For now we only show
       //       the changes made to pubspec.yaml in dry-run mode.
       await Entrypoint(directory, cache).acquireDependencies(
-        SolveType.UPGRADE,
+        SolveType.upgrade,
         precompile: _precompile,
         analytics: analytics,
       );
diff --git a/lib/src/command_runner.dart b/lib/src/command_runner.dart
index 4ed33f6..02faaf9 100644
--- a/lib/src/command_runner.dart
+++ b/lib/src/command_runner.dart
@@ -58,21 +58,21 @@
   Verbosity get verbosity {
     switch (argResults['verbosity']) {
       case 'error':
-        return log.Verbosity.ERROR;
+        return log.Verbosity.error;
       case 'warning':
-        return log.Verbosity.WARNING;
+        return log.Verbosity.warning;
       case 'normal':
-        return log.Verbosity.NORMAL;
+        return log.Verbosity.normal;
       case 'io':
-        return log.Verbosity.IO;
+        return log.Verbosity.io;
       case 'solver':
-        return log.Verbosity.SOLVER;
+        return log.Verbosity.solver;
       case 'all':
-        return log.Verbosity.ALL;
+        return log.Verbosity.all;
       default:
         // No specific verbosity given, so check for the shortcut.
-        if (argResults['verbose']) return log.Verbosity.ALL;
-        return log.Verbosity.NORMAL;
+        if (argResults['verbose']) return log.Verbosity.all;
+        return log.Verbosity.normal;
     }
   }
 
diff --git a/lib/src/exceptions.dart b/lib/src/exceptions.dart
index 82a5dac..fcde747 100644
--- a/lib/src/exceptions.dart
+++ b/lib/src/exceptions.dart
@@ -11,7 +11,6 @@
 import 'package:yaml/yaml.dart';
 
 import 'dart.dart';
-import 'sdk.dart';
 
 /// An exception class for exceptions that are intended to be seen by the user.
 ///
@@ -89,18 +88,20 @@
 /// that other code in pub can use this to show a more detailed explanation of
 /// why the package was being requested.
 class PackageNotFoundException extends WrappedException {
-  /// If this failure was caused by an SDK being unavailable, this is that SDK.
-  final Sdk? missingSdk;
+  /// A hint indicating an action the user could take to resolve this problem.
+  ///
+  /// This will be printed after the package resolution conflict.
+  final String? hint;
 
   PackageNotFoundException(
     String message, {
     Object? innerError,
     StackTrace? innerTrace,
-    this.missingSdk,
+    this.hint,
   }) : super(message, innerError, innerTrace);
 
   @override
-  String toString() => "Package doesn't exist ($message).";
+  String toString() => 'Package not available ($message).';
 }
 
 /// Returns whether [error] is a user-facing error object.
diff --git a/lib/src/executable.dart b/lib/src/executable.dart
index 2112acc..5d8ea8b 100644
--- a/lib/src/executable.dart
+++ b/lib/src/executable.dart
@@ -306,7 +306,7 @@
     try {
       await warningsOnlyUnlessTerminal(
         () => entrypoint.acquireDependencies(
-          SolveType.GET,
+          SolveType.get,
           analytics: analytics,
         ),
       );
diff --git a/lib/src/exit_codes.dart b/lib/src/exit_codes.dart
index e072ef2..c6acaf7 100644
--- a/lib/src/exit_codes.dart
+++ b/lib/src/exit_codes.dart
@@ -2,6 +2,8 @@
 // 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.
 
+// ignore_for_file: constant_identifier_names
+
 /// Exit code constants.
 ///
 /// From [the BSD sysexits manpage][manpage]. Not every constant here is used,
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index 578eca1..a868b4b 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -149,7 +149,7 @@
     var entrypoint = Entrypoint(path, cache);
 
     // Get the package's dependencies.
-    await entrypoint.acquireDependencies(SolveType.GET, analytics: analytics);
+    await entrypoint.acquireDependencies(SolveType.get, analytics: analytics);
     var name = entrypoint.root.name;
 
     try {
@@ -201,7 +201,7 @@
     SolveResult result;
     try {
       result = await log.progress('Resolving dependencies',
-          () => resolveVersions(SolveType.GET, cache, root));
+          () => resolveVersions(SolveType.get, cache, root));
     } on SolveFailure catch (error) {
       for (var incompatibility
           in error.incompatibility.externalIncompatibilities) {
@@ -221,7 +221,7 @@
 To recompile executables, first run `$topLevelProgram pub global deactivate ${dep.name}`.
 ''');
     } else {
-      await result.showReport(SolveType.GET, cache);
+      await result.showReport(SolveType.get, cache);
     }
 
     // Make sure all of the dependencies are locally installed.
diff --git a/lib/src/http.dart b/lib/src/http.dart
index fb6e9aa..724962b 100644
--- a/lib/src/http.dart
+++ b/lib/src/http.dart
@@ -10,7 +10,6 @@
 
 import 'package:http/http.dart' as http;
 import 'package:http/retry.dart';
-import 'package:pedantic/pedantic.dart';
 import 'package:pool/pool.dart';
 import 'package:stack_trace/stack_trace.dart';
 
diff --git a/lib/src/ignore.dart b/lib/src/ignore.dart
index ade58d0..fbd93e8 100644
--- a/lib/src/ignore.dart
+++ b/lib/src/ignore.dart
@@ -94,7 +94,7 @@
   /// [1]: https://git-scm.com/docs/gitignore
   /// [2]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreignoreCase
   Ignore(
-    Iterable<String> patterns, {
+    List<String> patterns, {
     bool ignoreCase = false,
     void Function(String pattern, FormatException exception)? onInvalidPattern,
   }) : _rules = _parseIgnorePatterns(
diff --git a/lib/src/io.dart b/lib/src/io.dart
index d6af9c2..231aba5 100644
--- a/lib/src/io.dart
+++ b/lib/src/io.dart
@@ -14,7 +14,6 @@
 import 'package:http_multi_server/http_multi_server.dart';
 import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
-import 'package:pedantic/pedantic.dart';
 import 'package:pool/pool.dart';
 import 'package:stack_trace/stack_trace.dart';
 
diff --git a/lib/src/log.dart b/lib/src/log.dart
index ff7fe29..930e0fb 100644
--- a/lib/src/log.dart
+++ b/lib/src/log.dart
@@ -24,7 +24,7 @@
 final json = _JsonLogger();
 
 /// The current logging verbosity.
-Verbosity verbosity = Verbosity.NORMAL;
+Verbosity verbosity = Verbosity.normal;
 
 /// In cases where there's a ton of log spew, make sure we don't eat infinite
 /// memory.
@@ -32,7 +32,7 @@
 /// This can occur when the backtracking solver stumbles into a pathological
 /// dependency graph. It generally will find a solution, but it may log
 /// thousands and thousands of entries to get there.
-const _MAX_TRANSCRIPT = 10000;
+const _maxTranscript = 10000;
 
 /// The list of recorded log messages. Will only be recorded if
 /// [recordTranscript()] is called.
@@ -58,34 +58,34 @@
 /// An enum type for defining the different logging levels a given message can
 /// be associated with.
 ///
-/// By default, [ERROR] and [WARNING] messages are printed to sterr. [MESSAGE]
+/// By default, [error] and [warning] messages are printed to sterr. [message]
 /// messages are printed to stdout, and others are ignored.
 class Level {
   /// An error occurred and an operation could not be completed.
   ///
   /// Usually shown to the user on stderr.
-  static const ERROR = Level._('ERR ');
+  static const error = Level._('ERR ');
 
   /// Something unexpected happened, but the program was able to continue,
   /// though possibly in a degraded fashion.
-  static const WARNING = Level._('WARN');
+  static const warning = Level._('WARN');
 
   /// A message intended specifically to be shown to the user.
-  static const MESSAGE = Level._('MSG ');
+  static const message = Level._('MSG ');
 
   /// Some interaction with the external world occurred, such as a network
   /// operation, process spawning, or file IO.
-  static const IO = Level._('IO  ');
+  static const io = Level._('IO  ');
 
   /// Incremental output during pub's version constraint solver.
-  static const SOLVER = Level._('SLVR');
+  static const solver = Level._('SLVR');
 
   /// Fine-grained and verbose additional information.
   ///
   /// Used to provide program state context for other logs (such as what pub
   /// was doing when an IO operation occurred) or just more detail for an
   /// operation.
-  static const FINE = Level._('FINE');
+  static const fine = Level._('FINE');
 
   const Level._(this.name);
 
@@ -99,73 +99,73 @@
 /// displayed.
 class Verbosity {
   /// Silence all logging.
-  static const NONE = Verbosity._('none', {
-    Level.ERROR: null,
-    Level.WARNING: null,
-    Level.MESSAGE: null,
-    Level.IO: null,
-    Level.SOLVER: null,
-    Level.FINE: null
+  static const none = Verbosity._('none', {
+    Level.error: null,
+    Level.warning: null,
+    Level.message: null,
+    Level.io: null,
+    Level.solver: null,
+    Level.fine: null
   });
 
   /// Shows only errors.
-  static const ERROR = Verbosity._('error', {
-    Level.ERROR: _logToStderr,
-    Level.WARNING: null,
-    Level.MESSAGE: null,
-    Level.IO: null,
-    Level.SOLVER: null,
-    Level.FINE: null
+  static const error = Verbosity._('error', {
+    Level.error: _logToStderr,
+    Level.warning: null,
+    Level.message: null,
+    Level.io: null,
+    Level.solver: null,
+    Level.fine: null
   });
 
   /// Shows only errors and warnings.
-  static const WARNING = Verbosity._('warning', {
-    Level.ERROR: _logToStderr,
-    Level.WARNING: _logToStderr,
-    Level.MESSAGE: null,
-    Level.IO: null,
-    Level.SOLVER: null,
-    Level.FINE: null
+  static const warning = Verbosity._('warning', {
+    Level.error: _logToStderr,
+    Level.warning: _logToStderr,
+    Level.message: null,
+    Level.io: null,
+    Level.solver: null,
+    Level.fine: null
   });
 
   /// The default verbosity which shows errors, warnings, and messages.
-  static const NORMAL = Verbosity._('normal', {
-    Level.ERROR: _logToStderr,
-    Level.WARNING: _logToStderr,
-    Level.MESSAGE: _logToStdout,
-    Level.IO: null,
-    Level.SOLVER: null,
-    Level.FINE: null
+  static const normal = Verbosity._('normal', {
+    Level.error: _logToStderr,
+    Level.warning: _logToStderr,
+    Level.message: _logToStdout,
+    Level.io: null,
+    Level.solver: null,
+    Level.fine: null
   });
 
   /// Shows errors, warnings, messages, and IO event logs.
-  static const IO = Verbosity._('io', {
-    Level.ERROR: _logToStderrWithLabel,
-    Level.WARNING: _logToStderrWithLabel,
-    Level.MESSAGE: _logToStdoutWithLabel,
-    Level.IO: _logToStderrWithLabel,
-    Level.SOLVER: null,
-    Level.FINE: null
+  static const io = Verbosity._('io', {
+    Level.error: _logToStderrWithLabel,
+    Level.warning: _logToStderrWithLabel,
+    Level.message: _logToStdoutWithLabel,
+    Level.io: _logToStderrWithLabel,
+    Level.solver: null,
+    Level.fine: null
   });
 
   /// Shows errors, warnings, messages, and version solver logs.
-  static const SOLVER = Verbosity._('solver', {
-    Level.ERROR: _logToStderr,
-    Level.WARNING: _logToStderr,
-    Level.MESSAGE: _logToStdout,
-    Level.IO: null,
-    Level.SOLVER: _logToStdout,
-    Level.FINE: null
+  static const solver = Verbosity._('solver', {
+    Level.error: _logToStderr,
+    Level.warning: _logToStderr,
+    Level.message: _logToStdout,
+    Level.io: null,
+    Level.solver: _logToStdout,
+    Level.fine: null
   });
 
   /// Shows all logs.
-  static const ALL = Verbosity._('all', {
-    Level.ERROR: _logToStderrWithLabel,
-    Level.WARNING: _logToStderrWithLabel,
-    Level.MESSAGE: _logToStdoutWithLabel,
-    Level.IO: _logToStderrWithLabel,
-    Level.SOLVER: _logToStderrWithLabel,
-    Level.FINE: _logToStderrWithLabel
+  static const all = Verbosity._('all', {
+    Level.error: _logToStderrWithLabel,
+    Level.warning: _logToStderrWithLabel,
+    Level.message: _logToStdoutWithLabel,
+    Level.io: _logToStderrWithLabel,
+    Level.solver: _logToStderrWithLabel,
+    Level.fine: _logToStderrWithLabel
   });
 
   const Verbosity._(this.name, this._loggers);
@@ -188,7 +188,7 @@
   _Entry(this.level, this.lines);
 }
 
-/// Logs [message] at [Level.ERROR].
+/// Logs [message] at [Level.error].
 ///
 /// If [error] is passed, it's appended to [message]. If [trace] is passed, it's
 /// printed at log level fine.
@@ -198,24 +198,24 @@
     message = message.isEmpty ? '$error' : '$message: $error';
     if (error is Error && trace == null) trace = error.stackTrace;
   }
-  write(Level.ERROR, message);
-  if (trace != null) write(Level.FINE, Chain.forTrace(trace));
+  write(Level.error, message);
+  if (trace != null) write(Level.fine, Chain.forTrace(trace));
 }
 
-/// Logs [message] at [Level.WARNING].
-void warning(message) => write(Level.WARNING, message);
+/// Logs [message] at [Level.warning].
+void warning(message) => write(Level.warning, message);
 
-/// Logs [message] at [Level.MESSAGE].
-void message(message) => write(Level.MESSAGE, message);
+/// Logs [message] at [Level.message].
+void message(message) => write(Level.message, message);
 
-/// Logs [message] at [Level.IO].
-void io(message) => write(Level.IO, message);
+/// Logs [message] at [Level.io].
+void io(message) => write(Level.io, message);
 
-/// Logs [message] at [Level.SOLVER].
-void solver(message) => write(Level.SOLVER, message);
+/// Logs [message] at [Level.solver].
+void solver(message) => write(Level.solver, message);
 
-/// Logs [message] at [Level.FINE].
-void fine(message) => write(Level.FINE, message);
+/// Logs [message] at [Level.fine].
+void fine(message) => write(Level.fine, message);
 
 /// Logs [message] at [level].
 void write(Level level, message) {
@@ -236,7 +236,7 @@
   if (_transcript != null) _transcript!.add(entry);
 }
 
-/// Logs the spawning of an [executable] process with [arguments] at [IO]
+/// Logs the spawning of an [executable] process with [arguments] at [io]
 /// level.
 void process(
     String executable, List<String> arguments, String workingDirectory) {
@@ -315,7 +315,7 @@
 
 /// Enables recording of log entries.
 void recordTranscript() {
-  _transcript = Transcript<_Entry>(_MAX_TRANSCRIPT);
+  _transcript = Transcript<_Entry>(_maxTranscript);
 }
 
 /// If [recordTranscript()] was called, then prints the previously recorded log
@@ -339,8 +339,8 @@
 /// This is useful to not pollute stdout when the output is piped somewhere.
 Future<T> warningsOnlyUnlessTerminal<T>(FutureOr<T> Function() callback) async {
   final oldVerbosity = verbosity;
-  if (verbosity == Verbosity.NORMAL && !stdout.hasTerminal) {
-    verbosity = Verbosity.WARNING;
+  if (verbosity == Verbosity.normal && !stdout.hasTerminal) {
+    verbosity = Verbosity.warning;
   }
   final result = await callback();
   verbosity = oldVerbosity;
@@ -353,7 +353,7 @@
 /// If anything else is logged during this (including another call to
 /// [progress]) that cancels the progress animation, although the total time
 /// will still be printed once it finishes. If [fine] is passed, the progress
-/// information will only be visible at [Level.FINE].
+/// information will only be visible at [Level.fine].
 Future<T> progress<T>(String message, Future<T> Function() callback) {
   _stopProgress();
 
diff --git a/lib/src/null_safety_analysis.dart b/lib/src/null_safety_analysis.dart
index 2ad034d..5b882a8 100644
--- a/lib/src/null_safety_analysis.dart
+++ b/lib/src/null_safety_analysis.dart
@@ -109,7 +109,7 @@
     SolveResult result;
     try {
       result = await resolveVersions(
-        SolveType.GET,
+        SolveType.get,
         _systemCache,
         fakeRoot,
       );
diff --git a/lib/src/package_name.dart b/lib/src/package_name.dart
index 50f4bcc..d83f466 100644
--- a/lib/src/package_name.dart
+++ b/lib/src/package_name.dart
@@ -57,6 +57,10 @@
   }
 
   @override
+  bool operator ==(Object other) =>
+      throw UnimplementedError('Subclass should implement ==');
+
+  @override
   int get hashCode {
     var thisSource = source;
     if (thisSource == null) return name.hashCode;
@@ -104,6 +108,9 @@
 
   @override
   bool operator ==(other) => other is PackageRef && samePackage(other);
+
+  @override
+  int get hashCode => super.hashCode ^ 'PackageRef'.hashCode;
 }
 
 /// A reference to a specific version of a package.
diff --git a/lib/src/progress.dart b/lib/src/progress.dart
index 06ad9e9..b9c6931 100644
--- a/lib/src/progress.dart
+++ b/lib/src/progress.dart
@@ -34,7 +34,7 @@
   Progress(this._message, {bool fine = false}) {
     _stopwatch.start();
 
-    var level = fine ? log.Level.FINE : log.Level.MESSAGE;
+    var level = fine ? log.Level.fine : log.Level.message;
 
     // The animation is only shown when it would be meaningful to a human.
     // That means we're writing a visible message to a TTY at normal log levels
@@ -43,7 +43,7 @@
         !log.verbosity.isLevelVisible(level) ||
         log.json.enabled ||
         fine ||
-        log.verbosity.isLevelVisible(log.Level.FINE)) {
+        log.verbosity.isLevelVisible(log.Level.fine)) {
       // Not animating, so just log the start and wait until the task is
       // completed.
       log.write(level, '$_message...');
diff --git a/lib/src/pub_embeddable_command.dart b/lib/src/pub_embeddable_command.dart
index c1fa863..a46e3f5 100644
--- a/lib/src/pub_embeddable_command.dart
+++ b/lib/src/pub_embeddable_command.dart
@@ -105,7 +105,7 @@
 
   @override
   Verbosity get verbosity =>
-      argResults['verbose'] ? Verbosity.ALL : Verbosity.NORMAL;
+      argResults['verbose'] ? Verbosity.all : Verbosity.normal;
 
   @override
   bool get trace => argResults['verbose'];
diff --git a/lib/src/rate_limited_scheduler.dart b/lib/src/rate_limited_scheduler.dart
index daeb76f..85d73cd 100644
--- a/lib/src/rate_limited_scheduler.dart
+++ b/lib/src/rate_limited_scheduler.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 import 'dart:collection';
 
-import 'package:pedantic/pedantic.dart';
 import 'package:pool/pool.dart';
 
 /// Handles rate-limited scheduling of tasks.
@@ -92,7 +91,9 @@
     // become uncaught.
     //
     // They will still show up for other listeners of the future.
-    await completer.future.catchError((_) {});
+    try {
+      await completer.future;
+    } catch (_) {}
   }
 
   /// Calls [callback] with a function that can pre-schedule jobs.
diff --git a/lib/src/solver/failure.dart b/lib/src/solver/failure.dart
index ba27a3b..60f70c5 100644
--- a/lib/src/solver/failure.dart
+++ b/lib/src/solver/failure.dart
@@ -7,7 +7,6 @@
 import '../exceptions.dart';
 import '../log.dart' as log;
 import '../package_name.dart';
-import '../sdk.dart';
 import '../utils.dart';
 import 'incompatibility.dart';
 import 'incompatibility_cause.dart';
@@ -93,39 +92,20 @@
   String write() {
     var buffer = StringBuffer();
 
-    // SDKs whose version constraints weren't matched.
-    var sdkConstraintCauses = <Sdk>{};
-
-    // SDKs implicated in any way in the solve failure.
-    var sdkCauses = <Sdk>{};
-
-    for (var incompatibility in _root.externalIncompatibilities) {
-      var cause = incompatibility.cause;
-      if (cause is PackageNotFoundCause) {
-        var sdk = cause.sdk;
-        if (sdk != null) {
-          sdkCauses.add(sdk);
-        }
-      } else if (cause is SdkCause) {
-        sdkCauses.add(cause.sdk);
-        sdkConstraintCauses.add(cause.sdk);
-      }
+    // Find all notices from incompatibility causes. This allows an
+    // [IncompatibilityCause] to provide a notice that is printed before the
+    // explanation of the conflict.
+    // Notably, this is used for stating which SDK version is currently
+    // installed, if an SDK is incompatible with a dependency.
+    final notices = _root.externalIncompatibilities
+        .map((c) => c.cause.notice)
+        .whereNotNull()
+        .toSet() // Avoid duplicates
+        .sortedBy((n) => n); // sort for consistency
+    for (final n in notices) {
+      buffer.writeln(n);
     }
-
-    // If the failure was caused in part by unsatisfied SDK constraints,
-    // indicate the actual versions so we don't have to list them (possibly
-    // multiple times) in the main body of the error message.
-    //
-    // Iterate through [sdks] to ensure that SDKs versions are printed in a
-    // consistent order
-    var wroteLine = false;
-    for (var sdk in sdks.values) {
-      if (!sdkConstraintCauses.contains(sdk)) continue;
-      if (!sdk.isAvailable) continue;
-      wroteLine = true;
-      buffer.writeln('The current ${sdk.name} SDK version is ${sdk.version}.');
-    }
-    if (wroteLine) buffer.writeln();
+    if (notices.isNotEmpty) buffer.writeln();
 
     if (_root.cause is ConflictCause) {
       _visit(_root, const {});
@@ -159,15 +139,21 @@
       buffer.writeln(wordWrap(message, prefix: ' ' * (padding + 2)));
     }
 
-    // Iterate through [sdks] to ensure that SDKs versions are printed in a
-    // consistent order
-    for (var sdk in sdks.values) {
-      if (!sdkCauses.contains(sdk)) continue;
-      if (sdk.isAvailable) continue;
-      if (sdk.installMessage == null) continue;
+    // Iterate through all hints, these are intended to be actionable, such as:
+    //  * How to install an SDK, and,
+    //  * How to provide authentication.
+    // Hence, it makes sense to show these at the end of the explanation, as the
+    // user will ideally see these before reading the actual conflict and
+    // understand how to fix the issue.
+    _root.externalIncompatibilities
+        .map((c) => c.cause.hint)
+        .whereNotNull()
+        .toSet() // avoid duplicates
+        .sortedBy((hint) => hint) // sort hints for consistent ordering.
+        .forEach((hint) {
       buffer.writeln();
-      buffer.writeln(sdk.installMessage);
-    }
+      buffer.writeln(hint);
+    });
 
     return buffer.toString();
   }
diff --git a/lib/src/solver/incompatibility_cause.dart b/lib/src/solver/incompatibility_cause.dart
index 53dcfe2..a2a2327 100644
--- a/lib/src/solver/incompatibility_cause.dart
+++ b/lib/src/solver/incompatibility_cause.dart
@@ -10,6 +10,8 @@
 
 /// The reason an [Incompatibility]'s terms are incompatible.
 abstract class IncompatibilityCause {
+  const IncompatibilityCause._();
+
   /// The incompatibility represents the requirement that the root package
   /// exists.
   static const IncompatibilityCause root = _Cause('root');
@@ -27,11 +29,26 @@
 
   /// The incompatibility indicates that the package has an unknown source.
   static const IncompatibilityCause unknownSource = _Cause('unknown source');
+
+  /// Human readable notice / information providing context for this
+  /// incompatibility.
+  ///
+  /// This may be multiple lines, and will be printed before the explanation.
+  /// This is used highlight information that is useful for understanding the
+  /// why this conflict happened.
+  String? get notice => null;
+
+  /// Human readable hint indicating how this incompatibility may be resolved.
+  ///
+  /// This may be multiple lines, and will be printed after the explanation.
+  /// This should only be included if it is actionable and likely to resolve the
+  /// issue for the user.
+  String? get hint => null;
 }
 
 /// The incompatibility was derived from two existing incompatibilities during
 /// conflict resolution.
-class ConflictCause implements IncompatibilityCause {
+class ConflictCause extends IncompatibilityCause {
   /// The incompatibility that was originally found to be in conflict, from
   /// which the target incompatibility was derived.
   final Incompatibility conflict;
@@ -40,14 +57,14 @@
   /// from which the target incompatibility was derived.
   final Incompatibility other;
 
-  ConflictCause(this.conflict, this.other);
+  ConflictCause(this.conflict, this.other) : super._();
 }
 
 /// A class for stateless [IncompatibilityCause]s.
-class _Cause implements IncompatibilityCause {
+class _Cause extends IncompatibilityCause {
   final String _name;
 
-  const _Cause(this._name);
+  const _Cause(this._name) : super._();
 
   @override
   String toString() => _name;
@@ -55,7 +72,7 @@
 
 /// The incompatibility represents a package's SDK constraint being
 /// incompatible with the current SDK.
-class SdkCause implements IncompatibilityCause {
+class SdkCause extends IncompatibilityCause {
   /// The union of all the incompatible versions' constraints on the SDK.
   // TODO(zarah): Investigate if this can be non-nullable
   final VersionConstraint? constraint;
@@ -63,20 +80,41 @@
   /// The SDK with which the package was incompatible.
   final Sdk sdk;
 
-  SdkCause(this.constraint, this.sdk);
+  @override
+  String? get notice {
+    // If the SDK is not available, then we have an actionable [hint] printed
+    // after the explanation. So we don't need to state that the SDK is not
+    // available.
+    if (!sdk.isAvailable) {
+      return null;
+    }
+    // If the SDK is available and we have an incompatibility, then the user has
+    // the wrong SDK version (one that is not compatible with any solution).
+    // Thus, it makes sense to highlight the current SDK version.
+    return 'The current ${sdk.name} SDK version is ${sdk.version}.';
+  }
+
+  @override
+  String? get hint {
+    // If the SDK is available, then installing it won't help
+    if (sdk.isAvailable) {
+      return null;
+    }
+    // Return an install message for the SDK, if there is an install message.
+    return sdk.installMessage;
+  }
+
+  SdkCause(this.constraint, this.sdk) : super._();
 }
 
 /// The incompatibility represents a package that couldn't be found by its
 /// source.
-class PackageNotFoundCause implements IncompatibilityCause {
+class PackageNotFoundCause extends IncompatibilityCause {
   /// The exception indicating why the package couldn't be found.
   final PackageNotFoundException exception;
 
-  /// If the incompatibility was caused by an SDK being unavailable, this is
-  /// that SDK.
-  ///
-  /// Otherwise `null`.
-  Sdk? get sdk => exception.missingSdk;
+  PackageNotFoundCause(this.exception) : super._();
 
-  PackageNotFoundCause(this.exception);
+  @override
+  String? get hint => exception.hint;
 }
diff --git a/lib/src/solver/report.dart b/lib/src/solver/report.dart
index 251c290..3b72cd8 100644
--- a/lib/src/solver/report.dart
+++ b/lib/src/solver/report.dart
@@ -89,7 +89,7 @@
       }
     } else {
       if (numChanged == 0) {
-        if (_type == SolveType.GET) {
+        if (_type == SolveType.get) {
           log.message('Got dependencies$suffix!');
         } else {
           log.message('No dependencies changed$suffix.');
@@ -245,7 +245,7 @@
     String? message;
     // See if there are any newer versions of the package that we were
     // unable to upgrade to.
-    if (newId != null && _type != SolveType.DOWNGRADE) {
+    if (newId != null && _type != SolveType.downgrade) {
       var versions = _result.availableVersions[newId.name]!;
 
       var newerStable = false;
@@ -292,7 +292,7 @@
       }
     }
 
-    if (_type == SolveType.GET &&
+    if (_type == SolveType.get &&
         !(alwaysShow || changed || addedOrRemoved || message != null)) {
       return;
     }
diff --git a/lib/src/solver/result.dart b/lib/src/solver/result.dart
index 692b05f..b8ff0e5 100644
--- a/lib/src/solver/result.dart
+++ b/lib/src/solver/result.dart
@@ -122,7 +122,7 @@
     final report =
         SolveReport(type, _sources, _root, _previousLockFile, this, cache);
     report.summarize(dryRun: dryRun);
-    if (type == SolveType.UPGRADE) {
+    if (type == SolveType.upgrade) {
       await report.reportDiscontinued();
       report.reportOutdated();
     }
diff --git a/lib/src/solver/type.dart b/lib/src/solver/type.dart
index c899e31..28a3230 100644
--- a/lib/src/solver/type.dart
+++ b/lib/src/solver/type.dart
@@ -6,15 +6,15 @@
 class SolveType {
   /// As few changes to the lockfile as possible to be consistent with the
   /// pubspec.
-  static const GET = SolveType._('get');
+  static const get = SolveType._('get');
 
   /// Upgrade all packages or specific packages to the highest versions
   /// possible, regardless of the lockfile.
-  static const UPGRADE = SolveType._('upgrade');
+  static const upgrade = SolveType._('upgrade');
 
   /// Downgrade all packages or specific packages to the lowest versions
   /// possible, regardless of the lockfile.
-  static const DOWNGRADE = SolveType._('downgrade');
+  static const downgrade = SolveType._('downgrade');
 
   final String _name;
 
diff --git a/lib/src/solver/version_solver.dart b/lib/src/solver/version_solver.dart
index 120244a..d4e3a75 100644
--- a/lib/src/solver/version_solver.dart
+++ b/lib/src/solver/version_solver.dart
@@ -485,7 +485,7 @@
           _root.dependencyType(package.name),
           overridden,
           _getAllowedRetracted(ref.name),
-          downgrade: _type == SolveType.DOWNGRADE);
+          downgrade: _type == SolveType.downgrade);
     });
   }
 
@@ -493,7 +493,7 @@
   ///
   /// Returns `null` if it isn't in the lockfile (or has been unlocked).
   PackageId? _getLocked(String? package) {
-    if (_type == SolveType.GET) {
+    if (_type == SolveType.get) {
       if (_unlock.contains(package)) {
         return null;
       }
@@ -503,7 +503,7 @@
     // When downgrading, we don't want to force the latest versions of
     // non-hosted packages, since they don't support multiple versions and thus
     // can't be downgraded.
-    if (_type == SolveType.DOWNGRADE) {
+    if (_type == SolveType.downgrade) {
       var locked = _lockFile.packages[package];
       if (locked != null && !locked.source!.hasMultipleVersions) return locked;
     }
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart
index def4a98..1cb1950 100644
--- a/lib/src/source/hosted.dart
+++ b/lib/src/source/hosted.dart
@@ -10,7 +10,6 @@
     show maxBy, IterableNullableExtension;
 import 'package:http/http.dart' as http;
 import 'package:path/path.dart' as p;
-import 'package:pedantic/pedantic.dart';
 import 'package:pub_semver/pub_semver.dart';
 import 'package:stack_trace/stack_trace.dart';
 
@@ -406,8 +405,8 @@
       body = decoded;
       result = _versionInfoFromPackageListing(body, ref, url);
     } on Exception catch (error, stackTrace) {
-      var parsed = source._asDescription(ref.description);
-      _throwFriendlyError(error, stackTrace, parsed.packageName, parsed.uri);
+      final packageName = source._asDescription(ref.description).packageName;
+      _throwFriendlyError(error, stackTrace, packageName, serverUrl);
     }
 
     // Cache the response on disk.
@@ -824,40 +823,64 @@
     });
   }
 
-  /// When an error occurs trying to read something about [package] from [url],
+  /// When an error occurs trying to read something about [package] from [hostedUrl],
   /// this tries to translate into a more user friendly error message.
   ///
   /// Always throws an error, either the original one or a better one.
   Never _throwFriendlyError(
-    error,
+    Exception error,
     StackTrace stackTrace,
     String package,
-    Uri url,
+    Uri hostedUrl,
   ) {
     if (error is PubHttpException) {
       if (error.response.statusCode == 404) {
         throw PackageNotFoundException(
-            'could not find package $package at $url',
+            'could not find package $package at $hostedUrl',
             innerError: error,
             innerTrace: stackTrace);
       }
 
       fail(
           '${error.response.statusCode} ${error.response.reasonPhrase} trying '
-          'to find package $package at $url.',
+          'to find package $package at $hostedUrl.',
           error,
           stackTrace);
     } else if (error is io.SocketException) {
-      fail('Got socket error trying to find package $package at $url.', error,
-          stackTrace);
+      fail('Got socket error trying to find package $package at $hostedUrl.',
+          error, stackTrace);
     } else if (error is io.TlsException) {
-      fail('Got TLS error trying to find package $package at $url.', error,
-          stackTrace);
+      fail('Got TLS error trying to find package $package at $hostedUrl.',
+          error, stackTrace);
+    } else if (error is AuthenticationException) {
+      String? hint;
+      var message = 'authentication failed';
+
+      assert(error.statusCode == 401 || error.statusCode == 403);
+      if (error.statusCode == 401) {
+        hint = '$hostedUrl package repository requested authentication!\n'
+            'You can provide credentials using:\n'
+            '    pub token add $hostedUrl';
+      }
+      if (error.statusCode == 403) {
+        hint = 'Insufficient permissions to the resource at the $hostedUrl '
+            'package repository.\nYou can modify credentials using:\n'
+            '    pub token add $hostedUrl';
+        message = 'authorization failed';
+      }
+
+      if (error.serverMessage?.isNotEmpty == true && hint != null) {
+        hint += '\n${error.serverMessage}';
+      }
+
+      throw PackageNotFoundException(message, hint: hint);
     } else if (error is FormatException) {
       throw PackageNotFoundException(
-          'Got badly formatted response trying to find package $package at $url',
-          innerError: error,
-          innerTrace: stackTrace);
+        'Got badly formatted response trying to find package $package at $hostedUrl',
+        innerError: error,
+        innerTrace: stackTrace,
+        hint: 'Check that "$hostedUrl" is a valid package repository.',
+      );
     } else {
       // Otherwise re-throw the original exception.
       throw error;
@@ -975,7 +998,9 @@
     // If there are no versions in the cache, report a clearer error.
     if (versions.isEmpty) {
       throw PackageNotFoundException(
-          'could not find package ${ref.name} in cache');
+        'could not find package ${ref.name} in cache',
+        hint: 'Try again without --offline!',
+      );
     }
 
     return versions;
@@ -991,7 +1016,9 @@
   @override
   Future<Pubspec> describeUncached(PackageId id) {
     throw PackageNotFoundException(
-        '${id.name} ${id.version} is not available in your system cache');
+      '${id.name} ${id.version} is not available in cache',
+      hint: 'Try again without --offline!',
+    );
   }
 
   @override
diff --git a/lib/src/source/sdk.dart b/lib/src/source/sdk.dart
index f1dde9e..1458d1b 100644
--- a/lib/src/source/sdk.dart
+++ b/lib/src/source/sdk.dart
@@ -101,8 +101,10 @@
     if (sdk == null) {
       throw PackageNotFoundException('unknown SDK "$identifier"');
     } else if (!sdk.isAvailable) {
-      throw PackageNotFoundException('the ${sdk.name} SDK is not available',
-          missingSdk: sdk);
+      throw PackageNotFoundException(
+        'the ${sdk.name} SDK is not available',
+        hint: sdk.installMessage,
+      );
     }
 
     var path = sdk.packagePath(package.name);
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 39439e9..2a5768e 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -375,7 +375,7 @@
 
   // If we're using verbose logging, be more verbose but more accurate when
   // reporting timing information.
-  var msString = log.verbosity.isLevelVisible(log.Level.FINE)
+  var msString = log.verbosity.isLevelVisible(log.Level.fine)
       ? _padLeft(ms.toString(), 3, '0')
       : (ms ~/ 100).toString();
 
diff --git a/lib/src/validator.dart b/lib/src/validator.dart
index 29392fa..1b07560 100644
--- a/lib/src/validator.dart
+++ b/lib/src/validator.dart
@@ -101,7 +101,7 @@
         'Make sure your SDK constraint excludes old versions:\n'
         '\n'
         'environment:\n'
-        '  sdk: \"$newSdkConstraint\"');
+        '  sdk: "$newSdkConstraint"');
   }
 
   /// Returns whether [version1] and [version2] are pre-releases of the same version.
diff --git a/lib/src/validator/gitignore.dart b/lib/src/validator/gitignore.dart
index 7770b57..78bf9aa 100644
--- a/lib/src/validator/gitignore.dart
+++ b/lib/src/validator/gitignore.dart
@@ -46,8 +46,10 @@
         beneath: beneath,
         listDir: (dir) {
           var contents = Directory(resolve(dir)).listSync();
-          return contents.map((entity) =>
-              p.posix.joinAll(p.split(p.relative(entity.path, from: root))));
+          return contents
+              .where((e) => !(linkExists(e.path) && dirExists(e.path)))
+              .map((entity) => p.posix
+                  .joinAll(p.split(p.relative(entity.path, from: root))));
         },
         ignoreForDir: (dir) {
           final gitIgnore = resolve('$dir/.gitignore');
diff --git a/lib/src/validator/sdk_constraint.dart b/lib/src/validator/sdk_constraint.dart
index 063ad7e..ff25e53 100644
--- a/lib/src/validator/sdk_constraint.dart
+++ b/lib/src/validator/sdk_constraint.dart
@@ -50,7 +50,7 @@
             'Expand it manually instead:\n'
             '\n'
             'environment:\n'
-            '  sdk: \"$dartConstraintWithoutCaret\"');
+            '  sdk: "$dartConstraintWithoutCaret"');
       }
 
       if (dartConstraint.max == null) {
diff --git a/lib/src/validator/size.dart b/lib/src/validator/size.dart
index 8f258a9..e989518 100644
--- a/lib/src/validator/size.dart
+++ b/lib/src/validator/size.dart
@@ -10,7 +10,7 @@
 import '../validator.dart';
 
 /// The maximum size of the package to upload (100 MB).
-const _MAX_SIZE = 100 * 1024 * 1024;
+const _maxSize = 100 * 1024 * 1024;
 
 /// A validator that validates that a package isn't too big.
 class SizeValidator extends Validator {
@@ -21,7 +21,7 @@
   @override
   Future validate() {
     return packageSize.then((size) {
-      if (size <= _MAX_SIZE) return;
+      if (size <= _maxSize) return;
       var sizeInMb = (size / math.pow(2, 20)).toStringAsPrecision(4);
       // Current implementation of Package.listFiles skips hidden files
       var ignoreExists = fileExists(entrypoint.root.path('.gitignore'));
diff --git a/pubspec.yaml b/pubspec.yaml
index 8c76708..a7d9bb4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -18,7 +18,6 @@
   meta: ^1.3.0
   oauth2: ^2.0.0
   path: ^1.8.0
-  pedantic: ^1.11.0
   pool: ^1.5.0
   pub_semver: ^2.1.0
   shelf: ^1.1.1
@@ -29,6 +28,7 @@
   yaml_edit: ^2.0.0
 
 dev_dependencies:
+  lints: ^1.0.1
   shelf_test_handler: ^2.0.0
   test: ^1.17.3
   test_descriptor: ^2.0.0
diff --git a/test/add/common/add_test.dart b/test/add/common/add_test.dart
index 51d5b71..69f33fe 100644
--- a/test/add/common/add_test.dart
+++ b/test/add/common/add_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io' show File;
 
 import 'package:path/path.dart' as p;
@@ -15,7 +13,7 @@
 
 void main() {
   test('URL encodes the package name', () async {
-    await serveNoPackages();
+    await servePackages();
 
     await d.appDir({}).create();
 
@@ -40,9 +38,8 @@
 
   group('normally', () {
     test('fails if extra arguments are passed', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.2');
-      });
+      final server = await servePackages();
+      server.serve('foo', '1.2.2');
 
       await d.dir(appPath, [
         d.pubspec({'name': 'myapp'})
@@ -64,7 +61,8 @@
     });
 
     test('adds a package from a pub server', () async {
-      await servePackages((builder) => builder.serve('foo', '1.2.3'));
+      final server = await servePackages();
+      server.serve('foo', '1.2.3');
 
       await d.appDir({}).create();
 
@@ -78,10 +76,9 @@
     test(
         'does not remove empty dev_dependencies while adding to normal dependencies',
         () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3');
-        builder.serve('foo', '1.2.2');
-      });
+      await servePackages()
+        ..serve('foo', '1.2.3')
+        ..serve('foo', '1.2.2');
 
       await d.dir(appPath, [
         d.file('pubspec.yaml', '''
@@ -111,7 +108,8 @@
 
     test('dry run does not actually add the package or modify the pubspec',
         () async {
-      await servePackages((builder) => builder.serve('foo', '1.2.3'));
+      final server = await servePackages();
+      server.serve('foo', '1.2.3');
 
       await d.appDir({}).create();
 
@@ -133,7 +131,8 @@
     test(
         'adds a package from a pub server even when dependencies key does not exist',
         () async {
-      await servePackages((builder) => builder.serve('foo', '1.2.3'));
+      final server = await servePackages();
+      server.serve('foo', '1.2.3');
 
       await d.dir(appPath, [
         d.pubspec({'name': 'myapp'})
@@ -148,10 +147,9 @@
 
     group('warns user to use pub upgrade if package exists', () {
       test('if package is added without a version constraint', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-          builder.serve('foo', '1.2.2');
-        });
+        await servePackages()
+          ..serve('foo', '1.2.3')
+          ..serve('foo', '1.2.2');
 
         await d.appDir({'foo': '1.2.2'}).create();
 
@@ -166,10 +164,9 @@
       });
 
       test('if package is added with a specific version constraint', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-          builder.serve('foo', '1.2.2');
-        });
+        await servePackages()
+          ..serve('foo', '1.2.3')
+          ..serve('foo', '1.2.2');
 
         await d.appDir({'foo': '1.2.2'}).create();
 
@@ -184,10 +181,9 @@
       });
 
       test('if package is added with a version constraint range', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-          builder.serve('foo', '1.2.2');
-        });
+        await servePackages()
+          ..serve('foo', '1.2.3')
+          ..serve('foo', '1.2.2');
 
         await d.appDir({'foo': '1.2.2'}).create();
 
@@ -203,10 +199,9 @@
     });
 
     test('removes dev_dependency and add to normal dependency', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3');
-        builder.serve('foo', '1.2.2');
-      });
+      await servePackages()
+        ..serve('foo', '1.2.3')
+        ..serve('foo', '1.2.2');
 
       await d.dir(appPath, [
         d.file('pubspec.yaml', '''
@@ -239,10 +234,9 @@
 
     group('dependency override', () {
       test('passes if package does not specify a range', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-          builder.serve('foo', '1.2.2');
-        });
+        await servePackages()
+          ..serve('foo', '1.2.3')
+          ..serve('foo', '1.2.2');
 
         await d.dir(appPath, [
           d.pubspec({
@@ -266,9 +260,8 @@
       });
 
       test('passes if constraint matches git dependency override', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-        });
+        final server = await servePackages();
+        server.serve('foo', '1.2.3');
 
         await d.git('foo.git',
             [d.libDir('foo'), d.libPubspec('foo', '1.2.3')]).create();
@@ -297,9 +290,8 @@
       });
 
       test('passes if constraint matches path dependency override', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.2');
-        });
+        final server = await servePackages();
+        server.serve('foo', '1.2.2');
         await d.dir(
             'foo', [d.libDir('foo'), d.libPubspec('foo', '1.2.2')]).create();
 
@@ -327,9 +319,8 @@
       });
 
       test('fails with bad version constraint', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-        });
+        final server = await servePackages();
+        server.serve('foo', '1.2.3');
 
         await d.dir(appPath, [
           d.pubspec({'name': 'myapp', 'dependencies': {}})
@@ -350,10 +341,9 @@
       });
 
       test('fails if constraint does not match override', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-          builder.serve('foo', '1.2.2');
-        });
+        await servePackages()
+          ..serve('foo', '1.2.3')
+          ..serve('foo', '1.2.2');
 
         await d.dir(appPath, [
           d.pubspec({
@@ -383,9 +373,8 @@
       });
 
       test('fails if constraint matches git dependency override', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-        });
+        final server = await servePackages();
+        server.serve('foo', '1.2.3');
 
         await d.git('foo.git',
             [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
@@ -423,9 +412,8 @@
 
       test('fails if constraint does not match path dependency override',
           () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.2');
-        });
+        final server = await servePackages();
+        server.serve('foo', '1.2.2');
         await d.dir(
             'foo', [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
 
@@ -464,7 +452,8 @@
 
   group('--dev', () {
     test('--dev adds packages to dev_dependencies instead', () async {
-      await servePackages((builder) => builder.serve('foo', '1.2.3'));
+      final server = await servePackages();
+      server.serve('foo', '1.2.3');
 
       await d.dir(appPath, [
         d.pubspec({'name': 'myapp', 'dev_dependencies': {}})
@@ -484,10 +473,9 @@
 
     group('warns user to use pub upgrade if package exists', () {
       test('if package is added without a version constraint', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-          builder.serve('foo', '1.2.2');
-        });
+        await servePackages()
+          ..serve('foo', '1.2.3')
+          ..serve('foo', '1.2.2');
 
         await d.dir(appPath, [
           d.pubspec({
@@ -512,10 +500,9 @@
       });
 
       test('if package is added with a specific version constraint', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-          builder.serve('foo', '1.2.2');
-        });
+        await servePackages()
+          ..serve('foo', '1.2.3')
+          ..serve('foo', '1.2.2');
 
         await d.dir(appPath, [
           d.pubspec({
@@ -540,10 +527,9 @@
       });
 
       test('if package is added with a version constraint range', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-          builder.serve('foo', '1.2.2');
-        });
+        await servePackages()
+          ..serve('foo', '1.2.3')
+          ..serve('foo', '1.2.2');
 
         await d.dir(appPath, [
           d.pubspec({
@@ -570,10 +556,9 @@
 
     group('dependency override', () {
       test('passes if package does not specify a range', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-          builder.serve('foo', '1.2.2');
-        });
+        await servePackages()
+          ..serve('foo', '1.2.3')
+          ..serve('foo', '1.2.2');
 
         await d.dir(appPath, [
           d.pubspec({
@@ -597,10 +582,8 @@
       });
 
       test('passes if constraint is git dependency', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-        });
-
+        final server = await servePackages();
+        server.serve('foo', '1.2.3');
         await d.git('foo.git',
             [d.libDir('foo'), d.libPubspec('foo', '1.2.3')]).create();
 
@@ -628,9 +611,8 @@
       });
 
       test('passes if constraint matches path dependency override', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.2');
-        });
+        final server = await servePackages();
+        server.serve('foo', '1.2.2');
         await d.dir(
             'foo', [d.libDir('foo'), d.libPubspec('foo', '1.2.2')]).create();
 
@@ -658,10 +640,9 @@
       });
 
       test('fails if constraint does not match override', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-          builder.serve('foo', '1.2.2');
-        });
+        await servePackages()
+          ..serve('foo', '1.2.3')
+          ..serve('foo', '1.2.2');
 
         await d.dir(appPath, [
           d.pubspec({
@@ -691,9 +672,8 @@
       });
 
       test('fails if constraint matches git dependency override', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3');
-        });
+        final server = await servePackages();
+        server.serve('foo', '1.2.3');
 
         await d.git('foo.git',
             [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
@@ -731,9 +711,9 @@
 
       test('fails if constraint does not match path dependency override',
           () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.2');
-        });
+        final server = await servePackages();
+        server.serve('foo', '1.2.2');
+
         await d.dir(
             'foo', [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
 
@@ -772,10 +752,9 @@
     test(
         'prints information saying that package is already a dependency if it '
         'already exists and exits with a usage exception', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3');
-        builder.serve('foo', '1.2.2');
-      });
+      await servePackages()
+        ..serve('foo', '1.2.3')
+        ..serve('foo', '1.2.2');
 
       await d.dir(appPath, [
         d.pubspec({
@@ -807,9 +786,8 @@
 
   /// Differs from the previous test because this tests YAML in flow format.
   test('adds to empty ', () async {
-    await servePackages((builder) {
-      builder.serve('bar', '1.0.0');
-    });
+    final server = await servePackages();
+    server.serve('bar', '1.0.0');
 
     await d.dir(appPath, [
       d.file('pubspec.yaml', '''
@@ -827,10 +805,9 @@
   });
 
   test('preserves comments', () async {
-    await servePackages((builder) {
-      builder.serve('bar', '1.0.0');
-      builder.serve('foo', '1.0.0');
-    });
+    await servePackages()
+      ..serve('bar', '1.0.0')
+      ..serve('foo', '1.0.0');
 
     await d.dir(appPath, [
       d.file('pubspec.yaml', '''
diff --git a/test/add/common/invalid_options.dart b/test/add/common/invalid_options.dart
index 17262d2..f5bf23d 100644
--- a/test/add/common/invalid_options.dart
+++ b/test/add/common/invalid_options.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -41,12 +39,10 @@
   test('cannot use both --path and --host-<option> flags', () async {
     // Make the default server serve errors. Only the custom server should
     // be accessed.
-    await serveNoPackages();
-    globalPackageServer.serveErrors();
+    (await servePackages()).serveErrors();
 
-    final server = await PackageServer.start((builder) {
-      builder.serve('foo', '1.2.3');
-    });
+    final server = await startPackageServer();
+    server.serve('foo', '1.2.3');
 
     await d
         .dir('bar', [d.libDir('bar'), d.libPubspec('foo', '0.0.1')]).create();
@@ -78,12 +74,10 @@
   test('cannot use both --hosted-url and --git-<option> flags', () async {
     // Make the default server serve errors. Only the custom server should
     // be accessed.
-    await serveNoPackages();
-    globalPackageServer.serveErrors();
+    (await servePackages()).serveErrors();
 
-    final server = await PackageServer.start((builder) {
-      builder.serve('foo', '1.2.3');
-    });
+    final server = await startPackageServer();
+    server.serve('foo', '1.2.3');
 
     ensureGit();
 
diff --git a/test/add/common/version_constraint_test.dart b/test/add/common/version_constraint_test.dart
index 22df8bc..546642f 100644
--- a/test/add/common/version_constraint_test.dart
+++ b/test/add/common/version_constraint_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -12,13 +10,12 @@
 
 void main() {
   test('allows empty version constraint', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '0.2.3');
-      builder.serve('foo', '1.0.1');
-      builder.serve('foo', '1.2.3');
-      builder.serve('foo', '2.0.0-dev');
-      builder.serve('foo', '1.3.4-dev');
-    });
+    await servePackages()
+      ..serve('foo', '0.2.3')
+      ..serve('foo', '1.0.1')
+      ..serve('foo', '1.2.3')
+      ..serve('foo', '2.0.0-dev')
+      ..serve('foo', '1.3.4-dev');
 
     await d.appDir({}).create();
 
@@ -30,7 +27,8 @@
   });
 
   test('allows specific version constraint', () async {
-    await servePackages((builder) => builder.serve('foo', '1.2.3'));
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
 
     await d.appDir({}).create();
 
@@ -42,7 +40,8 @@
   });
 
   test('allows specific pre-release version constraint', () async {
-    await servePackages((builder) => builder.serve('foo', '1.2.3-dev'));
+    final server = await servePackages();
+    server.serve('foo', '1.2.3-dev');
 
     await d.appDir({}).create();
 
@@ -54,13 +53,12 @@
   });
 
   test('allows the "any" version constraint', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '0.2.3');
-      builder.serve('foo', '1.0.1');
-      builder.serve('foo', '1.2.3');
-      builder.serve('foo', '2.0.0-dev');
-      builder.serve('foo', '1.3.4-dev');
-    });
+    await servePackages()
+      ..serve('foo', '0.2.3')
+      ..serve('foo', '1.0.1')
+      ..serve('foo', '1.2.3')
+      ..serve('foo', '2.0.0-dev')
+      ..serve('foo', '1.3.4-dev');
 
     await d.appDir({}).create();
 
@@ -72,7 +70,8 @@
   });
 
   test('allows version constraint range', () async {
-    await servePackages((builder) => builder.serve('foo', '1.2.3'));
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
 
     await d.appDir({}).create();
 
@@ -86,12 +85,11 @@
   test(
       'empty constraint allows it to choose the latest version not in conflict',
       () async {
-    await servePackages((builder) {
-      builder.serve('foo', '0.1.0');
-      builder.serve('foo', '1.2.3', deps: {'bar': '2.0.4'});
-      builder.serve('bar', '2.0.3');
-      builder.serve('bar', '2.0.4');
-    });
+    await servePackages()
+      ..serve('foo', '0.1.0')
+      ..serve('foo', '1.2.3', deps: {'bar': '2.0.4'})
+      ..serve('bar', '2.0.3')
+      ..serve('bar', '2.0.4');
 
     await d.appDir({'bar': '2.0.3'}).create();
 
@@ -105,7 +103,8 @@
 
   group('does not update pubspec if no available version found', () {
     test('simple', () async {
-      await servePackages((builder) => builder.serve('foo', '1.0.3'));
+      final server = await servePackages();
+      server.serve('foo', '1.0.3');
 
       await d.appDir({}).create();
 
@@ -126,11 +125,10 @@
     });
 
     test('transitive', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3', deps: {'bar': '2.0.4'});
-        builder.serve('bar', '2.0.3');
-        builder.serve('bar', '2.0.4');
-      });
+      await servePackages()
+        ..serve('foo', '1.2.3', deps: {'bar': '2.0.4'})
+        ..serve('bar', '2.0.3')
+        ..serve('bar', '2.0.4');
 
       await d.appDir({'bar': '2.0.3'}).create();
 
diff --git a/test/add/common/version_resolution_test.dart b/test/add/common/version_resolution_test.dart
index a6ad690..64b393a 100644
--- a/test/add/common/version_resolution_test.dart
+++ b/test/add/common/version_resolution_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -15,10 +13,10 @@
   test('unlocks transitive dependencies', () async {
     /// The server used to only have the foo v3.2.1 as the latest,
     /// so pub get will create a pubspec.lock to foo 3.2.1
-    await servePackages((builder) {
-      builder.serve('foo', '3.2.1');
-      builder.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
-    });
+    final server = await servePackages();
+
+    server.serve('foo', '3.2.1');
+    server.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
 
     await d.appDir({'bar': '1.0.0'}).create();
     await pubGet();
@@ -26,11 +24,9 @@
     /// foo's package creator releases a newer version of foo, and we
     /// want to test that this is what the user gets when they run
     /// pub add foo.
-    globalPackageServer.add((builder) {
-      builder.serve('foo', '3.5.0');
-      builder.serve('foo', '3.1.0');
-      builder.serve('foo', '2.5.0');
-    });
+    server.serve('foo', '3.5.0');
+    server.serve('foo', '3.1.0');
+    server.serve('foo', '2.5.0');
 
     await pubAdd(args: ['foo']);
 
@@ -43,18 +39,16 @@
       () async {
     /// The server used to only have the foo v3.2.1 as the latest,
     /// so pub get will create a pubspec.lock to foo 3.2.1
-    await servePackages((builder) {
-      builder.serve('foo', '3.2.1');
-      builder.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
-    });
+    final server = await servePackages();
+
+    server.serve('foo', '3.2.1');
+    server.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
 
     await d.appDir({'bar': '1.0.0'}).create();
     await pubGet();
 
-    globalPackageServer.add((builder) {
-      builder.serve('foo', '4.0.0');
-      builder.serve('foo', '2.0.0');
-    });
+    server.serve('foo', '4.0.0');
+    server.serve('foo', '2.0.0');
 
     await pubAdd(args: ['foo']);
 
@@ -67,20 +61,18 @@
       () async {
     /// The server used to only have the foo v3.2.1 as the latest,
     /// so pub get will create a pubspec.lock to foo 3.2.1
-    await servePackages((builder) {
-      builder.serve('foo', '3.2.1');
-      builder.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
-    });
+    final server = await servePackages();
+
+    server.serve('foo', '3.2.1');
+    server.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
 
     await d.appDir({'bar': '^1.0.0'}).create();
     await pubGet();
 
-    globalPackageServer.add((builder) {
-      builder.serve('foo', '5.0.0');
-      builder.serve('foo', '4.0.0');
-      builder.serve('foo', '2.0.0');
-      builder.serve('bar', '1.5.0', deps: {'foo': '^4.0.0'});
-    });
+    server.serve('foo', '5.0.0');
+    server.serve('foo', '4.0.0');
+    server.serve('foo', '2.0.0');
+    server.serve('bar', '1.5.0', deps: {'foo': '^4.0.0'});
 
     await pubAdd(args: ['foo']);
 
diff --git a/test/add/git/git_test.dart b/test/add/git/git_test.dart
index b120e38..7bc51f0 100644
--- a/test/add/git/git_test.dart
+++ b/test/add/git/git_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -158,9 +156,8 @@
   });
 
   test('can be overriden by dependency override', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.2');
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.2.2');
 
     await d.git(
         'foo.git', [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
diff --git a/test/add/git/ref_test.dart b/test/add/git/ref_test.dart
index fadd80a..11dfc0b 100644
--- a/test/add/git/ref_test.dart
+++ b/test/add/git/ref_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/add/git/subdir_test.dart b/test/add/git/subdir_test.dart
index 3bf381a..0f78069 100644
--- a/test/add/git/subdir_test.dart
+++ b/test/add/git/subdir_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/add/hosted/non_default_pub_server_test.dart b/test/add/hosted/non_default_pub_server_test.dart
index 33b6753..eea6c09 100644
--- a/test/add/hosted/non_default_pub_server_test.dart
+++ b/test/add/hosted/non_default_pub_server_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -14,13 +12,12 @@
   test('adds a package from a non-default pub server', () async {
     // Make the default server serve errors. Only the custom server should
     // be accessed.
-    await serveErrors();
+    (await servePackages()).serveErrors();
 
-    var server = await PackageServer.start((builder) {
-      builder.serve('foo', '0.2.5');
-      builder.serve('foo', '1.1.0');
-      builder.serve('foo', '1.2.3');
-    });
+    final server = await servePackages();
+    server.serve('foo', '0.2.5');
+    server.serve('foo', '1.1.0');
+    server.serve('foo', '1.2.3');
 
     await d.appDir({}).create();
 
@@ -66,13 +63,12 @@
       () async {
     // Make the default server serve errors. Only the custom server should
     // be accessed.
-    await serveErrors();
+    (await servePackages()).serveErrors();
 
-    var server = await PackageServer.start((builder) {
-      builder.serve('foo', '0.2.5');
-      builder.serve('foo', '1.1.0');
-      builder.serve('foo', '1.2.3');
-    });
+    final server = await servePackages();
+    server.serve('foo', '0.2.5');
+    server.serve('foo', '1.1.0');
+    server.serve('foo', '1.2.3');
 
     await d.appDir({}).create();
 
@@ -94,13 +90,12 @@
       () async {
     // Make the default server serve errors. Only the custom server should
     // be accessed.
-    await serveErrors();
+    (await servePackages()).serveErrors();
 
-    var server = await PackageServer.start((builder) {
-      builder.serve('foo', '0.2.5');
-      builder.serve('foo', '1.1.0');
-      builder.serve('foo', '1.2.3');
-    });
+    final server = await servePackages();
+    server.serve('foo', '0.2.5');
+    server.serve('foo', '1.1.0');
+    server.serve('foo', '1.2.3');
 
     await d.appDir({}).create();
 
@@ -123,13 +118,11 @@
       'constraint', () async {
     // Make the default server serve errors. Only the custom server should
     // be accessed.
-    await serveErrors();
-
-    var server = await PackageServer.start((builder) {
-      builder.serve('foo', '0.2.5');
-      builder.serve('foo', '1.1.0');
-      builder.serve('foo', '1.2.3');
-    });
+    (await servePackages()).serveErrors();
+    final server = await servePackages();
+    server.serve('foo', '0.2.5');
+    server.serve('foo', '1.1.0');
+    server.serve('foo', '1.2.3');
 
     await d.appDir({}).create();
 
diff --git a/test/add/path/absolute_path_test.dart b/test/add/path/absolute_path_test.dart
index dc74638..5b7e726 100644
--- a/test/add/path/absolute_path_test.dart
+++ b/test/add/path/absolute_path_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
@@ -90,9 +88,8 @@
   });
 
   test('can be overriden by dependency override', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.2');
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.2.2');
     await d
         .dir('foo', [d.libDir('foo'), d.libPubspec('foo', '0.0.1')]).create();
 
diff --git a/test/add/path/relative_path_test.dart b/test/add/path/relative_path_test.dart
index 9d443e8..c02b644 100644
--- a/test/add/path/relative_path_test.dart
+++ b/test/add/path/relative_path_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io' show Platform;
 
 import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -104,9 +102,8 @@
   });
 
   test('can be overriden by dependency override', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.2');
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.2.2');
     await d
         .dir('foo', [d.libDir('foo'), d.libPubspec('foo', '0.0.1')]).create();
 
diff --git a/test/add/sdk/sdk_test.dart b/test/add/sdk/sdk_test.dart
index 1ded16e..632725e 100644
--- a/test/add/sdk/sdk_test.dart
+++ b/test/add/sdk/sdk_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
@@ -13,9 +11,8 @@
 
 void main() {
   setUp(() async {
-    await servePackages((builder) {
-      builder.serve('bar', '1.0.0');
-    });
+    final server = await servePackages();
+    server.serve('bar', '1.0.0');
 
     await d.dir('flutter', [
       d.dir('packages', [
diff --git a/test/cache/add/adds_latest_matching_version_test.dart b/test/cache/add/adds_latest_matching_version_test.dart
index d7e26c4..7bf9625 100644
--- a/test/cache/add/adds_latest_matching_version_test.dart
+++ b/test/cache/add/adds_latest_matching_version_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:test/test.dart';
@@ -15,12 +13,11 @@
   test(
       'adds the latest version of the package matching the '
       'version constraint', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.2');
-      builder.serve('foo', '1.2.3');
-      builder.serve('foo', '2.0.0-dev');
-      builder.serve('foo', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.2.2')
+      ..serve('foo', '1.2.3')
+      ..serve('foo', '2.0.0-dev')
+      ..serve('foo', '2.0.0');
 
     await runPub(
         args: ['cache', 'add', 'foo', '-v', '>=1.0.0 <2.0.0'],
diff --git a/test/cache/add/adds_latest_version_test.dart b/test/cache/add/adds_latest_version_test.dart
index 6a8b795..cf34857 100644
--- a/test/cache/add/adds_latest_version_test.dart
+++ b/test/cache/add/adds_latest_version_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
 
 void main() {
   test('adds the latest stable version of the package', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.2');
-      builder.serve('foo', '1.2.3');
-      builder.serve('foo', '1.2.4-dev');
-    });
+    await servePackages()
+      ..serve('foo', '1.2.2')
+      ..serve('foo', '1.2.3')
+      ..serve('foo', '1.2.4-dev');
 
     await runPub(
         args: ['cache', 'add', 'foo'], output: 'Downloading foo 1.2.3...');
diff --git a/test/cache/add/all_adds_all_matching_versions_test.dart b/test/cache/add/all_adds_all_matching_versions_test.dart
index bfffa7f..a05e8dc 100644
--- a/test/cache/add/all_adds_all_matching_versions_test.dart
+++ b/test/cache/add/all_adds_all_matching_versions_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,12 +9,11 @@
 
 void main() {
   test('"--all" adds all matching versions of the package', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.2');
-      builder.serve('foo', '1.2.3-dev');
-      builder.serve('foo', '1.2.3');
-      builder.serve('foo', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.2.2')
+      ..serve('foo', '1.2.3-dev')
+      ..serve('foo', '1.2.3')
+      ..serve('foo', '2.0.0');
 
     await runPub(
         args: ['cache', 'add', 'foo', '-v', '>=1.0.0 <2.0.0', '--all'],
diff --git a/test/cache/add/all_with_some_versions_present_test.dart b/test/cache/add/all_with_some_versions_present_test.dart
index da4da98..7b5b36d 100644
--- a/test/cache/add/all_with_some_versions_present_test.dart
+++ b/test/cache/add/all_with_some_versions_present_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,12 +9,11 @@
 
 void main() {
   test('"--all" adds all non-installed versions of the package', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.1');
-      builder.serve('foo', '1.2.2');
-      builder.serve('foo', '1.2.3');
-      builder.serve('foo', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.2.1')
+      ..serve('foo', '1.2.2')
+      ..serve('foo', '1.2.3')
+      ..serve('foo', '2.0.0');
 
     // Install a couple of versions first.
     await runPub(
diff --git a/test/cache/add/already_cached_test.dart b/test/cache/add/already_cached_test.dart
index 9bf8df3..8c74da9 100644
--- a/test/cache/add/already_cached_test.dart
+++ b/test/cache/add/already_cached_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,9 +9,8 @@
 
 void main() {
   test('does nothing if the package is already cached', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.3');
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
 
     // Run once to put it in the cache.
     await runPub(
diff --git a/test/cache/add/bad_version_test.dart b/test/cache/add/bad_version_test.dart
index 8d5d2e1..4e93331 100644
--- a/test/cache/add/bad_version_test.dart
+++ b/test/cache/add/bad_version_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/cache/add/missing_package_arg_test.dart b/test/cache/add/missing_package_arg_test.dart
index 426b0d8..456342b 100644
--- a/test/cache/add/missing_package_arg_test.dart
+++ b/test/cache/add/missing_package_arg_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/cache/add/no_matching_version_test.dart b/test/cache/add/no_matching_version_test.dart
index d395f29..a860294 100644
--- a/test/cache/add/no_matching_version_test.dart
+++ b/test/cache/add/no_matching_version_test.dart
@@ -2,18 +2,15 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../test_pub.dart';
 
 void main() {
   test('fails if no version matches the version constraint', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.2');
-      builder.serve('foo', '1.2.3');
-    });
+    await servePackages()
+      ..serve('foo', '1.2.2')
+      ..serve('foo', '1.2.3');
 
     await runPub(
         args: ['cache', 'add', 'foo', '-v', '>2.0.0'],
diff --git a/test/cache/add/package_not_found_test.dart b/test/cache/add/package_not_found_test.dart
index 4179319..caf45f4 100644
--- a/test/cache/add/package_not_found_test.dart
+++ b/test/cache/add/package_not_found_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -11,12 +9,13 @@
 
 void main() {
   test('fails if the package cound not be found on the source', () async {
-    await serveNoPackages();
+    await servePackages();
 
     await runPub(
         args: ['cache', 'add', 'foo'],
-        error: RegExp(r"Package doesn't exist \(could not find package foo at "
-            r'http://.*\)\.'),
+        error: RegExp(
+          r'Package not available \(could not find package foo at http://.*\)\.',
+        ),
         exitCode: exit_codes.UNAVAILABLE);
   });
 }
diff --git a/test/cache/add/unexpected_arguments_test.dart b/test/cache/add/unexpected_arguments_test.dart
index 7ec0f30..1e4fa54 100644
--- a/test/cache/add/unexpected_arguments_test.dart
+++ b/test/cache/add/unexpected_arguments_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/cache/clean_test.dart b/test/cache/clean_test.dart
index 1ba2ac7..7a79bc8 100644
--- a/test/cache/clean_test.dart
+++ b/test/cache/clean_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -19,9 +17,9 @@
   });
 
   test('running pub cache clean --force deletes cache', () async {
-    await servePackages((b) => b
+    await servePackages()
       ..serve('foo', '1.1.2')
-      ..serve('bar', '1.2.3'));
+      ..serve('bar', '1.2.3');
     await d.appDir({'foo': 'any', 'bar': 'any'}).create();
     await pubGet();
     final cache = path.join(d.sandbox, cachePath);
@@ -34,9 +32,9 @@
 
   test('running pub cache clean deletes cache only with confirmation',
       () async {
-    await servePackages((b) => b
+    await servePackages()
       ..serve('foo', '1.1.2')
-      ..serve('bar', '1.2.3'));
+      ..serve('bar', '1.2.3');
     await d.appDir({'foo': 'any', 'bar': 'any'}).create();
     await pubGet();
     final cache = path.join(d.sandbox, cachePath);
diff --git a/test/cache/list_test.dart b/test/cache/list_test.dart
index 9d8b9f3..a2c26a4 100644
--- a/test/cache/list_test.dart
+++ b/test/cache/list_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
diff --git a/test/cache/repair/empty_cache_test.dart b/test/cache/repair/empty_cache_test.dart
index 679e32a..13d68cc 100644
--- a/test/cache/repair/empty_cache_test.dart
+++ b/test/cache/repair/empty_cache_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../test_pub.dart';
diff --git a/test/cache/repair/git_test.dart b/test/cache/repair/git_test.dart
index abb0ab7..262343a 100644
--- a/test/cache/repair/git_test.dart
+++ b/test/cache/repair/git_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:pub/src/io.dart';
diff --git a/test/cache/repair/handles_corrupted_binstub_test.dart b/test/cache/repair/handles_corrupted_binstub_test.dart
index b1c3556..0ca169f 100644
--- a/test/cache/repair/handles_corrupted_binstub_test.dart
+++ b/test/cache/repair/handles_corrupted_binstub_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
 
 void main() {
   test('handles a corrupted binstub script', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/cache/repair/handles_corrupted_global_lockfile_test.dart b/test/cache/repair/handles_corrupted_global_lockfile_test.dart
index 3952871..9a9af05 100644
--- a/test/cache/repair/handles_corrupted_global_lockfile_test.dart
+++ b/test/cache/repair/handles_corrupted_global_lockfile_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/cache/repair/handles_failure_test.dart b/test/cache/repair/handles_failure_test.dart
index 8016d30..d5637ca 100644
--- a/test/cache/repair/handles_failure_test.dart
+++ b/test/cache/repair/handles_failure_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -13,15 +11,14 @@
 void main() {
   test('handles failure to reinstall some packages', () async {
     // Only serve two packages so repairing will have a failure.
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.3');
-      builder.serve('foo', '1.2.5');
-    });
+    final server = await servePackages()
+      ..serve('foo', '1.2.3')
+      ..serve('foo', '1.2.5');
 
     // Set up a cache with some packages.
     await d.dir(cachePath, [
       d.dir('hosted', [
-        d.dir('localhost%58${globalServer.port}', [
+        d.dir('localhost%58${server.port}', [
           d.dir('foo-1.2.3',
               [d.libPubspec('foo', '1.2.3'), d.file('broken.txt')]),
           d.dir('foo-1.2.4',
@@ -41,7 +38,7 @@
     expect(pub.stderr, emits(startsWith('Failed to repair foo 1.2.4. Error:')));
     expect(
         pub.stderr,
-        emits('Package doesn\'t exist '
+        emits('Package not available '
             '(Package foo has no version 1.2.4).'));
 
     expect(pub.stdout, emits('Reinstalled 2 packages.'));
diff --git a/test/cache/repair/handles_orphaned_binstub_test.dart b/test/cache/repair/handles_orphaned_binstub_test.dart
index 4954121..0754496 100644
--- a/test/cache/repair/handles_orphaned_binstub_test.dart
+++ b/test/cache/repair/handles_orphaned_binstub_test.dart
@@ -2,14 +2,12 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
-const _ORPHANED_BINSTUB = '''
+const _orphanedBinstub = '''
 #!/usr/bin/env sh
 # This file was created by pub v0.1.2-3.
 # Package: foo
@@ -22,7 +20,7 @@
 void main() {
   test('handles an orphaned binstub script', () async {
     await d.dir(cachePath, [
-      d.dir('bin', [d.file(binStubName('script'), _ORPHANED_BINSTUB)])
+      d.dir('bin', [d.file(binStubName('script'), _orphanedBinstub)])
     ]).create();
 
     await runPub(
diff --git a/test/cache/repair/hosted.dart b/test/cache/repair/hosted.dart
index 23d839b..ec3786b 100644
--- a/test/cache/repair/hosted.dart
+++ b/test/cache/repair/hosted.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -13,14 +11,13 @@
 import '../../test_pub.dart';
 
 void main() {
-  setUp(() {
-    return servePackages((builder) {
-      builder.serve('foo', '1.2.3');
-      builder.serve('foo', '1.2.4');
-      builder.serve('foo', '1.2.5');
-      builder.serve('bar', '1.2.3');
-      builder.serve('bar', '1.2.4');
-    });
+  setUp(() async {
+    await servePackages()
+      ..serve('foo', '1.2.3')
+      ..serve('foo', '1.2.4')
+      ..serve('foo', '1.2.5')
+      ..serve('bar', '1.2.3')
+      ..serve('bar', '1.2.4');
   });
 
   test('reinstalls previously cached hosted packages', () async {
diff --git a/test/cache/repair/recompiles_snapshots_test.dart b/test/cache/repair/recompiles_snapshots_test.dart
index 698e148..f3c3d6c 100644
--- a/test/cache/repair/recompiles_snapshots_test.dart
+++ b/test/cache/repair/recompiles_snapshots_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
 
 void main() {
   test('recompiles activated executable snapshots', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/cache/repair/updates_binstubs_test.dart b/test/cache/repair/updates_binstubs_test.dart
index bfb6400..e8cbfb4 100644
--- a/test/cache/repair/updates_binstubs_test.dart
+++ b/test/cache/repair/updates_binstubs_test.dart
@@ -2,14 +2,12 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
-const _OUTDATED_BINSTUB = '''
+const _outdatedBinstub = '''
 #!/usr/bin/env sh
 # This file was created by pub v0.1.2-3.
 # Package: foo
@@ -21,19 +19,17 @@
 
 void main() {
   test('updates an outdated binstub script', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'executables': {'foo-script': 'script'}
-      }, contents: [
-        d.dir(
-            'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'executables': {'foo-script': 'script'}
+    }, contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
     await d.dir(cachePath, [
-      d.dir('bin', [d.file(binStubName('foo-script'), _OUTDATED_BINSTUB)])
+      d.dir('bin', [d.file(binStubName('foo-script'), _outdatedBinstub)])
     ]).create();
 
     // Repair them.
diff --git a/test/dependency_override_test.dart b/test/dependency_override_test.dart
index 3cac645..dd8dc0d 100644
--- a/test/dependency_override_test.dart
+++ b/test/dependency_override_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 
 import 'package:test/test.dart';
@@ -14,11 +12,10 @@
 void main() {
   forBothPubGetAndUpgrade((command) {
     test('chooses best version matching override constraint', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-        builder.serve('foo', '2.0.0');
-        builder.serve('foo', '3.0.0');
-      });
+      await servePackages()
+        ..serve('foo', '1.0.0')
+        ..serve('foo', '2.0.0')
+        ..serve('foo', '3.0.0');
 
       await d.dir(appPath, [
         d.pubspec({
@@ -34,9 +31,8 @@
     });
 
     test('treats override as implicit dependency', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-      });
+      final server = await servePackages();
+      server.serve('foo', '1.0.0');
 
       await d.dir(appPath, [
         d.pubspec({
@@ -51,14 +47,13 @@
     });
 
     test('ignores other constraints on overridden package', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-        builder.serve('foo', '2.0.0');
-        builder.serve('foo', '3.0.0');
-        builder.serve('bar', '1.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0')
+        ..serve('foo', '2.0.0')
+        ..serve('foo', '3.0.0')
+        ..serve('bar', '1.0.0', pubspec: {
           'dependencies': {'foo': '5.0.0-nonexistent'}
         });
-      });
 
       await d.dir(appPath, [
         d.pubspec({
@@ -74,10 +69,9 @@
     });
 
     test('ignores SDK constraints', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
-          'environment': {'sdk': '5.6.7-fblthp'}
-        });
+      final server = await servePackages();
+      server.serve('foo', '1.0.0', pubspec: {
+        'environment': {'sdk': '5.6.7-fblthp'}
       });
 
       await d.dir(appPath, [
@@ -93,10 +87,9 @@
     });
 
     test('warns about overridden dependencies', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-        builder.serve('bar', '1.0.0');
-      });
+      await servePackages()
+        ..serve('foo', '1.0.0')
+        ..serve('bar', '1.0.0');
 
       await d
           .dir('baz', [d.libDir('baz'), d.libPubspec('baz', '0.0.1')]).create();
diff --git a/test/deps/executables_test.dart b/test/deps/executables_test.dart
index 978cc24..ea864fd 100644
--- a/test/deps/executables_test.dart
+++ b/test/deps/executables_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import '../descriptor.dart' as d;
 import '../golden_file.dart';
 import '../test_pub.dart';
diff --git a/test/deps_test.dart b/test/deps_test.dart
index 2d59ef8..7336f13 100644
--- a/test/deps_test.dart
+++ b/test/deps_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
 
@@ -12,21 +10,19 @@
 
 void main() {
   setUp(() async {
-    await servePackages((builder) {
-      builder.serve('normal', '1.2.3',
-          deps: {'transitive': 'any', 'circular_a': 'any'});
-      builder.serve('transitive', '1.2.3', deps: {'shared': 'any'});
-      builder.serve('shared', '1.2.3', deps: {'other': 'any'});
-      builder.serve('dev_only', '1.2.3');
-      builder.serve('unittest', '1.2.3',
-          deps: {'shared': 'any', 'dev_only': 'any'});
-      builder.serve('other', '1.0.0', deps: {'myapp': 'any'});
-      builder.serve('overridden', '1.0.0');
-      builder.serve('overridden', '2.0.0');
-      builder.serve('override_only', '1.2.3');
-      builder.serve('circular_a', '1.2.3', deps: {'circular_b': 'any'});
-      builder.serve('circular_b', '1.2.3', deps: {'circular_a': 'any'});
-    });
+    await servePackages()
+      ..serve('normal', '1.2.3',
+          deps: {'transitive': 'any', 'circular_a': 'any'})
+      ..serve('transitive', '1.2.3', deps: {'shared': 'any'})
+      ..serve('shared', '1.2.3', deps: {'other': 'any'})
+      ..serve('dev_only', '1.2.3')
+      ..serve('unittest', '1.2.3', deps: {'shared': 'any', 'dev_only': 'any'})
+      ..serve('other', '1.0.0', deps: {'myapp': 'any'})
+      ..serve('overridden', '1.0.0')
+      ..serve('overridden', '2.0.0')
+      ..serve('override_only', '1.2.3')
+      ..serve('circular_a', '1.2.3', deps: {'circular_b': 'any'})
+      ..serve('circular_b', '1.2.3', deps: {'circular_a': 'any'});
 
     await d.dir('from_path',
         [d.libDir('from_path'), d.libPubspec('from_path', '1.2.3')]).create();
diff --git a/test/descriptor.dart b/test/descriptor.dart
index 3eee5d1..7b140e2 100644
--- a/test/descriptor.dart
+++ b/test/descriptor.dart
@@ -2,12 +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.
 
-// @dart=2.10
-
 /// Pub-specific test descriptors.
 import 'dart:convert';
 
-import 'package:meta/meta.dart';
 import 'package:oauth2/oauth2.dart' as oauth2;
 import 'package:path/path.dart' as p;
 import 'package:pub/src/language_version.dart';
@@ -27,11 +24,11 @@
 export 'descriptor/tar.dart';
 
 /// Creates a new [GitRepoDescriptor] with [name] and [contents].
-GitRepoDescriptor git(String name, [Iterable<Descriptor> contents]) =>
+GitRepoDescriptor git(String name, [List<Descriptor>? contents]) =>
     GitRepoDescriptor(name, contents ?? <Descriptor>[]);
 
 /// Creates a new [TarFileDescriptor] with [name] and [contents].
-TarFileDescriptor tar(String name, [Iterable<Descriptor> contents]) =>
+TarFileDescriptor tar(String name, [List<Descriptor>? contents]) =>
     TarFileDescriptor(name, contents ?? <Descriptor>[]);
 
 /// Describes a package that passes all validation.
@@ -67,14 +64,14 @@
 ///
 /// [contents] may contain [Future]s that resolve to serializable objects,
 /// which may in turn contain [Future]s recursively.
-Descriptor pubspec(Map<String, Object> contents) => YamlDescriptor(
+Descriptor pubspec(Map<String, Object?> contents) => YamlDescriptor(
       'pubspec.yaml',
       yaml({
         ...contents,
         // TODO: Copy-pasting this into all call-sites, or use d.libPubspec
         'environment': {
           'sdk': '>=0.1.2 <1.0.0',
-          ...contents['environment'] as Map ?? {},
+          ...(contents['environment'] ?? {}) as Map,
         },
       }),
     );
@@ -84,8 +81,8 @@
 
 /// Describes a file named `pubspec.yaml` for an application package with the
 /// given [dependencies].
-Descriptor appPubspec([Map dependencies]) {
-  var map = <String, dynamic>{
+Descriptor appPubspec([Map? dependencies]) {
+  var map = <String, Object>{
     'name': 'myapp',
     'environment': {
       'sdk': '>=0.1.2 <1.0.0',
@@ -100,7 +97,7 @@
 /// constraint on that version, otherwise it adds an SDK constraint allowing
 /// the current SDK version.
 Descriptor libPubspec(String name, String version,
-    {Map deps, Map devDeps, String sdk}) {
+    {Map? deps, Map? devDeps, String? sdk}) {
   var map = packageMap(name, version, deps, devDeps);
   if (sdk != null) {
     map['environment'] = {'sdk': sdk};
@@ -112,7 +109,7 @@
 
 /// Describes a directory named `lib` containing a single dart file named
 /// `<name>.dart` that contains a line of Dart code.
-Descriptor libDir(String name, [String code]) {
+Descriptor libDir(String name, [String? code]) {
   // Default to printing the name if no other code was given.
   code ??= name;
   return dir('lib', [file('$name.dart', 'main() => "$code";')]);
@@ -130,8 +127,8 @@
 /// If [repoName] is not given it is assumed to be equal to [packageName].
 Descriptor gitPackageRevisionCacheDir(
   String packageName, {
-  int modifier,
-  String repoName,
+  int? modifier,
+  String? repoName,
 }) {
   repoName = repoName ?? packageName;
   var value = packageName;
@@ -159,7 +156,7 @@
 /// validated since they will often lack the dependencies section that the
 /// real pubspec being compared against has. You usually only need to pass
 /// `true` for this if you plan to call [create] on the resulting descriptor.
-Descriptor cacheDir(Map packages, {int port, bool includePubspecs = false}) {
+Descriptor cacheDir(Map packages, {int? port, bool includePubspecs = false}) {
   var contents = <Descriptor>[];
   packages.forEach((name, versions) {
     if (versions is! List) versions = [versions];
@@ -180,7 +177,7 @@
 ///
 /// If [port] is passed, it's used as the port number of the local hosted server
 /// that this cache represents. It defaults to [globalServer.port].
-Descriptor hostedCache(Iterable<Descriptor> contents, {int port}) {
+Descriptor hostedCache(Iterable<Descriptor> contents, {int? port}) {
   return dir(cachePath, [
     dir('hosted', [dir('localhost%58${port ?? globalServer.port}', contents)])
   ]);
@@ -190,7 +187,7 @@
 /// credentials. The URL "/token" on [server] will be used as the token
 /// endpoint for refreshing the access token.
 Descriptor credentialsFile(PackageServer server, String accessToken,
-    {String refreshToken, DateTime expiration}) {
+    {String? refreshToken, DateTime? expiration}) {
   return dir(
     configPath,
     [
@@ -208,7 +205,7 @@
 }
 
 Descriptor legacyCredentialsFile(PackageServer server, String accessToken,
-    {String refreshToken, DateTime expiration}) {
+    {String? refreshToken, DateTime? expiration}) {
   return dir(
     cachePath,
     [
@@ -228,8 +225,8 @@
 String _credentialsFileContent(
   PackageServer server,
   String accessToken, {
-  String refreshToken,
-  DateTime expiration,
+  String? refreshToken,
+  DateTime? expiration,
 }) =>
     oauth2.Credentials(
       accessToken,
@@ -245,14 +242,12 @@
 /// Describes the file in the system cache that contains credentials for
 /// third party hosted pub servers.
 Descriptor tokensFile([Map<String, dynamic> contents = const {}]) {
-  return dir(configPath, [
-    file('pub-tokens.json', contents != null ? jsonEncode(contents) : null)
-  ]);
+  return dir(configPath, [file('pub-tokens.json', jsonEncode(contents))]);
 }
 
 /// Describes the application directory, containing only a pubspec specifying
 /// the given [dependencies].
-DirectoryDescriptor appDir([Map dependencies]) =>
+DirectoryDescriptor appDir([Map? dependencies]) =>
     dir(appPath, [appPubspec(dependencies)]);
 
 /// Describes a `.packages` file.
@@ -266,7 +261,7 @@
 /// entries (one per key in [dependencies]), each with a path that contains
 /// either the version string (for a reference to the pub cache) or a
 /// path to a path dependency, relative to the application directory.
-Descriptor packagesFile([Map<String, String> dependencies]) =>
+Descriptor packagesFile(Map<String, String> dependencies) =>
     PackagesFileDescriptor(dependencies);
 
 /// Describes a `.dart_tools/package_config.json` file.
@@ -285,10 +280,10 @@
 /// Create a [PackageConfigEntry] which assumes package with [name] is either
 /// a cached package with given [version] or a path dependency at given [path].
 PackageConfigEntry packageConfigEntry({
-  @required String name,
-  String version,
-  String path,
-  String languageVersion,
+  required String name,
+  String? version,
+  String? path,
+  String? languageVersion,
 }) {
   if (version != null && path != null) {
     throw ArgumentError.value(
@@ -300,7 +295,7 @@
   }
   Uri rootUri;
   if (version != null) {
-    rootUri = p.toUri(globalPackageServer.pathInCache(name, version));
+    rootUri = p.toUri(globalServer.pathInCache(name, version));
   } else {
     rootUri = p.toUri(p.join('..', path));
   }
diff --git a/test/descriptor/git.dart b/test/descriptor/git.dart
index 56cd59f..edfc7bd 100644
--- a/test/descriptor/git.dart
+++ b/test/descriptor/git.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async';
 
 import 'package:path/path.dart' as path;
@@ -17,7 +15,7 @@
 
   /// Creates the Git repository and commits the contents.
   @override
-  Future create([String parent]) async {
+  Future create([String? parent]) async {
     await super.create(parent);
     await _runGitCommands(parent, [
       ['init'],
@@ -35,7 +33,7 @@
   /// the previous structure to the Git repo.
   ///
   /// [parent] defaults to [sandbox].
-  Future commit([String parent]) async {
+  Future commit([String? parent]) async {
     await super.create(parent);
     await _runGitCommands(parent, [
       ['add', '.'],
@@ -47,7 +45,7 @@
   /// referred to by [ref].
   ///
   /// [parent] defaults to [sandbox].
-  Future<String> revParse(String ref, [String parent]) async {
+  Future<String> revParse(String ref, [String? parent]) async {
     var output = await _runGit(['rev-parse', ref], parent);
     return output[0];
   }
@@ -55,9 +53,9 @@
   /// Runs a Git command in this repository.
   ///
   /// [parent] defaults to [sandbox].
-  Future runGit(List<String> args, [String parent]) => _runGit(args, parent);
+  Future runGit(List<String> args, [String? parent]) => _runGit(args, parent);
 
-  Future<List<String>> _runGit(List<String> args, String parent) {
+  Future<List<String>> _runGit(List<String> args, String? parent) {
     // Explicitly specify the committer information. Git needs this to commit
     // and we don't want to rely on the buildbots having this already set up.
     var environment = {
@@ -72,7 +70,7 @@
         environment: environment);
   }
 
-  Future _runGitCommands(String parent, List<List<String>> commands) async {
+  Future _runGitCommands(String? parent, List<List<String>> commands) async {
     for (var command in commands) {
       await _runGit(command, parent);
     }
diff --git a/test/descriptor/packages.dart b/test/descriptor/packages.dart
index 2a23e40..de52a80 100644
--- a/test/descriptor/packages.dart
+++ b/test/descriptor/packages.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async' show Future;
 import 'dart:convert' show JsonEncoder, json, utf8;
 import 'dart:io' show File;
@@ -25,7 +23,7 @@
 /// Describes a `.packages` file and its contents.
 class PackagesFileDescriptor extends Descriptor {
   /// A map from package names to either version strings or path to the package.
-  final Map<String, String> _dependencies;
+  final Map<String, String>? _dependencies;
 
   /// Describes a `.packages` file with the given dependencies.
   ///
@@ -34,11 +32,12 @@
   PackagesFileDescriptor([this._dependencies]) : super('.packages');
 
   @override
-  Future create([String parent]) {
+  Future create([String? parent]) {
     var contents = const <int>[];
-    if (_dependencies != null) {
+    var dependencies = _dependencies;
+    if (dependencies != null) {
       var mapping = <String, Uri>{};
-      _dependencies.forEach((package, version) {
+      dependencies.forEach((package, version) {
         String packagePath;
         if (_isSemver(version)) {
           // It's a cache reference.
@@ -58,7 +57,7 @@
   }
 
   @override
-  Future validate([String parent]) async {
+  Future validate([String? parent]) async {
     var fullPath = p.join(parent ?? sandbox, name);
     if (!await File(fullPath).exists()) {
       fail("File not found: '$fullPath'.");
@@ -68,14 +67,16 @@
 
     var map = packages_file.parse(bytes, Uri.parse(_base));
 
-    for (var package in _dependencies.keys) {
+    var dependencies = _dependencies!;
+
+    for (var package in dependencies.keys) {
       if (!map.containsKey(package)) {
         fail('.packages does not contain $package entry');
       }
 
-      var description = _dependencies[package];
+      var description = dependencies[package]!;
       if (_isSemver(description)) {
-        if (!map[package].path.contains(description)) {
+        if (!map[package]!.path.contains(description)) {
           fail('.packages of $package has incorrect version. '
               'Expected $description, found location: ${map[package]}.');
         }
@@ -90,9 +91,9 @@
       }
     }
 
-    if (map.length != _dependencies.length) {
+    if (map.length != dependencies.length) {
       for (var key in map.keys) {
-        if (!_dependencies.containsKey(key)) {
+        if (!dependencies.containsKey(key)) {
           fail('.packages file contains unexpected entry: $key');
         }
       }
@@ -128,7 +129,7 @@
       : super('.dart_tool/package_config.json');
 
   @override
-  Future<void> create([String parent]) async {
+  Future<void> create([String? parent]) async {
     final packageConfigFile = File(p.join(parent ?? sandbox, name));
     await packageConfigFile.parent.create();
     await packageConfigFile.writeAsString(
@@ -137,13 +138,13 @@
   }
 
   @override
-  Future<void> validate([String parent]) async {
+  Future<void> validate([String? parent]) async {
     final packageConfigFile = p.join(parent ?? sandbox, name);
     if (!await File(packageConfigFile).exists()) {
       fail("File not found: '$packageConfigFile'.");
     }
 
-    Map<String, Object> rawJson = json.decode(
+    Map<String, dynamic> rawJson = json.decode(
       await File(packageConfigFile).readAsString(),
     );
     PackageConfig config;
diff --git a/test/descriptor/tar.dart b/test/descriptor/tar.dart
index 1c4f89f..2a3488f 100644
--- a/test/descriptor/tar.dart
+++ b/test/descriptor/tar.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async';
 import 'dart:io';
 
@@ -23,7 +21,7 @@
   /// Creates the files and directories within this tar file, then archives
   /// them, compresses them, and saves the result to [parentDir].
   @override
-  Future create([String parent]) {
+  Future create([String? parent]) {
     return withTempDir((tempDir) async {
       await Future.wait(contents.map((entry) => entry.create(tempDir)));
 
@@ -41,7 +39,7 @@
   /// Validates that the `.tar.gz` file at [path] contains the expected
   /// contents.
   @override
-  Future validate([String parent]) {
+  Future validate([String? parent]) {
     throw UnimplementedError('TODO(nweiz): implement this');
   }
 
diff --git a/test/descriptor/yaml.dart b/test/descriptor/yaml.dart
index 086da84..6840041 100644
--- a/test/descriptor/yaml.dart
+++ b/test/descriptor/yaml.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async' show Future;
 import 'dart:convert' show utf8;
 import 'dart:io';
@@ -29,7 +27,7 @@
       Stream.fromIterable([utf8.encode(_contents)]);
 
   @override
-  Future validate([String parent]) async {
+  Future validate([String? parent]) async {
     var fullPath = p.join(parent ?? sandbox, name);
     if (!await File(fullPath).exists()) {
       fail("File not found: '$fullPath'.");
diff --git a/test/descriptor_server.dart b/test/descriptor_server.dart
deleted file mode 100644
index a023518..0000000
--- a/test/descriptor_server.dart
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2016, 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.
-
-// @dart=2.10
-
-import 'dart:async';
-
-import 'package:path/path.dart' as p;
-import 'package:shelf/shelf.dart' as shelf;
-import 'package:shelf/shelf_io.dart' as shelf_io;
-import 'package:test/test.dart' hide fail;
-
-import 'descriptor.dart' as d;
-
-/// The global [DescriptorServer] that's used by default.
-///
-/// `null` if there's no global server in use. This can be set to replace the
-/// existing global server.
-DescriptorServer get globalServer => _globalServer;
-set globalServer(DescriptorServer value) {
-  if (_globalServer == null) {
-    addTearDown(() {
-      _globalServer = null;
-    });
-  } else {
-    expect(_globalServer.close(), completes);
-  }
-
-  _globalServer = value;
-}
-
-DescriptorServer _globalServer;
-
-/// Creates a global [DescriptorServer] to serve [contents] as static files.
-///
-/// This server will exist only for the duration of the pub run. It's accessible
-/// via [server]. Subsequent calls to [serve] replace the previous server.
-Future serve([List<d.Descriptor> contents]) async {
-  globalServer = (await DescriptorServer.start())..contents.addAll(contents);
-}
-
-class DescriptorServer {
-  /// The underlying server.
-  final shelf.Server _server;
-
-  /// A future that will complete to the port used for the server.
-  int get port => _server.url.port;
-
-  /// The list of paths that have been requested from this server.
-  final requestedPaths = <String>[];
-
-  /// The base directory descriptor of the directories served by [this].
-  final d.DirectoryDescriptor _baseDir;
-
-  /// The descriptors served by this server.
-  ///
-  /// This can safely be modified between requests.
-  List<d.Descriptor> get contents => _baseDir.contents;
-
-  /// Handlers for requests not easily described as files.
-  final Map<Pattern, shelf.Handler> extraHandlers = {};
-
-  /// Creates an HTTP server to serve [contents] as static files.
-  ///
-  /// This server exists only for the duration of the pub run. Subsequent calls
-  /// to [serve] replace the previous server.
-  static Future<DescriptorServer> start() async =>
-      DescriptorServer._(await shelf_io.IOServer.bind('localhost', 0));
-
-  /// Creates a server that reports an error if a request is ever received.
-  static Future<DescriptorServer> errors() async =>
-      DescriptorServer._(await shelf_io.IOServer.bind('localhost', 0));
-
-  DescriptorServer._(this._server) : _baseDir = d.dir('serve-dir', []) {
-    _server.mount((request) async {
-      final pathWithInitialSlash = '/${request.url.path}';
-      final key = extraHandlers.keys.firstWhere((pattern) {
-        final match = pattern.matchAsPrefix(pathWithInitialSlash);
-        return match != null && match.end == pathWithInitialSlash.length;
-      }, orElse: () => null);
-      if (key != null) return extraHandlers[key](request);
-
-      var path = p.posix.fromUri(request.url.path);
-      requestedPaths.add(path);
-
-      try {
-        var stream = await _validateStream(_baseDir.load(path));
-        return shelf.Response.ok(stream);
-      } catch (_) {
-        return shelf.Response.notFound('File "$path" not found.');
-      }
-    });
-    addTearDown(_server.close);
-  }
-
-  /// Closes this server.
-  Future close() => _server.close();
-}
-
-/// Ensures that [stream] can emit at least one value successfully (or close
-/// without any values).
-///
-/// For example, reading asynchronously from a non-existent file will return a
-/// stream that fails on the first chunk. In order to handle that more
-/// gracefully, you may want to check that the stream looks like it's working
-/// before you pipe the stream to something else.
-///
-/// This lets you do that. It returns a [Future] that completes to a [Stream]
-/// emitting the same values and errors as [stream], but only if at least one
-/// value can be read successfully. If an error occurs before any values are
-/// emitted, the returned Future completes to that error.
-Future<Stream<T>> _validateStream<T>(Stream<T> stream) {
-  var completer = Completer<Stream<T>>();
-  var controller = StreamController<T>(sync: true);
-
-  StreamSubscription subscription;
-  subscription = stream.listen((value) {
-    // We got a value, so the stream is valid.
-    if (!completer.isCompleted) completer.complete(controller.stream);
-    controller.add(value);
-  }, onError: (error, [StackTrace stackTrace]) {
-    // If the error came after values, it's OK.
-    if (completer.isCompleted) {
-      controller.addError(error, stackTrace);
-      return;
-    }
-
-    // Otherwise, the error came first and the stream is invalid.
-    completer.completeError(error, stackTrace);
-
-    // We won't be returning the stream at all in this case, so unsubscribe
-    // and swallow the error.
-    subscription.cancel();
-  }, onDone: () {
-    // It closed with no errors, so the stream is valid.
-    if (!completer.isCompleted) completer.complete(controller.stream);
-    controller.close();
-  });
-
-  return completer.future;
-}
diff --git a/test/dev_dependency_test.dart b/test/dev_dependency_test.dart
index 471f53c..88f321b 100644
--- a/test/dev_dependency_test.dart
+++ b/test/dev_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import 'descriptor.dart' as d;
diff --git a/test/directory_option_test.dart b/test/directory_option_test.dart
index 541ddd4..65193bf 100644
--- a/test/directory_option_test.dart
+++ b/test/directory_option_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:path/path.dart' as p;
@@ -16,20 +14,21 @@
 Future<void> main() async {
   testWithGolden('commands taking a --directory/-C parameter work',
       (ctx) async {
-    await servePackages((b) => b
+    await servePackages()
       ..serve('foo', '1.0.0')
       ..serve('foo', '0.1.2')
-      ..serve('bar', '1.2.3'));
-    await credentialsFile(globalPackageServer, 'access token').create();
-    globalPackageServer
-        .extraHandlers[RegExp('/api/packages/test_pkg/uploaders')] = (request) {
-      return shelf.Response.ok(
-        jsonEncode({
-          'success': {'message': 'Good job!'}
-        }),
-        headers: {'content-type': 'application/json'},
-      );
-    };
+      ..serve('bar', '1.2.3');
+    await credentialsFile(globalServer, 'access token').create();
+    globalServer.handle(
+      RegExp('/api/packages/test_pkg/uploaders'),
+      (request) {
+        return shelf.Response.ok(
+            jsonEncode({
+              'success': {'message': 'Good job!'}
+            }),
+            headers: {'content-type': 'application/json'});
+      },
+    );
 
     await validPackage.create();
     await dir(appPath, [
diff --git a/test/downgrade/does_not_show_other_versions_test.dart b/test/downgrade/does_not_show_other_versions_test.dart
index 485debb..884bbaf 100644
--- a/test/downgrade/does_not_show_other_versions_test.dart
+++ b/test/downgrade/does_not_show_other_versions_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -11,11 +9,10 @@
 
 void main() {
   test('does not show how many other versions are available', () async {
-    await servePackages((builder) {
-      builder.serve('downgraded', '1.0.0');
-      builder.serve('downgraded', '2.0.0');
-      builder.serve('downgraded', '3.0.0-dev');
-    });
+    await servePackages()
+      ..serve('downgraded', '1.0.0')
+      ..serve('downgraded', '2.0.0')
+      ..serve('downgraded', '3.0.0-dev');
 
     await d.appDir({'downgraded': '3.0.0-dev'}).create();
 
diff --git a/test/downgrade/doesnt_change_git_dependencies_test.dart b/test/downgrade/doesnt_change_git_dependencies_test.dart
index 41f0a51..1450af5 100644
--- a/test/downgrade/doesnt_change_git_dependencies_test.dart
+++ b/test/downgrade/doesnt_change_git_dependencies_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
diff --git a/test/downgrade/dry_run_does_not_apply_changes_test.dart b/test/downgrade/dry_run_does_not_apply_changes_test.dart
index 765cb35..38fbebe 100644
--- a/test/downgrade/dry_run_does_not_apply_changes_test.dart
+++ b/test/downgrade/dry_run_does_not_apply_changes_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -13,10 +11,9 @@
 
 void main() {
   test('--dry-run shows report but does not apply changes', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '2.0.0');
 
     // Create the first lockfile.
     await d.appDir({'foo': '2.0.0'}).create();
diff --git a/test/downgrade/unlock_if_necessary_test.dart b/test/downgrade/unlock_if_necessary_test.dart
index b8aa83e..0299e27 100644
--- a/test/downgrade/unlock_if_necessary_test.dart
+++ b/test/downgrade/unlock_if_necessary_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -13,10 +11,9 @@
   test(
       "downgrades one locked hosted package's dependencies if it's "
       'necessary', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '2.0.0', deps: {'foo_dep': 'any'});
-      builder.serve('foo_dep', '2.0.0');
-    });
+    final server = await servePackages();
+    server.serve('foo', '2.0.0', deps: {'foo_dep': 'any'});
+    server.serve('foo_dep', '2.0.0');
 
     await d.appDir({'foo': 'any'}).create();
 
@@ -24,10 +21,8 @@
 
     await d.appPackagesFile({'foo': '2.0.0', 'foo_dep': '2.0.0'}).validate();
 
-    globalPackageServer.add((builder) {
-      builder.serve('foo', '1.0.0', deps: {'foo_dep': '<2.0.0'});
-      builder.serve('foo_dep', '1.0.0');
-    });
+    server.serve('foo', '1.0.0', deps: {'foo_dep': '<2.0.0'});
+    server.serve('foo_dep', '1.0.0');
 
     await pubDowngrade(args: ['foo']);
 
diff --git a/test/downgrade/unlock_single_package_test.dart b/test/downgrade/unlock_single_package_test.dart
index 73c3467..cfd315d 100644
--- a/test/downgrade/unlock_single_package_test.dart
+++ b/test/downgrade/unlock_single_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -11,28 +9,23 @@
 
 void main() {
   test('can unlock a single package only in downgrade', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '2.1.0', deps: {'bar': '>1.0.0'});
-      builder.serve('bar', '2.1.0');
-    });
+    final server = await servePackages();
+    server.serve('foo', '2.1.0', deps: {'bar': '>1.0.0'});
+    server.serve('bar', '2.1.0');
 
     await d.appDir({'foo': 'any', 'bar': 'any'}).create();
 
     await pubGet();
     await d.appPackagesFile({'foo': '2.1.0', 'bar': '2.1.0'}).validate();
 
-    globalPackageServer.add((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
-      builder.serve('bar', '1.0.0');
-    });
+    server.serve('foo', '1.0.0', deps: {'bar': 'any'});
+    server.serve('bar', '1.0.0');
 
     await pubDowngrade(args: ['bar']);
     await d.appPackagesFile({'foo': '2.1.0', 'bar': '2.1.0'}).validate();
 
-    globalPackageServer.add((builder) {
-      builder.serve('foo', '2.0.0', deps: {'bar': 'any'});
-      builder.serve('bar', '2.0.0');
-    });
+    server.serve('foo', '2.0.0', deps: {'bar': 'any'});
+    server.serve('bar', '2.0.0');
 
     await pubDowngrade(args: ['bar']);
     await d.appPackagesFile({'foo': '2.1.0', 'bar': '2.0.0'}).validate();
@@ -42,11 +35,10 @@
   });
 
   test('will not downgrade below constraint #2629', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '2.0.0');
-      builder.serve('foo', '2.1.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '2.0.0')
+      ..serve('foo', '2.1.0');
 
     await d.appDir({'foo': '^2.0.0'}).create();
 
diff --git a/test/embedding/embedding_test.dart b/test/embedding/embedding_test.dart
index b5cf8bd..ccb16f6 100644
--- a/test/embedding/embedding_test.dart
+++ b/test/embedding/embedding_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 import 'dart:io';
 
@@ -14,16 +12,16 @@
 import '../golden_file.dart';
 import '../test_pub.dart';
 
-const _command_runner = 'tool/test-bin/pub_command_runner.dart';
+const _commandRunner = 'tool/test-bin/pub_command_runner.dart';
 
-String snapshot;
+late String snapshot;
 
 /// Runs `dart tool/test-bin/pub_command_runner.dart [args]` and appends the output to [buffer].
 Future<void> runEmbeddingToBuffer(
   List<String> args,
   StringBuffer buffer, {
-  String workingDirextory,
-  Map<String, String> environment,
+  String? workingDirectory,
+  Map<String, String>? environment,
   dynamic exitCode = 0,
 }) async {
   final process = await TestProcess.start(
@@ -33,12 +31,12 @@
       ...getPubTestEnvironment(),
       ...?environment,
     },
-    workingDirectory: workingDirextory,
+    workingDirectory: workingDirectory,
   );
   await process.shouldExit(exitCode);
 
   buffer.writeln([
-    '\$ $_command_runner ${args.join(' ')}',
+    '\$ $_commandRunner ${args.join(' ')}',
     ...await process.stdout.rest.toList(),
   ].join('\n'));
   final stdErr = await process.stderr.rest.toList();
@@ -53,15 +51,15 @@
   /// next section in golden file.
   Future<void> runEmbedding(
     List<String> args, {
-    String workingDirextory,
-    Map<String, String> environment,
+    String? workingDirextory,
+    Map<String, String>? environment,
     dynamic exitCode = 0,
   }) async {
     final buffer = StringBuffer();
     await runEmbeddingToBuffer(
       args,
       buffer,
-      workingDirextory: workingDirextory,
+      workingDirectory: workingDirextory,
       environment: environment,
       exitCode: exitCode,
     );
@@ -75,7 +73,7 @@
     final tempDir = Directory.systemTemp.createTempSync();
     snapshot = path.join(tempDir.path, 'command_runner.dart.snapshot');
     final r = Process.runSync(
-        Platform.resolvedExecutable, ['--snapshot=$snapshot', _command_runner]);
+        Platform.resolvedExecutable, ['--snapshot=$snapshot', _commandRunner]);
     expect(r.exitCode, 0, reason: r.stderr);
   });
 
@@ -113,9 +111,9 @@
   });
 
   test('analytics', () async {
-    await servePackages((b) => b
+    await servePackages()
       ..serve('foo', '1.0.0', deps: {'bar': 'any'})
-      ..serve('bar', '1.0.0'));
+      ..serve('bar', '1.0.0');
     await d.dir('dep', [
       d.pubspec({
         'name': 'dep',
@@ -136,7 +134,7 @@
     await runEmbeddingToBuffer(
       ['pub', 'get'],
       buffer,
-      workingDirextory: app.io.path,
+      workingDirectory: app.io.path,
       environment: {...getPubTestEnvironment(), '_PUB_LOG_ANALYTICS': 'true'},
     );
     final analytics = buffer
diff --git a/test/embedding/get_executable_for_command_test.dart b/test/embedding/get_executable_for_command_test.dart
index 7667e12..0edfa72 100644
--- a/test/embedding/get_executable_for_command_test.dart
+++ b/test/embedding/get_executable_for_command_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:path/path.dart' show separator;
@@ -23,11 +21,11 @@
   executable,
   packageConfig,
   errorMessage,
-  CommandResolutionIssue issue,
+  CommandResolutionIssue? issue,
 }) async {
   final _cachePath = getPubTestEnvironment()['PUB_CACHE'];
   final oldVerbosity = log.verbosity;
-  log.verbosity = log.Verbosity.NONE;
+  log.verbosity = log.Verbosity.none;
   if (executable == null) {
     expect(
       () => getExecutableForCommand(
@@ -131,7 +129,7 @@
       ])
     ]).create();
 
-    await serveNoPackages();
+    await servePackages();
     // The solver uses word-wrapping in its error message, so we use \s to
     // accomodate.
     await testGetExecutable(
@@ -168,7 +166,7 @@
       ])
     ]).create();
 
-    await serveNoPackages();
+    await servePackages();
     // The solver uses word-wrapping in its error message, so we use \s to
     // accomodate.
     await testGetExecutable(
@@ -180,15 +178,15 @@
   });
 
   test('Finds files', () async {
-    await servePackages((b) => b
-      ..serve('foo', '1.0.0', pubspec: {
-        'environment': {'sdk': '>=$_currentVersion <3.0.0'}
-      }, contents: [
-        d.dir('bin', [
-          d.file('foo.dart', 'main() {print(42);}'),
-          d.file('tool.dart', 'main() {print(42);}')
-        ])
-      ]));
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'environment': {'sdk': '>=$_currentVersion <3.0.0'}
+    }, contents: [
+      d.dir('bin', [
+        d.file('foo.dart', 'main() {print(42);}'),
+        d.file('tool.dart', 'main() {print(42);}')
+      ])
+    ]);
 
     await d.dir(appPath, [
       d.pubspec({
diff --git a/test/get/dry_run_does_not_apply_changes_test.dart b/test/get/dry_run_does_not_apply_changes_test.dart
index 1879f51..3e44bf9 100644
--- a/test/get/dry_run_does_not_apply_changes_test.dart
+++ b/test/get/dry_run_does_not_apply_changes_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -11,9 +9,8 @@
 
 void main() {
   test('--dry-run shows but does not apply changes', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
 
     await d.appDir({'foo': '1.0.0'}).create();
 
diff --git a/test/get/flutter_constraint_upper_bound_ignored_test.dart b/test/get/flutter_constraint_upper_bound_ignored_test.dart
index 9fc833c..7fd2edc 100644
--- a/test/get/flutter_constraint_upper_bound_ignored_test.dart
+++ b/test/get/flutter_constraint_upper_bound_ignored_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/get/gets_in_example_folder_test.dart b/test/get/gets_in_example_folder_test.dart
index d7f6c57..04f9d47 100644
--- a/test/get/gets_in_example_folder_test.dart
+++ b/test/get/gets_in_example_folder_test.dart
@@ -2,8 +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.
 
-// @dart = 2.11
-
 import 'dart:io';
 
 import 'package:path/path.dart' as p;
diff --git a/test/get/git/check_out_and_upgrade_test.dart b/test/get/git/check_out_and_upgrade_test.dart
index 846859b..42044af 100644
--- a/test/get/git/check_out_and_upgrade_test.dart
+++ b/test/get/git/check_out_and_upgrade_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/get/git/check_out_branch_test.dart b/test/get/git/check_out_branch_test.dart
index 0b58abf..104c8b9 100644
--- a/test/get/git/check_out_branch_test.dart
+++ b/test/get/git/check_out_branch_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/get/git/check_out_revision_test.dart b/test/get/git/check_out_revision_test.dart
index eed9f01..2428d7c 100644
--- a/test/get/git/check_out_revision_test.dart
+++ b/test/get/git/check_out_revision_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/get/git/check_out_test.dart b/test/get/git/check_out_test.dart
index 194e980..f3caaa2 100644
--- a/test/get/git/check_out_test.dart
+++ b/test/get/git/check_out_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:path/path.dart' as p;
diff --git a/test/get/git/check_out_transitive_test.dart b/test/get/git/check_out_transitive_test.dart
index b7e71fa..0587c58 100644
--- a/test/get/git/check_out_transitive_test.dart
+++ b/test/get/git/check_out_transitive_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
diff --git a/test/get/git/check_out_twice_test.dart b/test/get/git/check_out_twice_test.dart
index f9cebd1..b6de388 100644
--- a/test/get/git/check_out_twice_test.dart
+++ b/test/get/git/check_out_twice_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/get/git/check_out_unfetched_revision_of_cached_repo_test.dart b/test/get/git/check_out_unfetched_revision_of_cached_repo_test.dart
index c5fc4aa..dae234d 100644
--- a/test/get/git/check_out_unfetched_revision_of_cached_repo_test.dart
+++ b/test/get/git/check_out_unfetched_revision_of_cached_repo_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
diff --git a/test/get/git/check_out_with_trailing_slash_test.dart b/test/get/git/check_out_with_trailing_slash_test.dart
index 16dc07c..5838986 100644
--- a/test/get/git/check_out_with_trailing_slash_test.dart
+++ b/test/get/git/check_out_with_trailing_slash_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/get/git/clean_invalid_git_repo_cache_test.dart b/test/get/git/clean_invalid_git_repo_cache_test.dart
index 6ea650b..ab386ab 100644
--- a/test/get/git/clean_invalid_git_repo_cache_test.dart
+++ b/test/get/git/clean_invalid_git_repo_cache_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.
 
-// @dart=2.10
 import 'dart:io';
 
 import 'package:path/path.dart' as path;
@@ -15,11 +14,10 @@
 void _invalidateGitCache(String repo) {
   final cacheDir =
       path.join(d.sandbox, path.joinAll([cachePath, 'git', 'cache']));
-  final Directory fooCacheDir =
-      Directory(cacheDir).listSync().firstWhere((entity) {
+  final fooCacheDir = Directory(cacheDir).listSync().firstWhere((entity) {
     return entity is Directory &&
         entity.path.split(Platform.pathSeparator).last.startsWith(repo);
-  });
+  }) as Directory;
 
   fooCacheDir.deleteSync(recursive: true);
   fooCacheDir.createSync();
diff --git a/test/get/git/dependency_name_match_pubspec_test.dart b/test/get/git/dependency_name_match_pubspec_test.dart
index 2accd62..1545fca 100644
--- a/test/get/git/dependency_name_match_pubspec_test.dart
+++ b/test/get/git/dependency_name_match_pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/get/git/different_repo_name_test.dart b/test/get/git/different_repo_name_test.dart
index 65e37eb..1d8f9c4 100644
--- a/test/get/git/different_repo_name_test.dart
+++ b/test/get/git/different_repo_name_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/get/git/doesnt_fetch_if_nothing_changes_test.dart b/test/get/git/doesnt_fetch_if_nothing_changes_test.dart
index ec214d4..3d9f040 100644
--- a/test/get/git/doesnt_fetch_if_nothing_changes_test.dart
+++ b/test/get/git/doesnt_fetch_if_nothing_changes_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
diff --git a/test/get/git/git_not_installed_test.dart b/test/get/git/git_not_installed_test.dart
index 13a5601..f00d795 100644
--- a/test/get/git/git_not_installed_test.dart
+++ b/test/get/git/git_not_installed_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 @TestOn('linux')
 import 'dart:io';
 
diff --git a/test/get/git/lock_version_test.dart b/test/get/git/lock_version_test.dart
index 1e51d12..40b2708 100644
--- a/test/get/git/lock_version_test.dart
+++ b/test/get/git/lock_version_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
diff --git a/test/get/git/locked_revision_without_repo_test.dart b/test/get/git/locked_revision_without_repo_test.dart
index 49c1a11..c00c730 100644
--- a/test/get/git/locked_revision_without_repo_test.dart
+++ b/test/get/git/locked_revision_without_repo_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
diff --git a/test/get/git/path_test.dart b/test/get/git/path_test.dart
index 8bbd9e7..49607a1 100644
--- a/test/get/git/path_test.dart
+++ b/test/get/git/path_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:pub/src/lock_file.dart';
@@ -80,7 +78,7 @@
     final lockFile = LockFile.load(
         p.join(d.sandbox, appPath, 'pubspec.lock'), SourceRegistry());
 
-    expect(lockFile.packages['sub'].description['path'], 'sub/dir%25',
+    expect(lockFile.packages['sub']!.description['path'], 'sub/dir%25',
         reason: 'use uris to specify the path relative to the repo');
   });
 
@@ -124,7 +122,7 @@
     final lockFile = LockFile.load(
         p.join(d.sandbox, appPath, 'pubspec.lock'), SourceRegistry());
 
-    expect(lockFile.packages['sub'].description['path'], 'sub/dir%25',
+    expect(lockFile.packages['sub']!.description['path'], 'sub/dir%25',
         reason: 'use uris to specify the path relative to the repo');
   });
 
diff --git a/test/get/git/require_pubspec_name_test.dart b/test/get/git/require_pubspec_name_test.dart
index e0815b2..adc31e4 100644
--- a/test/get/git/require_pubspec_name_test.dart
+++ b/test/get/git/require_pubspec_name_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/get/git/require_pubspec_test.dart b/test/get/git/require_pubspec_test.dart
index fb1dd56..0f75c75 100644
--- a/test/get/git/require_pubspec_test.dart
+++ b/test/get/git/require_pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/get/git/stay_locked_if_compatible_test.dart b/test/get/git/stay_locked_if_compatible_test.dart
index 615a11b..d7f6eb9 100644
--- a/test/get/git/stay_locked_if_compatible_test.dart
+++ b/test/get/git/stay_locked_if_compatible_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/get/git/unlock_if_incompatible_test.dart b/test/get/git/unlock_if_incompatible_test.dart
index 1a97136..61b60e6 100644
--- a/test/get/git/unlock_if_incompatible_test.dart
+++ b/test/get/git/unlock_if_incompatible_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/get/hosted/avoid_network_requests_test.dart b/test/get/hosted/avoid_network_requests_test.dart
index 4a0cd90..8778ae6 100644
--- a/test/get/hosted/avoid_network_requests_test.dart
+++ b/test/get/hosted/avoid_network_requests_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,14 +9,13 @@
 
 void main() {
   test('only requests versions that are needed during solving', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '1.1.0');
-      builder.serve('foo', '1.2.0');
-      builder.serve('bar', '1.0.0');
-      builder.serve('bar', '1.1.0');
-      builder.serve('bar', '1.2.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '1.1.0')
+      ..serve('foo', '1.2.0')
+      ..serve('bar', '1.0.0')
+      ..serve('bar', '1.1.0')
+      ..serve('bar', '1.2.0');
 
     await d.appDir({'foo': 'any'}).create();
 
diff --git a/test/get/hosted/cached_pubspec_test.dart b/test/get/hosted/cached_pubspec_test.dart
index c4711c8..beb4e16 100644
--- a/test/get/hosted/cached_pubspec_test.dart
+++ b/test/get/hosted/cached_pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,7 +9,8 @@
 
 void main() {
   test('does not request a pubspec for a cached package', () async {
-    await servePackages((builder) => builder.serve('foo', '1.2.3'));
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
 
     await d.appDir({'foo': '1.2.3'}).create();
 
@@ -20,7 +19,7 @@
 
     // Clear the cache. We don't care about anything that was served during
     // the initial get.
-    globalServer.requestedPaths.clear();
+    server.requestedPaths.clear();
 
     await d.cacheDir({'foo': '1.2.3'}).validate();
     await d.appPackagesFile({'foo': '1.2.3'}).validate();
@@ -29,7 +28,7 @@
     await pubGet();
 
     // The get should not have requested the pubspec since it's local already.
-    expect(globalServer.requestedPaths,
+    expect(server.requestedPaths,
         isNot(contains('packages/foo/versions/1.2.3.yaml')));
   });
 }
diff --git a/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart b/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart
index c635399..00b2444 100644
--- a/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart
+++ b/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -13,12 +11,11 @@
   test(
       "doesn't upgrade dependencies whose constraints have been "
       'removed', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'shared_dep': 'any'});
-      builder.serve('bar', '1.0.0', deps: {'shared_dep': '<2.0.0'});
-      builder.serve('shared_dep', '1.0.0');
-      builder.serve('shared_dep', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'shared_dep': 'any'})
+      ..serve('bar', '1.0.0', deps: {'shared_dep': '<2.0.0'})
+      ..serve('shared_dep', '1.0.0')
+      ..serve('shared_dep', '2.0.0');
 
     await d.appDir({'foo': 'any', 'bar': 'any'}).create();
 
diff --git a/test/get/hosted/does_no_network_requests_when_possible_test.dart b/test/get/hosted/does_no_network_requests_when_possible_test.dart
index bca2c4d..ea1f4a7 100644
--- a/test/get/hosted/does_no_network_requests_when_possible_test.dart
+++ b/test/get/hosted/does_no_network_requests_when_possible_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
 
 void main() {
   test('does not request versions if the lockfile is up to date', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '1.1.0');
-      builder.serve('foo', '1.2.0');
-    });
+    final server = await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '1.1.0')
+      ..serve('foo', '1.2.0');
 
     await d.appDir({'foo': 'any'}).create();
 
@@ -24,7 +21,7 @@
 
     // Clear the cache. We don't care about anything that was served during
     // the initial get.
-    globalServer.requestedPaths.clear();
+    server.requestedPaths.clear();
 
     // Run the solver again now that it's cached.
     await pubGet();
@@ -34,6 +31,6 @@
 
     // The get should not have done any network requests since the lock file is
     // up to date.
-    expect(globalServer.requestedPaths, isEmpty);
+    expect(server.requestedPaths, isEmpty);
   });
 }
diff --git a/test/get/hosted/explain_bad_hosted_url_test.dart b/test/get/hosted/explain_bad_hosted_url_test.dart
index 6de6860..feebf67 100644
--- a/test/get/hosted/explain_bad_hosted_url_test.dart
+++ b/test/get/hosted/explain_bad_hosted_url_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -34,11 +32,12 @@
   });
 
   test('Allows PUB_HOSTED_URL to end with a slash', () async {
-    await servePackages((b) => b.serve('foo', '1.0.0'));
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
     await d.appDir({'foo': 'any'}).create();
 
     await pubGet(
-      environment: {'PUB_HOSTED_URL': '${globalPackageServer.url}/'},
+      environment: {'PUB_HOSTED_URL': '${globalServer.url}/'},
     );
   });
 }
diff --git a/test/get/hosted/get_stress_test.dart b/test/get/hosted/get_stress_test.dart
index 8a05104..86a8da9 100644
--- a/test/get/hosted/get_stress_test.dart
+++ b/test/get/hosted/get_stress_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,12 +9,11 @@
 
 void main() {
   test('gets more than 16 packages from a pub server', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.3');
-      for (var i = 0; i < 20; i++) {
-        builder.serve('pkg$i', '1.$i.0');
-      }
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
+    for (var i = 0; i < 20; i++) {
+      server.serve('pkg$i', '1.$i.0');
+    }
 
     await d.appDir({
       'foo': '1.2.3',
diff --git a/test/get/hosted/get_test.dart b/test/get/hosted/get_test.dart
index 13f9ad8..30dd4b8 100644
--- a/test/get/hosted/get_test.dart
+++ b/test/get/hosted/get_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:pub/src/io.dart';
@@ -15,7 +13,8 @@
 
 void main() {
   test('gets a package from a pub server', () async {
-    await servePackages((builder) => builder.serve('foo', '1.2.3'));
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
 
     await d.appDir({'foo': '1.2.3'}).create();
 
@@ -26,7 +25,7 @@
   });
 
   test('URL encodes the package name', () async {
-    await serveNoPackages();
+    await servePackages();
 
     await d.appDir({'bad name!': '1.2.3'}).create();
 
@@ -43,11 +42,10 @@
   test('gets a package from a non-default pub server', () async {
     // Make the default server serve errors. Only the custom server should
     // be accessed.
-    await serveErrors();
+    (await servePackages()).serveErrors();
 
-    var server = await PackageServer.start((builder) {
-      builder.serve('foo', '1.2.3');
-    });
+    var server = await startPackageServer();
+    server.serve('foo', '1.2.3');
 
     await d.appDir({
       'foo': {
@@ -63,14 +61,15 @@
   });
 
   group('categorizes dependency types in the lockfile', () {
-    setUp(() => servePackages((builder) {
-          builder.serve('foo', '1.2.3', deps: {'bar': 'any'});
-          builder.serve('bar', '1.2.3');
-          builder.serve('baz', '1.2.3', deps: {'qux': 'any'});
-          builder.serve('qux', '1.2.3');
-          builder.serve('zip', '1.2.3', deps: {'zap': 'any'});
-          builder.serve('zap', '1.2.3');
-        }));
+    setUp(() async {
+      await servePackages()
+        ..serve('foo', '1.2.3', deps: {'bar': 'any'})
+        ..serve('bar', '1.2.3')
+        ..serve('baz', '1.2.3', deps: {'qux': 'any'})
+        ..serve('qux', '1.2.3')
+        ..serve('zip', '1.2.3', deps: {'zap': 'any'})
+        ..serve('zap', '1.2.3');
+    });
 
     test('for main, dev, and overridden dependencies', () async {
       await d.dir(appPath, [
diff --git a/test/get/hosted/get_transitive_test.dart b/test/get/hosted/get_transitive_test.dart
index 4640c44..74635bc 100644
--- a/test/get/hosted/get_transitive_test.dart
+++ b/test/get/hosted/get_transitive_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,12 +9,11 @@
 
 void main() {
   test('gets packages transitively from a pub server', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.3', deps: {'bar': '2.0.4'});
-      builder.serve('bar', '2.0.3');
-      builder.serve('bar', '2.0.4');
-      builder.serve('bar', '2.0.5');
-    });
+    await servePackages()
+      ..serve('foo', '1.2.3', deps: {'bar': '2.0.4'})
+      ..serve('bar', '2.0.3')
+      ..serve('bar', '2.0.4')
+      ..serve('bar', '2.0.5');
 
     await d.appDir({'foo': '1.2.3'}).create();
 
diff --git a/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart b/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart
index 14f1d98..0d75f95 100644
--- a/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart
+++ b/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -14,12 +12,11 @@
   test(
       'gets a dependency with broken dev dependencies from a pub '
       'server', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.3', pubspec: {
-        'dev_dependencies': {
-          'busted': {'not a real source': null}
-        }
-      });
+    final server = await servePackages();
+    server.serve('foo', '1.2.3', pubspec: {
+      'dev_dependencies': {
+        'busted': {'not a real source': null}
+      }
     });
 
     await d.appDir({'foo': '1.2.3'}).create();
diff --git a/test/get/hosted/resolve_constraints_test.dart b/test/get/hosted/resolve_constraints_test.dart
index cf3d434..c9c73d2 100644
--- a/test/get/hosted/resolve_constraints_test.dart
+++ b/test/get/hosted/resolve_constraints_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,13 +9,12 @@
 
 void main() {
   test('resolves version constraints from a pub server', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.3', deps: {'baz': '>=2.0.0'});
-      builder.serve('bar', '2.3.4', deps: {'baz': '<3.0.0'});
-      builder.serve('baz', '2.0.3');
-      builder.serve('baz', '2.0.4');
-      builder.serve('baz', '3.0.1');
-    });
+    await servePackages()
+      ..serve('foo', '1.2.3', deps: {'baz': '>=2.0.0'})
+      ..serve('bar', '2.3.4', deps: {'baz': '<3.0.0'})
+      ..serve('baz', '2.0.3')
+      ..serve('baz', '2.0.4')
+      ..serve('baz', '3.0.1');
 
     await d.appDir({'foo': 'any', 'bar': 'any'}).create();
 
diff --git a/test/get/hosted/resolve_with_retracted_package_versions_test.dart b/test/get/hosted/resolve_with_retracted_package_versions_test.dart
index af714cf..efd3a0a 100644
--- a/test/get/hosted/resolve_with_retracted_package_versions_test.dart
+++ b/test/get/hosted/resolve_with_retracted_package_versions_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 
 import 'package:pub/src/io.dart';
@@ -15,14 +13,13 @@
 
 void main() {
   test('Do not consider retracted packages', () async {
-    await servePackages((builder) => builder
+    final server = await servePackages()
       ..serve('foo', '1.0.0', deps: {'bar': '^1.0.0'})
       ..serve('bar', '1.0.0')
-      ..serve('bar', '1.1.0'));
+      ..serve('bar', '1.1.0');
     await d.appDir({'foo': '1.0.0'}).create();
 
-    globalPackageServer
-        .add((builder) => builder..retractPackageVersion('bar', '1.1.0'));
+    server.retractPackageVersion('bar', '1.1.0');
     await pubGet();
 
     await d.cacheDir({'foo': '1.0.0', 'bar': '1.0.0'}).validate();
@@ -30,13 +27,12 @@
   });
 
   test('Error when the only available package version is retracted', () async {
-    await servePackages((builder) => builder
+    final server = await servePackages()
       ..serve('foo', '1.0.0', deps: {'bar': '^1.0.0'})
-      ..serve('bar', '1.0.0'));
+      ..serve('bar', '1.0.0');
     await d.appDir({'foo': '1.0.0'}).create();
 
-    globalPackageServer
-        .add((builder) => builder..retractPackageVersion('bar', '1.0.0'));
+    server.retractPackageVersion('bar', '1.0.0');
     await pubGet(
         error:
             '''Because every version of foo depends on bar ^1.0.0 which doesn't match any versions, foo is forbidden. 
@@ -49,28 +45,27 @@
   // In this case we expect a newer version to be published at some point which
   // will then cause pub upgrade to choose that one.
   test('Allow retracted version when it was already in pubspec.lock', () async {
-    await servePackages((builder) => builder
+    final server = await servePackages()
       ..serve('foo', '1.0.0', deps: {'bar': '^1.0.0'})
       ..serve('bar', '1.0.0')
-      ..serve('bar', '1.1.0'));
+      ..serve('bar', '1.1.0');
     await d.appDir({'foo': '1.0.0'}).create();
 
     await pubGet();
     await d.cacheDir({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
     await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
 
-    globalPackageServer
-        .add((builder) => builder..retractPackageVersion('bar', '1.1.0'));
+    server.retractPackageVersion('bar', '1.1.0');
     await pubUpgrade();
     await d.cacheDir({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
     await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
 
-    globalPackageServer.add((builder) => builder..serve('bar', '2.0.0'));
+    server.serve('bar', '2.0.0');
     await pubUpgrade();
     await d.cacheDir({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
     await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
 
-    globalPackageServer.add((builder) => builder..serve('bar', '1.2.0'));
+    server.serve('bar', '1.2.0');
     await pubUpgrade();
     await d.cacheDir({'foo': '1.0.0', 'bar': '1.2.0'}).validate();
     await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.2.0'}).validate();
@@ -78,10 +73,11 @@
 
   test('Offline versions of pub commands also handle retracted packages',
       () async {
+    final server = await servePackages();
     await populateCache({
       'foo': ['1.0.0'],
       'bar': ['1.0.0', '1.1.0']
-    });
+    }, server);
 
     await d.cacheDir({
       'foo': '1.0.0',
@@ -89,18 +85,17 @@
     }).validate();
 
     final barVersionsCache =
-        p.join(globalPackageServer.cachingPath, '.cache', 'bar-versions.json');
+        p.join(globalServer.cachingPath, '.cache', 'bar-versions.json');
     expect(fileExists(barVersionsCache), isTrue);
     deleteEntry(barVersionsCache);
 
-    globalPackageServer
-        .add((builder) => builder..retractPackageVersion('bar', '1.1.0'));
+    server.retractPackageVersion('bar', '1.1.0');
     await pubGet();
 
     await d.cacheDir({'bar': '1.1.0'}).validate();
 
     // Now serve only errors - to validate we are truly offline.
-    await serveErrors();
+    server.serveErrors();
 
     await d.appDir({'foo': '1.0.0', 'bar': '^1.0.0'}).create();
 
@@ -119,11 +114,10 @@
   });
 
   test('Allow retracted version when pinned in dependency_overrides', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '2.0.0');
-      builder.serve('foo', '3.0.0');
-    });
+    final server = await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '2.0.0')
+      ..serve('foo', '3.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -133,8 +127,7 @@
       })
     ]).create();
 
-    globalPackageServer
-        .add((builder) => builder..retractPackageVersion('foo', '2.0.0'));
+    server.retractPackageVersion('foo', '2.0.0');
 
     await pubGet();
     await d.appPackagesFile({'foo': '2.0.0'}).validate();
@@ -142,19 +135,16 @@
 
   test('Prefer retracted version in dependency_overrides over pubspec.lock',
       () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '2.0.0');
-      builder.serve('foo', '3.0.0');
-    });
+    final server = await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '2.0.0')
+      ..serve('foo', '3.0.0');
 
     await d.appDir({'foo': 'any'}).create();
     await pubGet();
 
-    globalPackageServer
-        .add((builder) => builder..retractPackageVersion('foo', '2.0.0'));
-    globalPackageServer
-        .add((builder) => builder..retractPackageVersion('foo', '3.0.0'));
+    server.retractPackageVersion('foo', '2.0.0');
+    server.retractPackageVersion('foo', '3.0.0');
 
     await pubUpgrade();
     await d.appPackagesFile({'foo': '3.0.0'}).validate();
diff --git a/test/get/hosted/stay_locked_if_compatible_test.dart b/test/get/hosted/stay_locked_if_compatible_test.dart
index 588f395..bb5e63a 100644
--- a/test/get/hosted/stay_locked_if_compatible_test.dart
+++ b/test/get/hosted/stay_locked_if_compatible_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -13,7 +11,8 @@
   test(
       "doesn't upgrade a locked pub server package with a new "
       'compatible constraint', () async {
-    await servePackages((builder) => builder.serve('foo', '1.0.0'));
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
 
     await d.appDir({'foo': 'any'}).create();
 
@@ -21,7 +20,7 @@
 
     await d.appPackagesFile({'foo': '1.0.0'}).validate();
 
-    globalPackageServer.add((builder) => builder.serve('foo', '1.0.1'));
+    server.serve('foo', '1.0.1');
 
     await d.appDir({'foo': '>=1.0.0'}).create();
 
diff --git a/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart b/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart
index 743c5f4..dbe6039 100644
--- a/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart
+++ b/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -13,11 +11,10 @@
   test(
       "doesn't unlock dependencies if a new dependency is already "
       'satisfied', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
-      builder.serve('bar', '1.0.0', deps: {'baz': '<2.0.0'});
-      builder.serve('baz', '1.0.0');
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
+    server.serve('bar', '1.0.0', deps: {'baz': '<2.0.0'});
+    server.serve('baz', '1.0.0');
 
     await d.appDir({'foo': 'any'}).create();
 
@@ -26,12 +23,10 @@
     await d.appPackagesFile(
         {'foo': '1.0.0', 'bar': '1.0.0', 'baz': '1.0.0'}).validate();
 
-    globalPackageServer.add((builder) {
-      builder.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
-      builder.serve('bar', '2.0.0', deps: {'baz': '<3.0.0'});
-      builder.serve('baz', '2.0.0');
-      builder.serve('newdep', '2.0.0', deps: {'baz': '>=1.0.0'});
-    });
+    server.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
+    server.serve('bar', '2.0.0', deps: {'baz': '<3.0.0'});
+    server.serve('baz', '2.0.0');
+    server.serve('newdep', '2.0.0', deps: {'baz': '>=1.0.0'});
 
     await d.appDir({'foo': 'any', 'newdep': 'any'}).create();
 
diff --git a/test/get/hosted/stay_locked_test.dart b/test/get/hosted/stay_locked_test.dart
index c5c11ff..134e8b5 100644
--- a/test/get/hosted/stay_locked_test.dart
+++ b/test/get/hosted/stay_locked_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -15,7 +13,8 @@
   test(
       'keeps a hosted package locked to the version in the '
       'lockfile', () async {
-    await servePackages((builder) => builder.serve('foo', '1.0.0'));
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
 
     await d.appDir({'foo': 'any'}).create();
 
@@ -28,7 +27,7 @@
     deleteEntry(path.join(d.sandbox, packageConfigFilePath));
 
     // Start serving a newer package as well.
-    globalPackageServer.add((builder) => builder.serve('foo', '1.0.1'));
+    server.serve('foo', '1.0.1');
 
     // This shouldn't upgrade the foo dependency due to the lockfile.
     await pubGet();
diff --git a/test/get/hosted/unlock_if_incompatible_test.dart b/test/get/hosted/unlock_if_incompatible_test.dart
index f9f8748..11bf909 100644
--- a/test/get/hosted/unlock_if_incompatible_test.dart
+++ b/test/get/hosted/unlock_if_incompatible_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -13,14 +11,15 @@
   test(
       'upgrades a locked pub server package with a new incompatible '
       'constraint', () async {
-    await servePackages((builder) => builder.serve('foo', '1.0.0'));
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
 
     await d.appDir({'foo': 'any'}).create();
 
     await pubGet();
 
     await d.appPackagesFile({'foo': '1.0.0'}).validate();
-    globalPackageServer.add((builder) => builder.serve('foo', '1.0.1'));
+    server.serve('foo', '1.0.1');
     await d.appDir({'foo': '>1.0.0'}).create();
 
     await pubGet();
diff --git a/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart b/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart
index feaf478..1cedc5a 100644
--- a/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart
+++ b/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -13,12 +11,12 @@
   test(
       'unlocks dependencies if necessary to ensure that a new '
       'dependency is satisfied', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
-      builder.serve('bar', '1.0.0', deps: {'baz': '<2.0.0'});
-      builder.serve('baz', '1.0.0', deps: {'qux': '<2.0.0'});
-      builder.serve('qux', '1.0.0');
-    });
+    final server = await servePackages();
+
+    server.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
+    server.serve('bar', '1.0.0', deps: {'baz': '<2.0.0'});
+    server.serve('baz', '1.0.0', deps: {'qux': '<2.0.0'});
+    server.serve('qux', '1.0.0');
 
     await d.appDir({'foo': 'any'}).create();
 
@@ -31,13 +29,11 @@
       'qux': '1.0.0'
     }).validate();
 
-    globalPackageServer.add((builder) {
-      builder.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
-      builder.serve('bar', '2.0.0', deps: {'baz': '<3.0.0'});
-      builder.serve('baz', '2.0.0', deps: {'qux': '<3.0.0'});
-      builder.serve('qux', '2.0.0');
-      builder.serve('newdep', '2.0.0', deps: {'baz': '>=1.5.0'});
-    });
+    server.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
+    server.serve('bar', '2.0.0', deps: {'baz': '<3.0.0'});
+    server.serve('baz', '2.0.0', deps: {'qux': '<3.0.0'});
+    server.serve('qux', '2.0.0');
+    server.serve('newdep', '2.0.0', deps: {'baz': '>=1.5.0'});
 
     await d.appDir({'foo': 'any', 'newdep': 'any'}).create();
 
diff --git a/test/get/hosted/unlock_if_version_doesnt_exist_test.dart b/test/get/hosted/unlock_if_version_doesnt_exist_test.dart
index f42e12e..7eb4246 100644
--- a/test/get/hosted/unlock_if_version_doesnt_exist_test.dart
+++ b/test/get/hosted/unlock_if_version_doesnt_exist_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -14,7 +12,8 @@
 void main() {
   test('upgrades a locked pub server package with a nonexistent version',
       () async {
-    await servePackages((builder) => builder.serve('foo', '1.0.0'));
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
 
     await d.appDir({'foo': 'any'}).create();
     await pubGet();
@@ -22,7 +21,9 @@
 
     deleteEntry(p.join(d.sandbox, cachePath));
 
-    globalPackageServer.replace((builder) => builder.serve('foo', '1.0.1'));
+    server.clearPackages();
+    server.serve('foo', '1.0.1');
+
     await pubGet();
     await d.appPackagesFile({'foo': '1.0.1'}).validate();
   });
diff --git a/test/get/hosted/warn_about_discontinued_test.dart b/test/get/hosted/warn_about_discontinued_test.dart
index 76558a0..7057f9b 100644
--- a/test/get/hosted/warn_about_discontinued_test.dart
+++ b/test/get/hosted/warn_about_discontinued_test.dart
@@ -2,13 +2,11 @@
 // 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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
-import 'package:shelf/shelf.dart';
+import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -16,22 +14,22 @@
 
 void main() {
   test('Warns about discontinued dependencies', () async {
-    await servePackages((builder) => builder
-      ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
-      ..serve('transitive', '1.0.0'));
+    final server = await servePackages();
+    server.serve('foo', '1.2.3', deps: {'transitive': 'any'});
+    server.serve('transitive', '1.0.0');
     await d.appDir({'foo': '1.2.3'}).create();
     await pubGet();
 
-    globalPackageServer.add((builder) => builder
+    server
       ..discontinue('foo')
-      ..discontinue('transitive'));
+      ..discontinue('transitive');
     // A pub get straight away will not trigger the warning, as we cache
     // responses for a while.
     await pubGet();
     final fooVersionsCache =
-        p.join(globalPackageServer.cachingPath, '.cache', 'foo-versions.json');
-    final transitiveVersionsCache = p.join(
-        globalPackageServer.cachingPath, '.cache', 'transitive-versions.json');
+        p.join(globalServer.cachingPath, '.cache', 'foo-versions.json');
+    final transitiveVersionsCache =
+        p.join(globalServer.cachingPath, '.cache', 'transitive-versions.json');
     expect(fileExists(fooVersionsCache), isTrue);
     expect(fileExists(transitiveVersionsCache), isTrue);
     deleteEntry(fooVersionsCache);
@@ -48,8 +46,9 @@
     c['_fetchedAt'] =
         DateTime.now().subtract(Duration(days: 5)).toIso8601String();
     writeTextFile(fooVersionsCache, json.encode(c));
-    globalPackageServer
-        .add((builder) => builder.discontinue('foo', replacementText: 'bar'));
+
+    server.discontinue('foo', replacementText: 'bar');
+
     await pubGet(output: '''
 Resolving dependencies...
   foo 1.2.3 (discontinued replaced by bar)
@@ -69,7 +68,7 @@
 Got dependencies!''');
     // Test that --offline won't try to access the server for retrieving the
     // status.
-    await serveErrors();
+    server.serveErrors();
     await pubGet(args: ['--offline'], output: '''
 Resolving dependencies...
   foo 1.2.3 (discontinued replaced by bar)
@@ -83,9 +82,10 @@
   });
 
   test('Warns about discontinued dev dependencies', () async {
-    await servePackages((builder) => builder
+    final builder = await servePackages();
+    builder
       ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
-      ..serve('transitive', '1.0.0'));
+      ..serve('transitive', '1.0.0');
 
     await d.dir(appPath, [
       d.file('pubspec.yaml', '''
@@ -100,14 +100,14 @@
     ]).create();
     await pubGet();
 
-    globalPackageServer.add((builder) => builder
+    builder
       ..discontinue('foo')
-      ..discontinue('transitive'));
+      ..discontinue('transitive');
     // A pub get straight away will not trigger the warning, as we cache
     // responses for a while.
     await pubGet();
     final fooVersionsCache =
-        p.join(globalPackageServer.cachingPath, '.cache', 'foo-versions.json');
+        p.join(globalServer.cachingPath, '.cache', 'foo-versions.json');
     expect(fileExists(fooVersionsCache), isTrue);
     deleteEntry(fooVersionsCache);
     // We warn only about the direct dependency here:
@@ -122,8 +122,7 @@
     c['_fetchedAt'] =
         DateTime.now().subtract(Duration(days: 5)).toIso8601String();
     writeTextFile(fooVersionsCache, json.encode(c));
-    globalPackageServer
-        .add((builder) => builder.discontinue('foo', replacementText: 'bar'));
+    builder.discontinue('foo', replacementText: 'bar');
     await pubGet(output: '''
 Resolving dependencies...
   foo 1.2.3 (discontinued replaced by bar)
@@ -143,7 +142,7 @@
 Got dependencies!''');
     // Test that --offline won't try to access the server for retrieving the
     // status.
-    await serveErrors();
+    builder.serveErrors();
     await pubGet(args: ['--offline'], output: '''
 Resolving dependencies...
   foo 1.2.3 (discontinued replaced by bar)
@@ -156,17 +155,17 @@
   });
 
   test('get does not fail when status listing fails', () async {
-    await servePackages((builder) => builder..serve('foo', '1.2.3'));
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
     await d.appDir({'foo': '1.2.3'}).create();
     await pubGet();
     final fooVersionsCache =
-        p.join(globalPackageServer.cachingPath, '.cache', 'foo-versions.json');
+        p.join(globalServer.cachingPath, '.cache', 'foo-versions.json');
     expect(fileExists(fooVersionsCache), isTrue);
     deleteEntry(fooVersionsCache);
     // Serve 400 on all requests.
-    globalPackageServer.extraHandlers
-      ..clear()
-      ..[RegExp('.*')] = (request) async => Response(400);
+    globalServer.handle(RegExp('.*'),
+        (shelf.Request request) => shelf.Response.notFound('Not found'));
 
     /// Even if we fail to get status we still report success if versions don't unlock.
     await pubGet();
diff --git a/test/get/hosted/warn_about_retracted_package_test.dart b/test/get/hosted/warn_about_retracted_package_test.dart
index 5258d7c..2336c7f 100644
--- a/test/get/hosted/warn_about_retracted_package_test.dart
+++ b/test/get/hosted/warn_about_retracted_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -13,38 +11,36 @@
 
 void main() {
   test('Report retracted packages', () async {
-    await servePackages((builder) => builder
+    final server = await servePackages()
       ..serve('foo', '1.0.0', deps: {'bar': 'any'})
-      ..serve('bar', '1.0.0'));
+      ..serve('bar', '1.0.0');
     await d.appDir({'foo': '1.0.0'}).create();
 
     await pubGet();
 
-    globalPackageServer
-        .add((builder) => builder..retractPackageVersion('bar', '1.0.0'));
+    server.retractPackageVersion('bar', '1.0.0');
     // Delete the cache to trigger the report.
     final barVersionsCache =
-        p.join(globalPackageServer.cachingPath, '.cache', 'bar-versions.json');
+        p.join(server.cachingPath, '.cache', 'bar-versions.json');
     expect(fileExists(barVersionsCache), isTrue);
     deleteEntry(barVersionsCache);
     await pubGet(output: contains('bar 1.0.0 (retracted)'));
   });
 
   test('Report retracted packages with newer version available', () async {
-    await servePackages((builder) => builder
+    final server = await servePackages()
       ..serve('foo', '1.0.0', deps: {'bar': '^1.0.0'})
       ..serve('bar', '1.0.0')
       ..serve('bar', '2.0.0')
-      ..serve('bar', '2.0.1-pre'));
+      ..serve('bar', '2.0.1-pre');
     await d.appDir({'foo': '1.0.0'}).create();
 
     await pubGet();
 
-    globalPackageServer
-        .add((builder) => builder..retractPackageVersion('bar', '1.0.0'));
+    server.retractPackageVersion('bar', '1.0.0');
     // Delete the cache to trigger the report.
     final barVersionsCache =
-        p.join(globalPackageServer.cachingPath, '.cache', 'bar-versions.json');
+        p.join(server.cachingPath, '.cache', 'bar-versions.json');
     expect(fileExists(barVersionsCache), isTrue);
     deleteEntry(barVersionsCache);
     await pubGet(output: contains('bar 1.0.0 (retracted, 2.0.0 available)'));
@@ -52,19 +48,18 @@
 
   test('Report retracted packages with newer prerelease version available',
       () async {
-    await servePackages((builder) => builder
+    final server = await servePackages()
       ..serve('foo', '1.0.0', deps: {'bar': '^1.0.0-pre'})
       ..serve('bar', '1.0.0-pre')
-      ..serve('bar', '2.0.1-pre'));
+      ..serve('bar', '2.0.1-pre');
     await d.appDir({'foo': '1.0.0'}).create();
 
     await pubGet();
 
-    globalPackageServer
-        .add((builder) => builder..retractPackageVersion('bar', '1.0.0-pre'));
+    server.retractPackageVersion('bar', '1.0.0-pre');
     // Delete the cache to trigger the report.
     final barVersionsCache =
-        p.join(globalPackageServer.cachingPath, '.cache', 'bar-versions.json');
+        p.join(server.cachingPath, '.cache', 'bar-versions.json');
     expect(fileExists(barVersionsCache), isTrue);
     deleteEntry(barVersionsCache);
     await pubGet(
diff --git a/test/get/package_name_test.dart b/test/get/package_name_test.dart
index f385cfe..46ca386 100644
--- a/test/get/package_name_test.dart
+++ b/test/get/package_name_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/get/path/absolute_path_test.dart b/test/get/path/absolute_path_test.dart
index 7304f52..0fc987a 100644
--- a/test/get/path/absolute_path_test.dart
+++ b/test/get/path/absolute_path_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
diff --git a/test/get/path/absolute_symlink_test.dart b/test/get/path/absolute_symlink_test.dart
index b0cd147..1a2d912 100644
--- a/test/get/path/absolute_symlink_test.dart
+++ b/test/get/path/absolute_symlink_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
diff --git a/test/get/path/empty_pubspec_test.dart b/test/get/path/empty_pubspec_test.dart
index 5b94d70..0f9843f 100644
--- a/test/get/path/empty_pubspec_test.dart
+++ b/test/get/path/empty_pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
diff --git a/test/get/path/no_pubspec_test.dart b/test/get/path/no_pubspec_test.dart
index d12477d..d328f25 100644
--- a/test/get/path/no_pubspec_test.dart
+++ b/test/get/path/no_pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
diff --git a/test/get/path/nonexistent_dir_test.dart b/test/get/path/nonexistent_dir_test.dart
index 993590f..7616087 100644
--- a/test/get/path/nonexistent_dir_test.dart
+++ b/test/get/path/nonexistent_dir_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
diff --git a/test/get/path/path_is_file_test.dart b/test/get/path/path_is_file_test.dart
index 119a794..6fafd82 100644
--- a/test/get/path/path_is_file_test.dart
+++ b/test/get/path/path_is_file_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
diff --git a/test/get/path/relative_path_test.dart b/test/get/path/relative_path_test.dart
index a1d7437..4255d49 100644
--- a/test/get/path/relative_path_test.dart
+++ b/test/get/path/relative_path_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/lock_file.dart';
 import 'package:pub/src/source_registry.dart';
@@ -93,7 +91,7 @@
 
     var lockfilePath = path.join(d.sandbox, appPath, 'pubspec.lock');
     var lockfile = LockFile.load(lockfilePath, SourceRegistry());
-    var description = lockfile.packages['foo'].description;
+    var description = lockfile.packages['foo']!.description;
 
     expect(description['relative'], isTrue);
     expect(description['path'], path.join(d.sandbox, 'foo'));
diff --git a/test/get/path/relative_symlink_test.dart b/test/get/path/relative_symlink_test.dart
index e48ba41..af7185b 100644
--- a/test/get/path/relative_symlink_test.dart
+++ b/test/get/path/relative_symlink_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 // Pub uses NTFS junction points to create links in the packages directory.
 // These (unlike the symlinks that are supported in Vista and later) do not
 // support relative paths. So this test, by design, will not pass on Windows.
diff --git a/test/get/path/shared_dependency_symlink_test.dart b/test/get/path/shared_dependency_symlink_test.dart
index 7d1369c..46a78c6 100644
--- a/test/get/path/shared_dependency_symlink_test.dart
+++ b/test/get/path/shared_dependency_symlink_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 
 import 'package:test/test.dart';
diff --git a/test/get/path/shared_dependency_test.dart b/test/get/path/shared_dependency_test.dart
index 3525e6b..7072221 100644
--- a/test/get/path/shared_dependency_test.dart
+++ b/test/get/path/shared_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/get/preserve_lock_file_line_endings_test.dart b/test/get/preserve_lock_file_line_endings_test.dart
index 8f6dc26..bfd015a 100644
--- a/test/get/preserve_lock_file_line_endings_test.dart
+++ b/test/get/preserve_lock_file_line_endings_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/entrypoint.dart';
 import 'package:test/test.dart';
diff --git a/test/get/sdk_constraint_required_test.dart b/test/get/sdk_constraint_required_test.dart
index 3cb0f86..1b6fbc5 100644
--- a/test/get/sdk_constraint_required_test.dart
+++ b/test/get/sdk_constraint_required_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/get/switch_source_test.dart b/test/get/switch_source_test.dart
index 2dee748..ffbf8b4 100644
--- a/test/get/switch_source_test.dart
+++ b/test/get/switch_source_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -11,7 +9,8 @@
 
 void main() {
   test('re-gets a package if its source has changed', () async {
-    await servePackages((builder) => builder.serve('foo', '1.2.3'));
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
 
     await d.dir('foo',
         [d.libDir('foo', 'foo 0.0.1'), d.libPubspec('foo', '0.0.1')]).create();
diff --git a/test/get/with_empty_environment_test.dart b/test/get/with_empty_environment_test.dart
new file mode 100644
index 0000000..30768c4
--- /dev/null
+++ b/test/get/with_empty_environment_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2021, 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 'dart:io';
+
+import 'package:test/test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+void main() {
+  test(r'runs even with an empty environment (eg. no $HOME)', () async {
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
+
+    await d.appDir({'foo': 'any'}).create();
+
+    await pubGet(environment: {
+      '_PUB_TEST_CONFIG_DIR': null,
+      if (Platform.isWindows) ...{
+        'SYSTEMROOT': Platform.environment['SYSTEMROOT'],
+        'TMP': Platform.environment['TMP'],
+      },
+    }, includeParentEnvironment: false);
+  });
+}
diff --git a/test/global/activate/activate_git_after_hosted_test.dart b/test/global/activate/activate_git_after_hosted_test.dart
index 5dd32c1..c553041 100644
--- a/test/global/activate/activate_git_after_hosted_test.dart
+++ b/test/global/activate/activate_git_after_hosted_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -13,11 +11,10 @@
   test('activating a Git package deactivates the hosted one', () async {
     ensureGit();
 
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
+    ]);
 
     await d.git('foo.git', [
       d.libPubspec('foo', '1.0.0'),
diff --git a/test/global/activate/activate_hosted_after_git_test.dart b/test/global/activate/activate_hosted_after_git_test.dart
index a86b2cc..58c65fb 100644
--- a/test/global/activate/activate_hosted_after_git_test.dart
+++ b/test/global/activate/activate_hosted_after_git_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
 
 void main() {
   test('activating a hosted package deactivates the Git one', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '2.0.0', contents: [
-        d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '2.0.0', contents: [
+      d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
+    ]);
 
     await d.git('foo.git', [
       d.libPubspec('foo', '1.0.0'),
diff --git a/test/global/activate/activate_hosted_after_path_test.dart b/test/global/activate/activate_hosted_after_path_test.dart
index 1e01735..4cd753f 100644
--- a/test/global/activate/activate_hosted_after_path_test.dart
+++ b/test/global/activate/activate_hosted_after_path_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -13,11 +11,10 @@
 
 void main() {
   test('activating a hosted package deactivates the path one', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '2.0.0', contents: [
-        d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '2.0.0', contents: [
+      d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
+    ]);
 
     await d.dir('foo', [
       d.libPubspec('foo', '1.0.0'),
diff --git a/test/global/activate/activate_hosted_twice_test.dart b/test/global/activate/activate_hosted_twice_test.dart
index 50ed807..9baed5b 100644
--- a/test/global/activate/activate_hosted_twice_test.dart
+++ b/test/global/activate/activate_hosted_twice_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,7 +9,8 @@
 
 void main() {
   test('activating a hosted package twice will not precompile', () async {
-    await servePackages((builder) => builder
+    final server = await servePackages();
+    server
       ..serve('foo', '1.0.0', deps: {
         'bar': 'any'
       }, contents: [
@@ -23,7 +22,7 @@
       ])
       ..serve('bar', '1.0.0', contents: [
         d.dir('lib', [d.file('bar.dart', 'final version = "1.0.0";')])
-      ]));
+      ]);
 
     await runPub(args: ['global', 'activate', 'foo'], output: '''
 Resolving dependencies...
@@ -48,10 +47,9 @@
 
     await runPub(args: ['global', 'activate', 'foo']);
 
-    globalPackageServer
-        .add((builder) => builder.serve('bar', '2.0.0', contents: [
-              d.dir('lib', [d.file('bar.dart', 'final version = "2.0.0";')])
-            ]));
+    server.serve('bar', '2.0.0', contents: [
+      d.dir('lib', [d.file('bar.dart', 'final version = "2.0.0";')])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo'], output: '''
 Package foo is currently active at version 1.0.0.
diff --git a/test/global/activate/activate_path_after_hosted_test.dart b/test/global/activate/activate_path_after_hosted_test.dart
index c73cb01..cfc28fd 100644
--- a/test/global/activate/activate_path_after_hosted_test.dart
+++ b/test/global/activate/activate_path_after_hosted_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -13,11 +11,10 @@
 
 void main() {
   test('activating a hosted package deactivates the path one', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
+    ]);
 
     await d.dir('foo', [
       d.libPubspec('foo', '2.0.0'),
diff --git a/test/global/activate/bad_version_test.dart b/test/global/activate/bad_version_test.dart
index 651c342..c5c4635 100644
--- a/test/global/activate/bad_version_test.dart
+++ b/test/global/activate/bad_version_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/global/activate/cached_package_test.dart b/test/global/activate/cached_package_test.dart
index 7ddcf10..98db402 100644
--- a/test/global/activate/cached_package_test.dart
+++ b/test/global/activate/cached_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
 
 void main() {
   test('can activate an already cached package', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('foo.dart', 'main() => print("hi"); ')])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('foo.dart', 'main() => print("hi"); ')])
+    ]);
 
     await runPub(args: ['cache', 'add', 'foo']);
 
diff --git a/test/global/activate/constraint_test.dart b/test/global/activate/constraint_test.dart
index b712d00..23386c0 100644
--- a/test/global/activate/constraint_test.dart
+++ b/test/global/activate/constraint_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,12 +9,11 @@
 
 void main() {
   test('chooses the highest version that matches the constraint', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '1.0.1');
-      builder.serve('foo', '1.1.0');
-      builder.serve('foo', '1.2.3');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '1.0.1')
+      ..serve('foo', '1.1.0')
+      ..serve('foo', '1.2.3');
 
     await runPub(args: ['global', 'activate', 'foo', '<1.1.0']);
 
diff --git a/test/global/activate/constraint_with_path_test.dart b/test/global/activate/constraint_with_path_test.dart
index 1a5beb7..359cd60 100644
--- a/test/global/activate/constraint_with_path_test.dart
+++ b/test/global/activate/constraint_with_path_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/global/activate/custom_hosted_url_test.dart b/test/global/activate/custom_hosted_url_test.dart
index 7443887..8b2f0fc 100644
--- a/test/global/activate/custom_hosted_url_test.dart
+++ b/test/global/activate/custom_hosted_url_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../test_pub.dart';
@@ -11,22 +9,21 @@
 void main() {
   test('activating a package from a custom pub server', () async {
     // The default pub server (i.e. pub.dartlang.org).
-    await servePackages((builder) {
-      builder.serve('baz', '1.0.0');
-    });
+    final server = await servePackages();
+    server.serve('baz', '1.0.0');
 
     // The custom pub server.
-    final customServer = await PackageServer.start((builder) {
-      Map<String, dynamic> hostedDep(String name, String constraint) => {
-            'hosted': {
-              'url': builder.serverUrl,
-              'name': name,
-            },
-            'version': constraint,
-          };
-      builder.serve('foo', '1.0.0', deps: {'bar': hostedDep('bar', 'any')});
-      builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
-    });
+    final customServer = await startPackageServer();
+    Map<String, dynamic> hostedDep(String name, String constraint) => {
+          'hosted': {
+            'url': customServer.url,
+            'name': name,
+          },
+          'version': constraint,
+        };
+
+    customServer.serve('foo', '1.0.0', deps: {'bar': hostedDep('bar', 'any')});
+    customServer.serve('bar', '1.0.0', deps: {'baz': 'any'});
 
     await runPub(
         args: ['global', 'activate', 'foo', '-u', customServer.url],
diff --git a/test/global/activate/different_version_test.dart b/test/global/activate/different_version_test.dart
index 61ba228..8406b92 100644
--- a/test/global/activate/different_version_test.dart
+++ b/test/global/activate/different_version_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -13,14 +11,13 @@
   test(
       "discards the previous active version if it doesn't match the "
       'constraint', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('foo.dart', 'main() => print("hi"); ')])
+    await servePackages()
+      ..serve('foo', '1.0.0', contents: [
+        d.dir('bin', [d.file('foo.dart', 'main() => print("hi");')])
+      ])
+      ..serve('foo', '2.0.0', contents: [
+        d.dir('bin', [d.file('foo.dart', 'main() => print("hi2");')])
       ]);
-      builder.serve('foo', '2.0.0', contents: [
-        d.dir('bin', [d.file('foo.dart', 'main() => print("hi2"); ')])
-      ]);
-    });
 
     // Activate 1.0.0.
     await runPub(args: ['global', 'activate', 'foo', '1.0.0']);
diff --git a/test/global/activate/doesnt_snapshot_path_executables_test.dart b/test/global/activate/doesnt_snapshot_path_executables_test.dart
index b809ea7..2ca8d3a 100644
--- a/test/global/activate/doesnt_snapshot_path_executables_test.dart
+++ b/test/global/activate/doesnt_snapshot_path_executables_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/activate/empty_constraint_test.dart b/test/global/activate/empty_constraint_test.dart
index 9e0bde9..d893bcd 100644
--- a/test/global/activate/empty_constraint_test.dart
+++ b/test/global/activate/empty_constraint_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -11,10 +9,9 @@
 
 void main() {
   test('errors if the constraint matches no versions', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '1.0.1');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '1.0.1');
 
     await runPub(
         args: ['global', 'activate', 'foo', '>1.1.0'],
diff --git a/test/global/activate/feature_test.dart b/test/global/activate/feature_test.dart
index 2d30460..58119d1 100644
--- a/test/global/activate/feature_test.dart
+++ b/test/global/activate/feature_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 @Skip()
 
 import 'package:test/test.dart';
@@ -12,8 +10,8 @@
 
 void main() {
   test('enables default-on features by default', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'dependencies': {'bar': '1.0.0'}
@@ -23,11 +21,9 @@
             'dependencies': {'baz': '1.0.0'}
           }
         }
-      });
-
-      builder.serve('bar', '1.0.0');
-      builder.serve('baz', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0')
+      ..serve('baz', '1.0.0');
 
     await runPub(args: ['global', 'activate', 'foo'], output: contains('''
 Resolving dependencies...
@@ -37,8 +33,8 @@
   });
 
   test('can enable default-off features', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'dependencies': {'bar': '1.0.0'}
@@ -48,11 +44,9 @@
             'dependencies': {'baz': '1.0.0'}
           }
         }
-      });
-
-      builder.serve('bar', '1.0.0');
-      builder.serve('baz', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0')
+      ..serve('baz', '1.0.0');
 
     await runPub(
         args: ['global', 'activate', 'foo', '--features', 'things'],
@@ -65,8 +59,8 @@
   });
 
   test('can disable default-on features', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'dependencies': {'bar': '1.0.0'}
@@ -76,11 +70,9 @@
             'dependencies': {'baz': '1.0.0'}
           }
         }
-      });
-
-      builder.serve('bar', '1.0.0');
-      builder.serve('baz', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0')
+      ..serve('baz', '1.0.0');
 
     await runPub(
         args: ['global', 'activate', 'foo', '--omit-features', 'stuff'],
@@ -91,8 +83,8 @@
   });
 
   test('supports multiple arguments', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'default': false,
@@ -103,11 +95,9 @@
             'dependencies': {'baz': '1.0.0'}
           }
         }
-      });
-
-      builder.serve('bar', '1.0.0');
-      builder.serve('baz', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0')
+      ..serve('baz', '1.0.0');
 
     await runPub(
         args: ['global', 'activate', 'foo', '--features', 'things,stuff'],
@@ -120,8 +110,8 @@
   });
 
   test('can both enable and disable', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'dependencies': {'bar': '1.0.0'}
@@ -131,11 +121,9 @@
             'dependencies': {'baz': '1.0.0'}
           }
         }
-      });
-
-      builder.serve('bar', '1.0.0');
-      builder.serve('baz', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0')
+      ..serve('baz', '1.0.0');
 
     await runPub(args: [
       'global',
diff --git a/test/global/activate/git_package_test.dart b/test/global/activate/git_package_test.dart
index 43cd218..ee88de7 100644
--- a/test/global/activate/git_package_test.dart
+++ b/test/global/activate/git_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/activate/ignores_active_version_test.dart b/test/global/activate/ignores_active_version_test.dart
index d405f54..777a631 100644
--- a/test/global/activate/ignores_active_version_test.dart
+++ b/test/global/activate/ignores_active_version_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,15 +9,14 @@
 
 void main() {
   test('ignores previously activated version', () async {
-    await servePackages((builder) {
-      builder.serve(
+    await servePackages()
+      ..serve(
         'foo',
         '1.2.3',
-      );
-      builder.serve('foo', '1.3.0', contents: [
+      )
+      ..serve('foo', '1.3.0', contents: [
         d.dir('bin', [d.file('foo.dart', 'main() => print("hi"); ')])
       ]);
-    });
 
     // Activate 1.2.3.
     await runPub(args: ['global', 'activate', 'foo', '1.2.3']);
diff --git a/test/global/activate/installs_dependencies_for_git_test.dart b/test/global/activate/installs_dependencies_for_git_test.dart
index 8e5b477..6018f50 100644
--- a/test/global/activate/installs_dependencies_for_git_test.dart
+++ b/test/global/activate/installs_dependencies_for_git_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,10 +9,9 @@
 
 void main() {
   test('activating a Git package installs its dependencies', () async {
-    await servePackages((builder) {
-      builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
-      builder.serve('baz', '1.0.0');
-    });
+    await servePackages()
+      ..serve('bar', '1.0.0', deps: {'baz': 'any'})
+      ..serve('baz', '1.0.0');
 
     await d.git('foo.git', [
       d.libPubspec('foo', '1.0.0', deps: {'bar': 'any'}),
diff --git a/test/global/activate/installs_dependencies_for_path_test.dart b/test/global/activate/installs_dependencies_for_path_test.dart
index 0afe76e..4688f07 100644
--- a/test/global/activate/installs_dependencies_for_path_test.dart
+++ b/test/global/activate/installs_dependencies_for_path_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,10 +9,9 @@
 
 void main() {
   test('activating a path package installs dependencies', () async {
-    await servePackages((builder) {
-      builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
-      builder.serve('baz', '2.0.0');
-    });
+    await servePackages()
+      ..serve('bar', '1.0.0', deps: {'baz': 'any'})
+      ..serve('baz', '2.0.0');
 
     await d.dir('foo', [
       d.libPubspec('foo', '0.0.0', deps: {'bar': 'any'}),
diff --git a/test/global/activate/installs_dependencies_test.dart b/test/global/activate/installs_dependencies_test.dart
index 0b26d8b..770ebcf 100644
--- a/test/global/activate/installs_dependencies_test.dart
+++ b/test/global/activate/installs_dependencies_test.dart
@@ -2,19 +2,16 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../test_pub.dart';
 
 void main() {
   test('activating a package installs its dependencies', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
-      builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
-      builder.serve('baz', '1.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': 'any'})
+      ..serve('bar', '1.0.0', deps: {'baz': 'any'})
+      ..serve('baz', '1.0.0');
 
     await runPub(
         args: ['global', 'activate', 'foo'],
diff --git a/test/global/activate/missing_git_repo_test.dart b/test/global/activate/missing_git_repo_test.dart
index bbb2345..8db65c3 100644
--- a/test/global/activate/missing_git_repo_test.dart
+++ b/test/global/activate/missing_git_repo_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/global/activate/missing_package_arg_test.dart b/test/global/activate/missing_package_arg_test.dart
index 0b747af..588ffcf 100644
--- a/test/global/activate/missing_package_arg_test.dart
+++ b/test/global/activate/missing_package_arg_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/global/activate/outdated_binstub_test.dart b/test/global/activate/outdated_binstub_test.dart
index 43bed90..6d9e298 100644
--- a/test/global/activate/outdated_binstub_test.dart
+++ b/test/global/activate/outdated_binstub_test.dart
@@ -2,14 +2,12 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
-const _OUTDATED_BINSTUB = '''
+const _outdatedBinstub = '''
 #!/usr/bin/env sh
 # This file was created by pub v0.1.2-3.
 # Package: foo
@@ -21,19 +19,17 @@
 
 void main() {
   test('an outdated binstub is replaced', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'executables': {'foo-script': 'script'}
-      }, contents: [
-        d.dir(
-            'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'executables': {'foo-script': 'script'}
+    }, contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
     await d.dir(cachePath, [
-      d.dir('bin', [d.file(binStubName('foo-script'), _OUTDATED_BINSTUB)])
+      d.dir('bin', [d.file(binStubName('foo-script'), _outdatedBinstub)])
     ]).create();
 
     await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/activate/path_package_test.dart b/test/global/activate/path_package_test.dart
index 5153760..514176a 100644
--- a/test/global/activate/path_package_test.dart
+++ b/test/global/activate/path_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -57,14 +55,13 @@
   });
 
   test("Doesn't precompile binaries when activating from path", () async {
-    await servePackages(
-      (builder) => builder.serve(
-        'bar',
-        '1.0.0',
-        contents: [
-          d.dir('bin', [d.file('bar.dart', "main() => print('bar');")])
-        ],
-      ),
+    final server = await servePackages();
+    server.serve(
+      'bar',
+      '1.0.0',
+      contents: [
+        d.dir('bin', [d.file('bar.dart', "main() => print('bar');")])
+      ],
     );
 
     await d.dir('foo', [
diff --git a/test/global/activate/reactivating_git_upgrades_test.dart b/test/global/activate/reactivating_git_upgrades_test.dart
index 0ccbb65..100aaea 100644
--- a/test/global/activate/reactivating_git_upgrades_test.dart
+++ b/test/global/activate/reactivating_git_upgrades_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/activate/removes_old_lockfile_test.dart b/test/global/activate/removes_old_lockfile_test.dart
index 7d7a9e0..3392aff 100644
--- a/test/global/activate/removes_old_lockfile_test.dart
+++ b/test/global/activate/removes_old_lockfile_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,9 +9,8 @@
 
 void main() {
   test('removes the 1.6-style lockfile', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
 
     await d.dir(cachePath, [
       d.dir('global_packages', [
diff --git a/test/global/activate/snapshots_git_executables_test.dart b/test/global/activate/snapshots_git_executables_test.dart
index 81a0152..aee6a71 100644
--- a/test/global/activate/snapshots_git_executables_test.dart
+++ b/test/global/activate/snapshots_git_executables_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/activate/snapshots_hosted_executables_test.dart b/test/global/activate/snapshots_hosted_executables_test.dart
index e9d2a2d..bc2b332 100644
--- a/test/global/activate/snapshots_hosted_executables_test.dart
+++ b/test/global/activate/snapshots_hosted_executables_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,16 +9,15 @@
 
 void main() {
   test('snapshots the executables for a hosted package', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [
-          d.file('hello.dart', "void main() => print('hello!');"),
-          d.file('goodbye.dart', "void main() => print('goodbye!');"),
-          d.file('shell.sh', 'echo shell'),
-          d.dir('subdir', [d.file('sub.dart', "void main() => print('sub!');")])
-        ])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [
+        d.file('hello.dart', "void main() => print('hello!');"),
+        d.file('goodbye.dart', "void main() => print('goodbye!');"),
+        d.file('shell.sh', 'echo shell'),
+        d.dir('subdir', [d.file('sub.dart', "void main() => print('sub!');")])
+      ])
+    ]);
 
     await runPub(
         args: ['global', 'activate', 'foo'],
diff --git a/test/global/activate/supports_version_solver_backtracking_test.dart b/test/global/activate/supports_version_solver_backtracking_test.dart
index e43e735..c8c138d 100644
--- a/test/global/activate/supports_version_solver_backtracking_test.dart
+++ b/test/global/activate/supports_version_solver_backtracking_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,14 +9,13 @@
 
 void main() {
   test('performs verison solver backtracking if necessary', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.1.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.1.0', pubspec: {
         'environment': {'sdk': '>=0.1.2 <0.2.0'}
-      });
-      builder.serve('foo', '1.2.0', pubspec: {
+      })
+      ..serve('foo', '1.2.0', pubspec: {
         'environment': {'sdk': '>=0.1.3 <0.2.0'}
       });
-    });
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/activate/uncached_package_test.dart b/test/global/activate/uncached_package_test.dart
index 3bdb185..1a18d70 100644
--- a/test/global/activate/uncached_package_test.dart
+++ b/test/global/activate/uncached_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,17 +9,16 @@
 
 void main() {
   test('installs and activates the best version of a package', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('foo.dart', 'main() => print("hi"); ')])
+    await servePackages()
+      ..serve('foo', '1.0.0', contents: [
+        d.dir('bin', [d.file('foo.dart', 'main() => print("hi");')])
+      ])
+      ..serve('foo', '1.2.3', contents: [
+        d.dir('bin', [d.file('foo.dart', 'main() => print("hi 1.2.3");')])
+      ])
+      ..serve('foo', '2.0.0-wildly.unstable', contents: [
+        d.dir('bin', [d.file('foo.dart', 'main() => print("hi unstable");')])
       ]);
-      builder.serve('foo', '1.2.3', contents: [
-        d.dir('bin', [d.file('foo.dart', 'main() => print("hi 1.2.3"); ')])
-      ]);
-      builder.serve('foo', '2.0.0-wildly.unstable', contents: [
-        d.dir('bin', [d.file('foo.dart', 'main() => print("hi unstable"); ')])
-      ]);
-    });
 
     await runPub(args: ['global', 'activate', 'foo'], output: '''
         Resolving dependencies...
diff --git a/test/global/activate/unexpected_arguments_test.dart b/test/global/activate/unexpected_arguments_test.dart
index d7bb4cf..be6633d 100644
--- a/test/global/activate/unexpected_arguments_test.dart
+++ b/test/global/activate/unexpected_arguments_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/global/activate/unknown_package_test.dart b/test/global/activate/unknown_package_test.dart
index 6a4fe84..271545d 100644
--- a/test/global/activate/unknown_package_test.dart
+++ b/test/global/activate/unknown_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -11,7 +9,7 @@
 
 void main() {
   test('errors if the package could not be found', () async {
-    await serveNoPackages();
+    await servePackages();
 
     await runPub(
         args: ['global', 'activate', 'foo'],
diff --git a/test/global/binstubs/binstub_runs_executable_test.dart b/test/global/binstubs/binstub_runs_executable_test.dart
index 284729b..98ab53b 100644
--- a/test/global/binstubs/binstub_runs_executable_test.dart
+++ b/test/global/binstubs/binstub_runs_executable_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
 import 'package:test_process/test_process.dart';
@@ -14,14 +12,12 @@
 
 void main() {
   test('the generated binstub runs a snapshotted executable', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'executables': {'foo-script': 'script'}
-      }, contents: [
-        d.dir(
-            'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'executables': {'foo-script': 'script'}
+    }, contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart b/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart
index 25a6281..8024c3a 100644
--- a/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart
+++ b/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/binstub_runs_precompiled_snapshot_test.dart b/test/global/binstubs/binstub_runs_precompiled_snapshot_test.dart
index f59d8e2..cd477db 100644
--- a/test/global/binstubs/binstub_runs_precompiled_snapshot_test.dart
+++ b/test/global/binstubs/binstub_runs_precompiled_snapshot_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,13 +9,12 @@
 
 void main() {
   test('the binstubs runs a built snapshot if present', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'executables': {'foo-script': 'script'}
-      }, contents: [
-        d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'executables': {'foo-script': 'script'}
+    }, contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/binstubs/creates_executables_in_pubspec_test.dart b/test/global/binstubs/creates_executables_in_pubspec_test.dart
index 1529d3e..a6604ab 100644
--- a/test/global/binstubs/creates_executables_in_pubspec_test.dart
+++ b/test/global/binstubs/creates_executables_in_pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,17 +9,16 @@
 
 void main() {
   test('creates binstubs for each executable in the pubspec', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'executables': {'one': null, 'two-renamed': 'second'}
-      }, contents: [
-        d.dir('bin', [
-          d.file('one.dart', "main(args) => print('one');"),
-          d.file('second.dart', "main(args) => print('two');"),
-          d.file('nope.dart', "main(args) => print('nope');")
-        ])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'executables': {'one': null, 'two-renamed': 'second'}
+    }, contents: [
+      d.dir('bin', [
+        d.file('one.dart', "main(args) => print('one');"),
+        d.file('second.dart', "main(args) => print('two');"),
+        d.file('nope.dart', "main(args) => print('nope');")
+      ])
+    ]);
 
     await runPub(
         args: ['global', 'activate', 'foo'],
diff --git a/test/global/binstubs/does_not_warn_if_no_executables_test.dart b/test/global/binstubs/does_not_warn_if_no_executables_test.dart
index e172b1b..9814f15 100644
--- a/test/global/binstubs/does_not_warn_if_no_executables_test.dart
+++ b/test/global/binstubs/does_not_warn_if_no_executables_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,12 +9,10 @@
 
 void main() {
   test('does not warn if the package has no executables', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir(
-            'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+    ]);
 
     await runPub(
         args: ['global', 'activate', 'foo'],
diff --git a/test/global/binstubs/does_not_warn_if_on_path_test.dart b/test/global/binstubs/does_not_warn_if_on_path_test.dart
index 07cba16..9b11386 100644
--- a/test/global/binstubs/does_not_warn_if_on_path_test.dart
+++ b/test/global/binstubs/does_not_warn_if_on_path_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:path/path.dart' as p;
@@ -14,14 +12,12 @@
 
 void main() {
   test('does not warn if the binstub directory is on the path', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'executables': {'script': null}
-      }, contents: [
-        d.dir(
-            'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'executables': {'script': null}
+    }, contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+    ]);
 
     // Add the test's cache bin directory to the path.
     var binDir = p.dirname(Platform.executable);
diff --git a/test/global/binstubs/explicit_and_no_executables_options_test.dart b/test/global/binstubs/explicit_and_no_executables_options_test.dart
index d493bd7..68bbd5b 100644
--- a/test/global/binstubs/explicit_and_no_executables_options_test.dart
+++ b/test/global/binstubs/explicit_and_no_executables_options_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/global/binstubs/explicit_executables_test.dart b/test/global/binstubs/explicit_executables_test.dart
index e032c32..e721f73 100644
--- a/test/global/binstubs/explicit_executables_test.dart
+++ b/test/global/binstubs/explicit_executables_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/missing_script_test.dart b/test/global/binstubs/missing_script_test.dart
index 96b5e89..433f9cf 100644
--- a/test/global/binstubs/missing_script_test.dart
+++ b/test/global/binstubs/missing_script_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
 
diff --git a/test/global/binstubs/name_collision_test.dart b/test/global/binstubs/name_collision_test.dart
index 54afc02..75b72ce 100644
--- a/test/global/binstubs/name_collision_test.dart
+++ b/test/global/binstubs/name_collision_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/name_collision_with_overwrite_test.dart b/test/global/binstubs/name_collision_with_overwrite_test.dart
index caed6d1..6e5a869 100644
--- a/test/global/binstubs/name_collision_with_overwrite_test.dart
+++ b/test/global/binstubs/name_collision_with_overwrite_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/no_executables_flag_test.dart b/test/global/binstubs/no_executables_flag_test.dart
index d7bc037..39f91cd 100644
--- a/test/global/binstubs/no_executables_flag_test.dart
+++ b/test/global/binstubs/no_executables_flag_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/outdated_binstub_runs_pub_global_test.dart b/test/global/binstubs/outdated_binstub_runs_pub_global_test.dart
index f4cd075..442dfbc 100644
--- a/test/global/binstubs/outdated_binstub_runs_pub_global_test.dart
+++ b/test/global/binstubs/outdated_binstub_runs_pub_global_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:path/path.dart' as p;
@@ -15,7 +13,7 @@
 import 'utils.dart';
 
 /// The contents of the binstub for [executable], or `null` if it doesn't exist.
-String binStub(String executable) {
+String? binStub(String executable) {
   final f = File(p.join(d.sandbox, cachePath, 'bin', binStubName(executable)));
   if (f.existsSync()) {
     return f.readAsStringSync();
@@ -26,23 +24,22 @@
 void main() {
   test("an outdated binstub runs 'pub global run', which replaces old binstub",
       () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'executables': {
-          'foo-script': 'script',
-          'foo-script2': 'script',
-          'foo-script-not-installed': 'script',
-          'foo-another-script': 'another-script',
-          'foo-another-script-not-installed': 'another-script'
-        }
-      }, contents: [
-        d.dir('bin', [
-          d.file('script.dart', r"main(args) => print('ok $args');"),
-          d.file('another-script.dart',
-              r"main(args) => print('not so good $args');")
-        ])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'executables': {
+        'foo-script': 'script',
+        'foo-script2': 'script',
+        'foo-script-not-installed': 'script',
+        'foo-another-script': 'another-script',
+        'foo-another-script-not-installed': 'another-script'
+      }
+    }, contents: [
+      d.dir('bin', [
+        d.file('script.dart', r"main(args) => print('ok $args');"),
+        d.file(
+            'another-script.dart', r"main(args) => print('not so good $args');")
+      ])
+    ]);
 
     await runPub(args: [
       'global',
diff --git a/test/global/binstubs/outdated_snapshot_test.dart b/test/global/binstubs/outdated_snapshot_test.dart
index c1181b9..91bfff6 100644
--- a/test/global/binstubs/outdated_snapshot_test.dart
+++ b/test/global/binstubs/outdated_snapshot_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -15,14 +13,12 @@
 
 void main() {
   test("a binstub runs 'pub global run' for an outdated snapshot", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'executables': {'foo-script': 'script'}
-      }, contents: [
-        d.dir(
-            'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'executables': {'foo-script': 'script'}
+    }, contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/binstubs/path_package_test.dart b/test/global/binstubs/path_package_test.dart
index d702054..0461e35 100644
--- a/test/global/binstubs/path_package_test.dart
+++ b/test/global/binstubs/path_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/reactivate_removes_old_executables_test.dart b/test/global/binstubs/reactivate_removes_old_executables_test.dart
index e7f6ade..80b50ff 100644
--- a/test/global/binstubs/reactivate_removes_old_executables_test.dart
+++ b/test/global/binstubs/reactivate_removes_old_executables_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/removes_even_if_not_in_pubspec_test.dart b/test/global/binstubs/removes_even_if_not_in_pubspec_test.dart
index ed215ae..4cd458e 100644
--- a/test/global/binstubs/removes_even_if_not_in_pubspec_test.dart
+++ b/test/global/binstubs/removes_even_if_not_in_pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/removes_when_deactivated_test.dart b/test/global/binstubs/removes_when_deactivated_test.dart
index d241f27..975defe 100644
--- a/test/global/binstubs/removes_when_deactivated_test.dart
+++ b/test/global/binstubs/removes_when_deactivated_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,16 +9,15 @@
 
 void main() {
   test('removes binstubs when the package is deactivated', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'executables': {'one': null, 'two': null}
-      }, contents: [
-        d.dir('bin', [
-          d.file('one.dart', "main(args) => print('one');"),
-          d.file('two.dart', "main(args) => print('two');")
-        ])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'executables': {'one': null, 'two': null}
+    }, contents: [
+      d.dir('bin', [
+        d.file('one.dart', "main(args) => print('one');"),
+        d.file('two.dart', "main(args) => print('two');")
+      ])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
     await runPub(args: ['global', 'deactivate', 'foo']);
diff --git a/test/global/binstubs/runs_once_even_when_dart_is_batch_test.dart b/test/global/binstubs/runs_once_even_when_dart_is_batch_test.dart
index d53af96..99eeaaf 100644
--- a/test/global/binstubs/runs_once_even_when_dart_is_batch_test.dart
+++ b/test/global/binstubs/runs_once_even_when_dart_is_batch_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:path/path.dart' as p;
@@ -16,18 +14,17 @@
   test(
       'runs only once even when dart on path is a batch file (as in flutter/bin)',
       () async {
-    await servePackages((builder) {
-      builder.serve(
-        'foo',
-        '1.0.0',
-        contents: [
-          d.dir('bin', [d.file('script.dart', 'main(args) => print(args);')]),
-        ],
-        pubspec: {
-          'executables': {'script': 'script'},
-        },
-      );
-    });
+    final server = await servePackages();
+    server.serve(
+      'foo',
+      '1.0.0',
+      contents: [
+        d.dir('bin', [d.file('script.dart', 'main(args) => print(args);')]),
+      ],
+      pubspec: {
+        'executables': {'script': 'script'},
+      },
+    );
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/binstubs/unknown_explicit_executable_test.dart b/test/global/binstubs/unknown_explicit_executable_test.dart
index 0b27527..33b82e7 100644
--- a/test/global/binstubs/unknown_explicit_executable_test.dart
+++ b/test/global/binstubs/unknown_explicit_executable_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/global/binstubs/utils.dart b/test/global/binstubs/utils.dart
index e2346cc..59a8df0 100644
--- a/test/global/binstubs/utils.dart
+++ b/test/global/binstubs/utils.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:path/path.dart' as p;
@@ -16,7 +14,7 @@
 ///
 /// The `pub`/`pub.bat` command on the PATH will be the one in tool/test-bin not
 /// the one from the sdk.
-Map getEnvironment() {
+Map<String, String> getEnvironment() {
   var binDir = p.dirname(Platform.resolvedExecutable);
   var separator = Platform.isWindows ? ';' : ':';
   var pubBin = p.absolute('tool', 'test-bin');
diff --git a/test/global/binstubs/warns_if_not_on_path_test.dart b/test/global/binstubs/warns_if_not_on_path_test.dart
index fcfdb0c..d98bf76 100644
--- a/test/global/binstubs/warns_if_not_on_path_test.dart
+++ b/test/global/binstubs/warns_if_not_on_path_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,14 +9,12 @@
 
 void main() {
   test('warns if the binstub directory is not on the path', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'executables': {'some-dart-script': 'script'}
-      }, contents: [
-        d.dir(
-            'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'executables': {'some-dart-script': 'script'}
+    }, contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+    ]);
 
     await runPub(
         args: ['global', 'activate', 'foo'],
diff --git a/test/global/deactivate/deactivate_and_reactivate_package_test.dart b/test/global/deactivate/deactivate_and_reactivate_package_test.dart
index ffad990..da33486 100644
--- a/test/global/deactivate/deactivate_and_reactivate_package_test.dart
+++ b/test/global/deactivate/deactivate_and_reactivate_package_test.dart
@@ -2,18 +2,15 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../test_pub.dart';
 
 void main() {
   test('activates a different version after deactivating', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '2.0.0');
 
     // Activate an old version.
     await runPub(args: ['global', 'activate', 'foo', '1.0.0']);
diff --git a/test/global/deactivate/git_package_test.dart b/test/global/deactivate/git_package_test.dart
index 3aa047d..f06ce53 100644
--- a/test/global/deactivate/git_package_test.dart
+++ b/test/global/deactivate/git_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/deactivate/hosted_package_test.dart b/test/global/deactivate/hosted_package_test.dart
index 884e70f..fa91829 100644
--- a/test/global/deactivate/hosted_package_test.dart
+++ b/test/global/deactivate/hosted_package_test.dart
@@ -2,15 +2,14 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../test_pub.dart';
 
 void main() {
   test('deactivates an active hosted package', () async {
-    await servePackages((builder) => builder.serve('foo', '1.0.0'));
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/deactivate/missing_package_arg_test.dart b/test/global/deactivate/missing_package_arg_test.dart
index 6671991..8de8ab1 100644
--- a/test/global/deactivate/missing_package_arg_test.dart
+++ b/test/global/deactivate/missing_package_arg_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/global/deactivate/path_package_test.dart b/test/global/deactivate/path_package_test.dart
index f28d8d1..1f50713 100644
--- a/test/global/deactivate/path_package_test.dart
+++ b/test/global/deactivate/path_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
diff --git a/test/global/deactivate/removes_precompiled_snapshots_test.dart b/test/global/deactivate/removes_precompiled_snapshots_test.dart
index 7d075b3..a7670e2 100644
--- a/test/global/deactivate/removes_precompiled_snapshots_test.dart
+++ b/test/global/deactivate/removes_precompiled_snapshots_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,7 +9,8 @@
 
 void main() {
   test('removes built snapshots', () async {
-    await servePackages((builder) => builder.serve('foo', '1.0.0'));
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/deactivate/unexpected_arguments_test.dart b/test/global/deactivate/unexpected_arguments_test.dart
index 426b7f8..dd1f11f 100644
--- a/test/global/deactivate/unexpected_arguments_test.dart
+++ b/test/global/deactivate/unexpected_arguments_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/global/deactivate/unknown_package_test.dart b/test/global/deactivate/unknown_package_test.dart
index ad0973e..35023ad 100644
--- a/test/global/deactivate/unknown_package_test.dart
+++ b/test/global/deactivate/unknown_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -11,7 +9,7 @@
 
 void main() {
   test('errors if the package is not activated', () async {
-    await serveNoPackages();
+    await servePackages();
 
     await runPub(
         args: ['global', 'deactivate', 'foo'],
diff --git a/test/global/list_test.dart b/test/global/list_test.dart
index 8b7293a..8d4d02e 100644
--- a/test/global/list_test.dart
+++ b/test/global/list_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 
@@ -14,9 +12,8 @@
 
 void main() {
   test('lists an activated hosted package', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
 
     await runPub(args: ['global', 'activate', 'foo']);
 
@@ -51,11 +48,10 @@
   });
 
   test('lists activated packages in alphabetical order', () async {
-    await servePackages((builder) {
-      builder.serve('aaa', '1.0.0');
-      builder.serve('bbb', '1.0.0');
-      builder.serve('ccc', '1.0.0');
-    });
+    await servePackages()
+      ..serve('aaa', '1.0.0')
+      ..serve('bbb', '1.0.0')
+      ..serve('ccc', '1.0.0');
 
     await runPub(args: ['global', 'activate', 'ccc']);
     await runPub(args: ['global', 'activate', 'aaa']);
diff --git a/test/global/run/errors_if_outside_bin_test.dart b/test/global/run/errors_if_outside_bin_test.dart
index e6c15f7..72bcd4f 100644
--- a/test/global/run/errors_if_outside_bin_test.dart
+++ b/test/global/run/errors_if_outside_bin_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -12,11 +10,10 @@
 
 void main() {
   test('errors if the script is in a subdirectory.', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('example', [d.file('script.dart', "main(args) => print('ok');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('example', [d.file('script.dart', "main(args) => print('ok');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
     await runPub(
diff --git a/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart b/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart
index 73b5556..3bef340 100644
--- a/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart
+++ b/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -12,11 +10,10 @@
 
 void main() {
   test("fails if the current SDK doesn't match the constraint", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
@@ -43,15 +40,14 @@
   });
 
   test('fails if SDK is downgraded below the constraints', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'environment': {
-          'sdk': '>=2.0.0 <3.0.0',
-        },
-      }, contents: [
-        d.dir('bin', [d.file('script.dart', "main(args) => print('123-OK');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'environment': {
+        'sdk': '>=2.0.0 <3.0.0',
+      },
+    }, contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('123-OK');")])
+    ]);
 
     await runPub(
       environment: {'_PUB_TEST_SDK_VERSION': '2.0.0'},
@@ -71,8 +67,8 @@
   });
 
   test('fails if SDK is downgraded below dependency SDK constraints', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {
         'bar': '^1.0.0',
       }, pubspec: {
         'environment': {
@@ -80,13 +76,12 @@
         },
       }, contents: [
         d.dir('bin', [d.file('script.dart', "main(args) => print('123-OK');")])
-      ]);
-      builder.serve('bar', '1.0.0', pubspec: {
+      ])
+      ..serve('bar', '1.0.0', pubspec: {
         'environment': {
           'sdk': '>=2.2.0 <3.0.0',
         },
       });
-    });
 
     await runPub(
       environment: {'_PUB_TEST_SDK_VERSION': '2.2.0'},
diff --git a/test/global/run/implicit_executable_name_test.dart b/test/global/run/implicit_executable_name_test.dart
index a2f8c12..9757772 100644
--- a/test/global/run/implicit_executable_name_test.dart
+++ b/test/global/run/implicit_executable_name_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
 
 void main() {
   test('defaults to the package name if the script is omitted', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('foo.dart', "main(args) => print('foo');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('foo.dart', "main(args) => print('foo');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/run/missing_executable_arg_test.dart b/test/global/run/missing_executable_arg_test.dart
index efab258..b64d387 100644
--- a/test/global/run/missing_executable_arg_test.dart
+++ b/test/global/run/missing_executable_arg_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/global/run/missing_path_package_test.dart b/test/global/run/missing_path_package_test.dart
index f15d976..99cf30a 100644
--- a/test/global/run/missing_path_package_test.dart
+++ b/test/global/run/missing_path_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:pub/src/io.dart';
diff --git a/test/global/run/nonexistent_script_test.dart b/test/global/run/nonexistent_script_test.dart
index dc0a738..8ff0a42 100644
--- a/test/global/run/nonexistent_script_test.dart
+++ b/test/global/run/nonexistent_script_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
@@ -12,9 +10,10 @@
 
 void main() {
   test('errors if the script does not exist.', () async {
-    await servePackages((builder) => builder.serve('foo', '1.0.0', pubspec: {
-          'dev_dependencies': {'bar': '1.0.0'}
-        }));
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'dev_dependencies': {'bar': '1.0.0'}
+    });
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/run/package_api_test.dart b/test/global/run/package_api_test.dart
index c95fc5b..5db401b 100644
--- a/test/global/run/package_api_test.dart
+++ b/test/global/run/package_api_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
 
@@ -12,10 +10,9 @@
 
 void main() {
   test('an immutable application sees a file: package config', () async {
-    await servePackages((builder) {
-      builder.serve('bar', '1.0.0');
-
-      builder.serve('foo', '1.0.0', deps: {
+    await servePackages()
+      ..serve('bar', '1.0.0')
+      ..serve('foo', '1.0.0', deps: {
         'bar': '1.0.0'
       }, contents: [
         d.dir('bin', [
@@ -33,7 +30,6 @@
 """)
         ])
       ]);
-    });
 
     await runPub(args: ['global', 'activate', 'foo']);
 
@@ -45,12 +41,12 @@
         'global_packages/foo/.dart_tool/package_config.json');
     expect(pub.stdout, emits(p.toUri(packageConfigPath).toString()));
 
-    var fooResourcePath = p.join(
-        globalPackageServer.pathInCache('foo', '1.0.0'), 'lib/resource.txt');
+    var fooResourcePath =
+        p.join(globalServer.pathInCache('foo', '1.0.0'), 'lib/resource.txt');
     expect(pub.stdout, emits(p.toUri(fooResourcePath).toString()));
 
-    var barResourcePath = p.join(
-        globalPackageServer.pathInCache('bar', '1.0.0'), 'lib/resource.txt');
+    var barResourcePath =
+        p.join(globalServer.pathInCache('bar', '1.0.0'), 'lib/resource.txt');
     expect(pub.stdout, emits(p.toUri(barResourcePath).toString()));
     await pub.shouldExit(0);
   });
diff --git a/test/global/run/recompiles_if_snapshot_is_out_of_date_test.dart b/test/global/run/recompiles_if_snapshot_is_out_of_date_test.dart
index 4ace362..24e65bf 100644
--- a/test/global/run/recompiles_if_snapshot_is_out_of_date_test.dart
+++ b/test/global/run/recompiles_if_snapshot_is_out_of_date_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -13,11 +11,10 @@
 
 void main() {
   test('recompiles a script if the snapshot is out-of-date', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/run/reflects_changes_to_local_package_test.dart b/test/global/run/reflects_changes_to_local_package_test.dart
index 5bc9e55..864111b 100644
--- a/test/global/run/reflects_changes_to_local_package_test.dart
+++ b/test/global/run/reflects_changes_to_local_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/run/runs_git_script_test.dart b/test/global/run/runs_git_script_test.dart
index 8d120b4..900b586 100644
--- a/test/global/run/runs_git_script_test.dart
+++ b/test/global/run/runs_git_script_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/run/runs_path_script_test.dart b/test/global/run/runs_path_script_test.dart
index 90db648..7cc90d4 100644
--- a/test/global/run/runs_path_script_test.dart
+++ b/test/global/run/runs_path_script_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/global/run/runs_script_in_checked_mode_test.dart b/test/global/run/runs_script_in_checked_mode_test.dart
index 1b399c5..d0511cf 100644
--- a/test/global/run/runs_script_in_checked_mode_test.dart
+++ b/test/global/run/runs_script_in_checked_mode_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
 
 void main() {
   test('runs a script with assertions enabled', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('script.dart', 'main() { assert(false); }')])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('script.dart', 'main() { assert(false); }')])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/run/runs_script_in_unchecked_mode_test.dart b/test/global/run/runs_script_in_unchecked_mode_test.dart
index 005bad3..ca752b2 100644
--- a/test/global/run/runs_script_in_unchecked_mode_test.dart
+++ b/test/global/run/runs_script_in_unchecked_mode_test.dart
@@ -2,14 +2,12 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
-const SCRIPT = '''
+const _script = '''
 main() {
   assert(false);
   print("no checks");
@@ -18,11 +16,10 @@
 
 void main() {
   test('runs a script in unchecked mode by default', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('script.dart', SCRIPT)])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('script.dart', _script)])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/run/runs_script_test.dart b/test/global/run/runs_script_test.dart
index bab4d1c..f3f0e99 100644
--- a/test/global/run/runs_script_test.dart
+++ b/test/global/run/runs_script_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
 
 void main() {
   test('runs a script in an activated package', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/run/runs_script_without_packages_file_test.dart b/test/global/run/runs_script_without_packages_file_test.dart
index aa5e691..dc225ba 100644
--- a/test/global/run/runs_script_without_packages_file_test.dart
+++ b/test/global/run/runs_script_without_packages_file_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -14,11 +12,10 @@
 void main() {
   test('runs a snapshotted script without a .dart_tool/package_config file',
       () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+    ]);
 
     await runPub(args: ['global', 'activate', 'foo']);
 
diff --git a/test/global/run/unknown_package_test.dart b/test/global/run/unknown_package_test.dart
index 55a875a..adcb666 100644
--- a/test/global/run/unknown_package_test.dart
+++ b/test/global/run/unknown_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -11,7 +9,7 @@
 
 void main() {
   test('errors if the package is not activated', () async {
-    await serveNoPackages();
+    await servePackages();
 
     await runPub(
         args: ['global', 'run', 'foo:bar'],
diff --git a/test/global/run/uses_old_lockfile_test.dart b/test/global/run/uses_old_lockfile_test.dart
index 4ae12ef..1afab81 100644
--- a/test/global/run/uses_old_lockfile_test.dart
+++ b/test/global/run/uses_old_lockfile_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,9 +9,9 @@
 
 void main() {
   test('uses the 1.6-style lockfile if necessary', () async {
-    await servePackages((builder) {
-      builder.serve('bar', '1.0.0');
-      builder.serve('foo', '1.0.0', deps: {
+    await servePackages()
+      ..serve('bar', '1.0.0')
+      ..serve('foo', '1.0.0', deps: {
         'bar': 'any'
       }, contents: [
         d.dir('bin', [
@@ -23,7 +21,6 @@
               main(args) => print(bar.main());""")
         ])
       ]);
-    });
 
     await runPub(args: ['cache', 'add', 'foo']);
     await runPub(args: ['cache', 'add', 'bar']);
diff --git a/test/golden_file.dart b/test/golden_file.dart
index 90d2340..7927776 100644
--- a/test/golden_file.dart
+++ b/test/golden_file.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async';
 import 'dart:io';
 
@@ -40,14 +38,14 @@
       ' END OF OUTPUT '
       '---------------------------------\n\n';
 
-  final String _currentTestFile;
-  final String _testName;
+  late final String _currentTestFile;
+  late final String _testName;
 
-  String _goldenFilePath;
-  File _goldenFile;
-  String _header;
+  late String _goldenFilePath;
+  late File _goldenFile;
+  late String _header;
   final _results = <String>[];
-  bool _goldenFileExists;
+  late bool _goldenFileExists;
   bool _generatedNewData = false; // track if new data is generated
   int _nextSectionIndex = 0;
 
@@ -151,8 +149,8 @@
   /// log stdout/stderr and exitcode to golden file.
   Future<void> run(
     List<String> args, {
-    Map<String, String> environment,
-    String workingDirectory,
+    Map<String, String>? environment,
+    String? workingDirectory,
   }) async {
     // Create new section index number (before doing anything async)
     final sectionIndex = _nextSectionIndex++;
@@ -169,7 +167,7 @@
   }
 
   /// Log directory tree structure under [directory] to golden file.
-  Future<void> tree([String directory]) async {
+  Future<void> tree([String? directory]) async {
     // Create new section index number (before doing anything async)
     final sectionIndex = _nextSectionIndex++;
 
diff --git a/test/help_test.dart b/test/help_test.dart
index 7ef96ff..e66f8a4 100644
--- a/test/help_test.dart
+++ b/test/help_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.
 
-// @dart=2.10
 import 'package:args/command_runner.dart';
 import 'package:pub/src/command_runner.dart' show PubCommandRunner;
 
diff --git a/test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart b/test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
index f5ad35c..7fb22a3 100644
--- a/test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+++ b/test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -11,6 +9,7 @@
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
+import '../golden_file.dart';
 import '../test_pub.dart';
 
 void main() {
@@ -18,15 +17,18 @@
     test(
         'fails gracefully if the package server responds with broken package listings',
         () async {
-      await servePackages((b) => b..serve('foo', '1.2.3'));
-      globalPackageServer.extraHandlers[RegExp('/api/packages/.*')] =
-          expectAsync1((request) {
-        expect(request.method, 'GET');
-        return Response(200,
-            body: jsonEncode({
-              'notTheRight': {'response': 'type'}
-            }));
-      });
+      final server = await servePackages();
+      server.serve('foo', '1.2.3');
+      server.expect(
+        'GET',
+        RegExp('/api/packages/.*'),
+        expectAsync1((request) {
+          return Response(200,
+              body: jsonEncode({
+                'notTheRight': {'response': 'type'}
+              }));
+        }),
+      );
       await d.appDir({'foo': '1.2.3'}).create();
 
       await pubCommand(command,
@@ -38,4 +40,80 @@
           exitCode: exit_codes.DATA);
     });
   });
+
+  testWithGolden('bad_json', (ctx) async {
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
+    server.expect('GET', RegExp('/api/packages/.*'), (request) {
+      return Response(200,
+          body: jsonEncode({
+            'notTheRight': {'response': 'type'}
+          }));
+    });
+    await d.appDir({'foo': '1.2.3'}).create();
+
+    await ctx.run(['get']);
+  });
+
+  testWithGolden('403', (ctx) async {
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
+    server.expect('GET', RegExp('/api/packages/.*'), (request) {
+      return Response(403,
+          body: jsonEncode({
+            'notTheRight': {'response': 'type'}
+          }));
+    });
+    await d.appDir({'foo': '1.2.3'}).create();
+
+    await ctx.run(['get']);
+  });
+
+  testWithGolden('401', (ctx) async {
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
+    server.expect('GET', RegExp('/api/packages/.*'), (request) {
+      return Response(401,
+          body: jsonEncode({
+            'notTheRight': {'response': 'type'}
+          }));
+    });
+    await d.appDir({'foo': '1.2.3'}).create();
+
+    await ctx.run(['get']);
+  });
+
+  testWithGolden('403-with-message', (ctx) async {
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
+    server.expect('GET', RegExp('/api/packages/.*'), (request) {
+      return Response(403,
+          headers: {
+            'www-authenticate': 'Bearer realm="pub", message="<message>"',
+          },
+          body: jsonEncode({
+            'notTheRight': {'response': 'type'}
+          }));
+    });
+    await d.appDir({'foo': '1.2.3'}).create();
+
+    await ctx.run(['get']);
+  });
+
+  testWithGolden('401-with-message', (ctx) async {
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
+    server.expect('GET', RegExp('/api/packages/.*'), (request) {
+      return Response(401,
+          headers: {
+            'www-authenticate': 'Bearer realm="pub", message="<message>"',
+          },
+          body: jsonEncode({
+            'notTheRight': {'response': 'type'}
+          }));
+    });
+    await d.appDir({'foo': '1.2.3'}).create();
+
+    await ctx.run(['get']);
+  });
 }
diff --git a/test/hosted/fail_gracefully_on_invalid_url_test.dart b/test/hosted/fail_gracefully_on_invalid_url_test.dart
index 9cbfbe8..94922c0 100644
--- a/test/hosted/fail_gracefully_on_invalid_url_test.dart
+++ b/test/hosted/fail_gracefully_on_invalid_url_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/hosted/fail_gracefully_on_missing_package_test.dart b/test/hosted/fail_gracefully_on_missing_package_test.dart
index 882d11c..7c6290d 100644
--- a/test/hosted/fail_gracefully_on_missing_package_test.dart
+++ b/test/hosted/fail_gracefully_on_missing_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -13,7 +11,7 @@
 void main() {
   forBothPubGetAndUpgrade((command) {
     test('fails gracefully if the package does not exist', () async {
-      await serveNoPackages();
+      await servePackages();
 
       await d.appDir({'foo': '1.2.3'}).create();
 
diff --git a/test/hosted/fail_gracefully_on_url_resolve_test.dart b/test/hosted/fail_gracefully_on_url_resolve_test.dart
index 9e3abcd..7a91e7a 100644
--- a/test/hosted/fail_gracefully_on_url_resolve_test.dart
+++ b/test/hosted/fail_gracefully_on_url_resolve_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/hosted/fail_gracefully_with_hint_test.dart b/test/hosted/fail_gracefully_with_hint_test.dart
new file mode 100644
index 0000000..4f1a326
--- /dev/null
+++ b/test/hosted/fail_gracefully_with_hint_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2012, 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 '../golden_file.dart';
+import '../test_pub.dart';
+
+void main() {
+  testWithGolden('hint: try without --offline', (ctx) async {
+    // Run the server so that we know what URL to use in the system cache.
+    (await servePackages()).serveErrors();
+
+    await d.appDir({'foo': 'any'}).create();
+
+    await pubGet(
+      args: ['--offline'],
+      exitCode: exit_codes.UNAVAILABLE,
+      error: contains('Try again without --offline!'),
+    );
+  });
+
+  testWithGolden('supports two hints', (ctx) async {
+    // Run the server so that we know what URL to use in the system cache.
+    (await servePackages()).serveErrors();
+
+    await d.hostedCache([
+      d.dir('foo-1.2.3', [
+        d.pubspec({
+          'name': 'foo',
+          'version': '1.2.3',
+          'environment': {
+            'flutter': 'any', // generates hint -> flutter pub get
+          },
+        }),
+      ]),
+      d.dir('foo-1.2.4', [
+        d.pubspec({
+          'name': 'foo',
+          'version': '1.2.4',
+          'dependencies': {
+            'bar': 'any', // generates hint -> try without --offline
+          },
+        }),
+      ]),
+    ]).create();
+
+    await d.appDir({'foo': 'any'}).create();
+
+    await pubGet(
+      args: ['--offline'],
+      exitCode: exit_codes.UNAVAILABLE,
+      error: allOf(
+        contains('Try again without --offline!'),
+        contains('flutter pub get'), // hint that
+      ),
+    );
+
+    await ctx.run(['get', '--offline']);
+  });
+}
diff --git a/test/hosted/metadata_test.dart b/test/hosted/metadata_test.dart
index 6ba59f5..c705ac7 100644
--- a/test/hosted/metadata_test.dart
+++ b/test/hosted/metadata_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:test/test.dart';
@@ -14,9 +12,8 @@
 void main() {
   forBothPubGetAndUpgrade((command) {
     test('sends metadata headers for a direct dependency', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-      });
+      final server = await servePackages();
+      server.serve('foo', '1.0.0');
 
       await d.appDir({'foo': '1.0.0'}).create();
 
@@ -35,9 +32,8 @@
     });
 
     test('sends metadata headers for a dev dependency', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-      });
+      final server = await servePackages();
+      server.serve('foo', '1.0.0');
 
       await d.dir(appPath, [
         d.pubspec({
@@ -61,9 +57,8 @@
     });
 
     test('sends metadata headers for a transitive dependency', () async {
-      await servePackages((builder) {
-        builder.serve('bar', '1.0.0');
-      });
+      final server = await servePackages();
+      server.serve('bar', '1.0.0');
 
       await d.appDir({
         'foo': {'path': '../foo'}
@@ -84,9 +79,8 @@
     });
 
     test("doesn't send metadata headers to a foreign server", () async {
-      var server = await PackageServer.start((builder) {
-        builder.serve('foo', '1.0.0');
-      });
+      var server = await startPackageServer()
+        ..serve('foo', '1.0.0');
 
       await d.appDir({
         'foo': {
@@ -99,9 +93,7 @@
     });
 
     test("doesn't send metadata headers when CI=true", () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-      });
+      (await servePackages()).serve('foo', '1.0.0');
 
       await d.appDir({'foo': '1.0.0'}).create();
 
diff --git a/test/hosted/offline_test.dart b/test/hosted/offline_test.dart
index ef738c8..6482656 100644
--- a/test/hosted/offline_test.dart
+++ b/test/hosted/offline_test.dart
@@ -2,22 +2,19 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
-Future<void> populateCache(Map<String, List<String>> versions) async {
-  await servePackages((b) {
-    for (final entry in versions.entries) {
-      for (final version in entry.value) {
-        b.serve(entry.key, version);
-      }
+Future<void> populateCache(
+    Map<String, List<String>> versions, PackageServer server) async {
+  for (final entry in versions.entries) {
+    for (final version in entry.value) {
+      server.serve(entry.key, version);
     }
-  });
+  }
   for (final entry in versions.entries) {
     for (final version in entry.value) {
       await d.appDir({entry.key: version}).create();
@@ -29,17 +26,18 @@
 void main() {
   forBothPubGetAndUpgrade((command) {
     test('upgrades a package using the cache', () async {
+      final server = await servePackages();
       await populateCache({
         'foo': ['1.2.2', '1.2.3'],
         'bar': ['1.2.3']
-      });
+      }, server);
 
       // Now serve only errors - to validate we are truly offline.
-      await serveErrors();
+      server.serveErrors();
 
       await d.appDir({'foo': 'any', 'bar': 'any'}).create();
 
-      String warning;
+      String? warning;
       if (command == RunCommand.upgrade) {
         warning = 'Warning: Upgrading when offline may not update you '
             'to the latest versions of your dependencies.';
@@ -51,15 +49,16 @@
     });
 
     test('supports prerelease versions', () async {
+      final server = await servePackages();
       await populateCache({
         'foo': ['1.2.3-alpha.1']
-      });
+      }, server);
       // Now serve only errors - to validate we are truly offline.
-      await serveErrors();
+      server.serveErrors();
 
       await d.appDir({'foo': 'any'}).create();
 
-      String warning;
+      String? warning;
       if (command == RunCommand.upgrade) {
         warning = 'Warning: Upgrading when offline may not update you '
             'to the latest versions of your dependencies.';
@@ -72,7 +71,8 @@
 
     test('fails gracefully if a dependency is not cached', () async {
       // Run the server so that we know what URL to use in the system cache.
-      await serveErrors();
+      final server = await servePackages();
+      server.serveErrors();
 
       await d.appDir({'foo': 'any'}).create();
 
@@ -82,16 +82,19 @@
           error: equalsIgnoringWhitespace("""
             Because myapp depends on foo any which doesn't exist (could not find
               package foo in cache), version solving failed.
+
+            Try again without --offline!
           """));
     });
 
     test('fails gracefully if no cached versions match', () async {
+      final server = await servePackages();
       await populateCache({
         'foo': ['1.2.2', '1.2.3']
-      });
+      }, server);
 
       // Run the server so that we know what URL to use in the system cache.
-      await serveErrors();
+      server.serveErrors();
 
       await d.appDir({'foo': '>2.0.0'}).create();
 
@@ -105,8 +108,10 @@
     test(
         'fails gracefully if a dependency is not cached and a lockfile '
         'exists', () async {
+      final server = await servePackages();
+
       // Run the server so that we know what URL to use in the system cache.
-      await serveErrors();
+      server.serveErrors();
 
       await d.appDir({'foo': 'any'}).create();
 
@@ -118,15 +123,19 @@
           error: equalsIgnoringWhitespace("""
             Because myapp depends on foo any which doesn't exist (could not find
               package foo in cache), version solving failed.
+
+            Try again without --offline!
           """));
     });
 
     test('downgrades to the version in the cache if necessary', () async {
+      final server = await servePackages();
+
       await populateCache({
         'foo': ['1.2.2', '1.2.3']
-      });
+      }, server);
       // Run the server so that we know what URL to use in the system cache.
-      await serveErrors();
+      server.serveErrors();
 
       await d.appDir({'foo': 'any'}).create();
 
@@ -138,11 +147,13 @@
     });
 
     test('skips invalid cached versions', () async {
+      final server = await servePackages();
+
       await populateCache({
         'foo': ['1.2.2', '1.2.3']
-      });
+      }, server);
       // Run the server so that we know what URL to use in the system cache.
-      await serveErrors();
+      server.serveErrors();
 
       await d.hostedCache([
         d.dir('foo-1.2.3', [d.file('pubspec.yaml', '{')]),
@@ -157,11 +168,13 @@
     });
 
     test('skips invalid locked versions', () async {
+      final server = await servePackages();
+
       await populateCache({
         'foo': ['1.2.2', '1.2.3']
-      });
+      }, server);
       // Run the server so that we know what URL to use in the system cache.
-      await serveErrors();
+      server.serveErrors();
 
       await d.hostedCache([
         d.dir('foo-1.2.3', [d.file('pubspec.yaml', '{')])
diff --git a/test/hosted/remove_removed_dependency_test.dart b/test/hosted/remove_removed_dependency_test.dart
index 9d530d7..bb2e091 100644
--- a/test/hosted/remove_removed_dependency_test.dart
+++ b/test/hosted/remove_removed_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -12,10 +10,9 @@
 void main() {
   forBothPubGetAndUpgrade((command) {
     test("removes a dependency that's removed from the pubspec", () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-        builder.serve('bar', '1.0.0');
-      });
+      await servePackages()
+        ..serve('foo', '1.0.0')
+        ..serve('bar', '1.0.0');
 
       await d.appDir({'foo': 'any', 'bar': 'any'}).create();
 
diff --git a/test/hosted/remove_removed_transitive_dependency_test.dart b/test/hosted/remove_removed_transitive_dependency_test.dart
index 43ac01c..ac3a452 100644
--- a/test/hosted/remove_removed_transitive_dependency_test.dart
+++ b/test/hosted/remove_removed_transitive_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -14,13 +12,11 @@
     test(
         "removes a transitive dependency that's no longer depended "
         'on', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', deps: {'shared_dep': 'any'});
-        builder.serve('bar', '1.0.0',
-            deps: {'shared_dep': 'any', 'bar_dep': 'any'});
-        builder.serve('shared_dep', '1.0.0');
-        builder.serve('bar_dep', '1.0.0');
-      });
+      await servePackages()
+        ..serve('foo', '1.0.0', deps: {'shared_dep': 'any'})
+        ..serve('bar', '1.0.0', deps: {'shared_dep': 'any', 'bar_dep': 'any'})
+        ..serve('shared_dep', '1.0.0')
+        ..serve('bar_dep', '1.0.0');
 
       await d.appDir({'foo': 'any', 'bar': 'any'}).create();
 
diff --git a/test/hosted/short_syntax_test.dart b/test/hosted/short_syntax_test.dart
index bfbb3b4..5d4cf28 100644
--- a/test/hosted/short_syntax_test.dart
+++ b/test/hosted/short_syntax_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:path/path.dart' as p;
@@ -14,10 +12,12 @@
 import '../test_pub.dart';
 
 void main() {
-  setUp(() => servePackages((b) => b.serve('foo', '1.2.3', pubspec: {
-        'environment': {'sdk': '^2.0.0'}
-      })));
-
+  setUp(() async {
+    final server = await servePackages();
+    server.serve('foo', '1.2.3', pubspec: {
+      'environment': {'sdk': '^2.0.0'}
+    });
+  });
   forBothPubGetAndUpgrade((command) {
     Future<void> testWith(dynamic dependency) async {
       await d.dir(appPath, [
@@ -44,19 +44,19 @@
         'source': 'hosted',
         'description': {
           'name': 'foo',
-          'url': globalPackageServer.url,
+          'url': globalServer.url,
         },
         'version': '1.2.3',
       });
     }
 
     test('supports hosted: <url> syntax', () async {
-      return testWith({'hosted': globalPackageServer.url});
+      return testWith({'hosted': globalServer.url});
     });
 
     test('supports hosted map without name', () {
       return testWith({
-        'hosted': {'url': globalPackageServer.url},
+        'hosted': {'url': globalServer.url},
       });
     });
 
@@ -82,8 +82,8 @@
         await File(p.join(d.sandbox, appPath, 'pubspec.lock')).readAsString(),
       );
 
-      expect(lockFile['packages']['foo']['description']['url'],
-          globalPackageServer.url);
+      expect(
+          lockFile['packages']['foo']['description']['url'], globalServer.url);
     });
   });
 }
diff --git a/test/hosted/version_negotiation_test.dart b/test/hosted/version_negotiation_test.dart
index 3d12703..44dbe7a 100644
--- a/test/hosted/version_negotiation_test.dart
+++ b/test/hosted/version_negotiation_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
@@ -18,11 +16,11 @@
 
       await d.appDir({
         'foo': {
-          'hosted': {'name': 'foo', 'url': globalPackageServer.url}
+          'hosted': {'name': 'foo', 'url': globalServer.url}
         }
       }).create();
 
-      globalPackageServer.expect('GET', '/api/packages/foo', (request) {
+      globalServer.expect('GET', '/api/packages/foo', (request) {
         expect(
             request.headers['accept'], equals('application/vnd.pub.v2+json'));
         return shelf.Response(404);
@@ -37,13 +35,13 @@
 
       await d.appDir({
         'foo': {
-          'hosted': {'name': 'foo', 'url': globalPackageServer.url}
+          'hosted': {'name': 'foo', 'url': globalServer.url}
         }
       }).create();
 
       var pub = await startPub(args: [command.name]);
 
-      globalPackageServer.expect(
+      globalServer.expect(
           'GET', '/api/packages/foo', (request) => shelf.Response(406));
 
       await pub.shouldExit(1);
diff --git a/test/hosted/will_normalize_hosted_url_test.dart b/test/hosted/will_normalize_hosted_url_test.dart
index f2da266..6cc3888 100644
--- a/test/hosted/will_normalize_hosted_url_test.dart
+++ b/test/hosted/will_normalize_hosted_url_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:http/http.dart' as http;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:shelf/shelf.dart';
@@ -15,47 +13,50 @@
 void main() {
   forBothPubGetAndUpgrade((command) {
     test('does not require slash on bare domain', () async {
-      await servePackages((b) => b..serve('foo', '1.2.3'));
-      // All the tests in this file assumes that [globalPackageServer.url]
+      final server = await servePackages();
+      server.serve('foo', '1.2.3');
+      // All the tests in this file assumes that [globalServer.url]
       // will be on the form:
       //   http://localhost:<port>
       // In particular, that it doesn't contain anything path segment.
-      expect(Uri.parse(globalPackageServer.url).path, isEmpty);
+      expect(Uri.parse(globalServer.url).path, isEmpty);
 
       await d.dir(appPath, [
         d.appPubspec({
           'foo': {
-            'hosted': {'name': 'foo', 'url': globalPackageServer.url},
+            'hosted': {'name': 'foo', 'url': globalServer.url},
           },
         }),
       ]).create();
 
       await pubCommand(
         command,
-        silent: contains('${globalPackageServer.url}/api/packages/foo'),
+        silent: contains('${globalServer.url}/api/packages/foo'),
       );
     });
 
     test('normalizes extra slash', () async {
-      await servePackages((b) => b..serve('foo', '1.2.3'));
+      final server = await servePackages();
+      server.serve('foo', '1.2.3');
 
       await d.dir(appPath, [
         d.appPubspec({
           'foo': {
-            'hosted': {'name': 'foo', 'url': globalPackageServer.url + '/'},
+            'hosted': {'name': 'foo', 'url': globalServer.url + '/'},
           },
         }),
       ]).create();
 
       await pubCommand(
         command,
-        silent: contains('${globalPackageServer.url}/api/packages/foo'),
+        silent: contains('${globalServer.url}/api/packages/foo'),
       );
     });
 
     test('cannot normalize double slash', () async {
-      await servePackages((b) => b..serve('foo', '1.2.3'));
-      globalPackageServer.expect(
+      final server = await servePackages();
+      server.serve('foo', '1.2.3');
+      globalServer.expect(
         'GET',
         '//api/packages/foo',
         (request) => Response.notFound(''),
@@ -64,15 +65,14 @@
       await d.dir(appPath, [
         d.appPubspec({
           'foo': {
-            'hosted': {'name': 'foo', 'url': globalPackageServer.url + '//'},
+            'hosted': {'name': 'foo', 'url': globalServer.url + '//'},
           },
         }),
       ]).create();
 
       await pubCommand(
         command,
-        error: contains(
-            'could not find package foo at ${globalPackageServer.url}//'),
+        error: contains('could not find package foo at ${globalServer.url}//'),
         exitCode: exit_codes.UNAVAILABLE,
       );
     });
@@ -82,27 +82,31 @@
     /// This is a bit of a hack, to easily test if hosted pub URLs with a path
     /// segment works and if the slashes are normalized.
     void _proxyMyFolderToRoot() {
-      globalPackageServer.extraHandlers[RegExp('/my-folder/.*')] = (r) async {
-        if (r.method != 'GET' && r.method != 'HEAD') {
-          return Response.forbidden(null);
-        }
-        final path = r.requestedUri.path.substring('/my-folder/'.length);
-        final res = await http.get(
-          Uri.parse(globalPackageServer.url + '/$path'),
-        );
-        return Response(res.statusCode, body: res.bodyBytes, headers: {
-          'Content-Type': res.headers['Content-Type'],
-        });
-      };
+      globalServer.handle(
+        RegExp('/my-folder/.*'),
+        (r) async {
+          if (r.method != 'GET' && r.method != 'HEAD') {
+            return Response.forbidden(null);
+          }
+          final path = r.requestedUri.path.substring('/my-folder/'.length);
+          final res = await http.get(
+            Uri.parse(globalServer.url + '/$path'),
+          );
+          return Response(res.statusCode, body: res.bodyBytes, headers: {
+            'Content-Type': res.headers['content-type']!,
+          });
+        },
+      );
     }
 
     test('will use normalized url with path', () async {
-      await servePackages((b) => b..serve('foo', '1.2.3'));
+      final server = await servePackages();
+      server.serve('foo', '1.2.3');
       _proxyMyFolderToRoot();
 
       // testing with a normalized URL
-      final testUrl = globalPackageServer.url + '/my-folder/';
-      final normalizedUrl = globalPackageServer.url + '/my-folder/';
+      final testUrl = globalServer.url + '/my-folder/';
+      final normalizedUrl = globalServer.url + '/my-folder/';
 
       await d.dir(appPath, [
         d.appPubspec({
@@ -120,12 +124,13 @@
     });
 
     test('will normalize url with path by adding slash', () async {
-      await servePackages((b) => b..serve('foo', '1.2.3'));
+      final server = await servePackages();
+      server.serve('foo', '1.2.3');
       _proxyMyFolderToRoot();
 
       // Testing with a URL that is missing the slash.
-      final testUrl = globalPackageServer.url + '/my-folder';
-      final normalizedUrl = globalPackageServer.url + '/my-folder/';
+      final testUrl = globalServer.url + '/my-folder';
+      final normalizedUrl = globalServer.url + '/my-folder/';
 
       await d.dir(appPath, [
         d.appPubspec({
diff --git a/test/ignore_test.dart b/test/ignore_test.dart
index 75238b5..42a189a 100644
--- a/test/ignore_test.dart
+++ b/test/ignore_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:pub/src/ignore.dart';
@@ -41,10 +39,10 @@
           return [path.substring(0, nextSlash == -1 ? path.length : nextSlash)];
         }
 
-        Ignore ignoreForDir(String dir) => c.patterns[dir] == null
+        Ignore? ignoreForDir(String dir) => c.patterns[dir] == null
             ? null
             : Ignore(
-                c.patterns[dir],
+                c.patterns[dir]!,
                 onInvalidPattern: (_, __) => hasWarning = true,
                 ignoreCase: ignoreCase,
               );
@@ -87,17 +85,18 @@
 
     for (final c in testData) {
       c.paths.forEach((path, expected) {
-        if (c.ignoreCase == null) {
+        var ignoreCase = c.ignoreCase;
+        if (ignoreCase == null) {
           _testIgnorePath(c, path, expected, false);
           _testIgnorePath(c, path, expected, true);
         } else {
-          _testIgnorePath(c, path, expected, c.ignoreCase);
+          _testIgnorePath(c, path, expected, ignoreCase);
         }
       });
     }
   });
 
-  ProcessResult runGit(List<String> args, {String workingDirectory}) {
+  ProcessResult runGit(List<String> args, {String? workingDirectory}) {
     final executable = Platform.isWindows ? 'cmd' : 'git';
     args = Platform.isWindows ? ['/c', 'git', ...args] : args;
     return Process.runSync(executable, args,
@@ -105,24 +104,24 @@
   }
 
   group('git', () {
-    Directory tmp;
+    Directory? tmp;
 
     setUpAll(() async {
       tmp = await Directory.systemTemp.createTemp('package-ignore-test-');
 
-      final ret = runGit(['init'], workingDirectory: tmp.path);
+      final ret = runGit(['init'], workingDirectory: tmp!.path);
       expect(ret.exitCode, equals(0),
           reason:
               'Running "git init" failed. StdErr: ${ret.stderr} StdOut: ${ret.stdout}');
     });
 
     tearDownAll(() async {
-      await tmp.delete(recursive: true);
+      await tmp!.delete(recursive: true);
       tmp = null;
     });
 
     tearDown(() async {
-      runGit(['clean', '-f', '-d', '-x'], workingDirectory: tmp.path);
+      runGit(['clean', '-f', '-d', '-x'], workingDirectory: tmp!.path);
     });
 
     void _testIgnorePath(
@@ -137,7 +136,7 @@
         expect(
           runGit(
             ['config', '--local', 'core.ignoreCase', ignoreCase.toString()],
-            workingDirectory: tmp.path,
+            workingDirectory: tmp!.path,
           ).exitCode,
           anyOf(0, 1),
           reason: 'Running "git config --local core.ignoreCase ..." failed',
@@ -145,17 +144,17 @@
 
         for (final directory in c.patterns.keys) {
           final resolvedDirectory =
-              directory == '' ? tmp.uri : tmp.uri.resolve(directory + '/');
+              directory == '' ? tmp!.uri : tmp!.uri.resolve(directory + '/');
           Directory.fromUri(resolvedDirectory).createSync(recursive: true);
           final gitIgnore =
               File.fromUri(resolvedDirectory.resolve('.gitignore'));
           gitIgnore.writeAsStringSync(
-            c.patterns[directory].join('\n') + '\n',
+            c.patterns[directory]!.join('\n') + '\n',
           );
         }
         final process = runGit(
-            ['-C', tmp.path, 'check-ignore', '--no-index', path],
-            workingDirectory: tmp.path);
+            ['-C', tmp!.path, 'check-ignore', '--no-index', path],
+            workingDirectory: tmp!.path);
         expect(process.exitCode, anyOf(0, 1),
             reason: 'Running "git check-ignore" failed');
         final ignored = process.exitCode == 0;
@@ -172,11 +171,12 @@
 
     for (final c in testData) {
       c.paths.forEach((path, expected) {
-        if (c.ignoreCase == null) {
+        var ignoreCase = c.ignoreCase;
+        if (ignoreCase == null) {
           _testIgnorePath(c, path, expected, false);
           _testIgnorePath(c, path, expected, true);
         } else {
-          _testIgnorePath(c, path, expected, c.ignoreCase);
+          _testIgnorePath(c, path, expected, ignoreCase);
         }
       });
     }
@@ -200,7 +200,7 @@
   final bool skipOnWindows;
 
   /// Test with `core.ignoreCase` set to `true`, `false` or both (if `null`).
-  final bool ignoreCase;
+  final bool? ignoreCase;
 
   TestData(
     this.name,
diff --git a/test/io_test.dart b/test/io_test.dart
index b54bc91..2c529cd 100644
--- a/test/io_test.dart
+++ b/test/io_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
@@ -463,14 +461,14 @@
 }
 
 void testExistencePredicate(String name, bool Function(String path) predicate,
-    {bool forFile,
-    bool forFileSymlink,
-    bool forMultiLevelFileSymlink,
-    bool forDirectory,
-    bool forDirectorySymlink,
-    bool forMultiLevelDirectorySymlink,
-    bool forBrokenSymlink,
-    bool forMultiLevelBrokenSymlink}) {
+    {required bool forFile,
+    required bool forFileSymlink,
+    required bool forMultiLevelFileSymlink,
+    required bool forDirectory,
+    required bool forDirectorySymlink,
+    required bool forMultiLevelDirectorySymlink,
+    required bool forBrokenSymlink,
+    required bool forMultiLevelBrokenSymlink}) {
   group(name, () {
     test('returns $forFile for a file', () {
       expect(withTempDir((temp) {
diff --git a/test/levenshtein_test.dart b/test/levenshtein_test.dart
index 6d113c7..67361af 100644
--- a/test/levenshtein_test.dart
+++ b/test/levenshtein_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/levenshtein.dart';
 import 'package:test/test.dart';
 
diff --git a/test/lish/archives_and_uploads_a_package_test.dart b/test/lish/archives_and_uploads_a_package_test.dart
index e835281..88e4862 100644
--- a/test/lish/archives_and_uploads_a_package_test.dart
+++ b/test/lish/archives_and_uploads_a_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:path/path.dart' as p;
@@ -21,14 +19,14 @@
 
   test('archives and uploads a package', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
-    handleUploadForm(globalPackageServer);
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer);
+    handleUpload(globalServer);
 
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.ok(jsonEncode({
         'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
       }));
@@ -44,21 +42,21 @@
     await d.tokensFile({
       'version': 1,
       'hosted': [
-        {'url': globalPackageServer.url + '/sub/folder', 'env': 'TOKEN'},
+        {'url': globalServer.url + '/sub/folder', 'env': 'TOKEN'},
       ]
     }).create();
     var pub = await startPublish(
-      globalPackageServer,
+      globalServer,
       path: '/sub/folder',
       authMethod: 'token',
       environment: {'TOKEN': 'access token'},
     );
 
     await confirmPublish(pub);
-    handleUploadForm(globalPackageServer, path: '/sub/folder');
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer, path: '/sub/folder');
+    handleUpload(globalServer);
 
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.ok(jsonEncode({
         'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
       }));
@@ -85,14 +83,14 @@
     await d.dir(p.join(appPath, 'empty')).create();
 
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
-    handleUploadForm(globalPackageServer);
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer);
+    handleUpload(globalServer);
 
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.ok(jsonEncode({
         'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
       }));
diff --git a/test/lish/cloud_storage_upload_doesnt_redirect_test.dart b/test/lish/cloud_storage_upload_doesnt_redirect_test.dart
index f2e542f..0f792d5 100644
--- a/test/lish/cloud_storage_upload_doesnt_redirect_test.dart
+++ b/test/lish/cloud_storage_upload_doesnt_redirect_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
 
@@ -16,13 +14,13 @@
 
   test("cloud storage upload doesn't redirect", () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
-    handleUploadForm(globalPackageServer);
+    handleUploadForm(globalServer);
 
-    globalPackageServer.expect('POST', '/upload', (request) async {
+    globalServer.expect('POST', '/upload', (request) async {
       await request.read().drain();
       return shelf.Response(200);
     });
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 a67d85b..5dec03d 100644
--- a/test/lish/cloud_storage_upload_provides_an_error_test.dart
+++ b/test/lish/cloud_storage_upload_provides_an_error_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
 
@@ -16,13 +14,13 @@
 
   test('cloud storage upload provides an error', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
-    handleUploadForm(globalPackageServer);
+    handleUploadForm(globalServer);
 
-    globalPackageServer.expect('POST', '/upload', (request) {
+    globalServer.expect('POST', '/upload', (request) {
       return request.read().drain().then((_) {
         return shelf.Response.notFound(
             '<Error><Message>Your request sucked.</Message></Error>',
diff --git a/test/lish/does_not_include_dot_file.dart b/test/lish/does_not_include_dot_file.dart
index 6dfa622..cec8ab0 100644
--- a/test/lish/does_not_include_dot_file.dart
+++ b/test/lish/does_not_include_dot_file.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -32,14 +30,14 @@
 
   test('Check if package doesn\'t include dot-files', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
-    handleUploadForm(globalPackageServer);
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer);
+    handleUpload(globalServer);
 
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.ok(jsonEncode({
         'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
       }));
diff --git a/test/lish/does_not_publish_if_private_test.dart b/test/lish/does_not_publish_if_private_test.dart
index 9ab8712..52321c2 100644
--- a/test/lish/does_not_publish_if_private_test.dart
+++ b/test/lish/does_not_publish_if_private_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/lish/does_not_publish_if_private_with_server_arg_test.dart b/test/lish/does_not_publish_if_private_with_server_arg_test.dart
index c33b1a3..689609b 100644
--- a/test/lish/does_not_publish_if_private_with_server_arg_test.dart
+++ b/test/lish/does_not_publish_if_private_with_server_arg_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/lish/dry_run_warns_about_server_checks.dart b/test/lish/dry_run_warns_about_server_checks.dart
index 8e12f9b..ad7abe0 100644
--- a/test/lish/dry_run_warns_about_server_checks.dart
+++ b/test/lish/dry_run_warns_about_server_checks.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
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 6e77aa3..9d2233c 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
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/lish/force_does_not_publish_if_private_test.dart b/test/lish/force_does_not_publish_if_private_test.dart
index 9ca4bf6..0d4ad59 100644
--- a/test/lish/force_does_not_publish_if_private_test.dart
+++ b/test/lish/force_does_not_publish_if_private_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
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 26978ad..481f627 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,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -23,7 +21,7 @@
     ]).create();
 
     await servePackages();
-    var pub = await startPublish(globalPackageServer, args: ['--force']);
+    var pub = await startPublish(globalServer, args: ['--force']);
 
     await pub.shouldExit(exit_codes.DATA);
     expect(
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 59c8233..c5d8957 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
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -19,13 +17,13 @@
 
   test('--force publishes if there are no warnings or errors', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer, args: ['--force']);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer, args: ['--force']);
 
-    handleUploadForm(globalPackageServer);
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer);
+    handleUpload(globalServer);
 
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.ok(jsonEncode({
         'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
       }));
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 c217b29..9fb3d53 100644
--- a/test/lish/force_publishes_if_there_are_warnings_test.dart
+++ b/test/lish/force_publishes_if_there_are_warnings_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -24,13 +22,13 @@
     await d.dir(appPath, [d.pubspec(pkg)]).create();
 
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer, args: ['--force']);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer, args: ['--force']);
 
-    handleUploadForm(globalPackageServer);
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer);
+    handleUpload(globalServer);
 
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.ok(jsonEncode({
         'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
       }));
diff --git a/test/lish/many_files_test.dart b/test/lish/many_files_test.dart
index 02db6b2..36f4ed7 100644
--- a/test/lish/many_files_test.dart
+++ b/test/lish/many_files_test.dart
@@ -2,11 +2,8 @@
 // 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.
 
-// @dart=2.10
-
 import 'dart:convert';
 import 'dart:io';
-import 'dart:math' as math;
 
 import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -38,7 +35,7 @@
     int argMax;
     if (Platform.isWindows) {
       // On Windows, the maximum argument list length is 8^5 bytes.
-      argMax = math.pow(8, 5);
+      argMax = 32768; // 8^5
     } else {
       // On POSIX, the maximum argument list length can be retrieved
       // automatically.
@@ -76,14 +73,14 @@
     }
 
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
-    handleUploadForm(globalPackageServer);
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer);
+    handleUpload(globalServer);
 
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.ok(jsonEncode({
         'success': {'message': '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 d78e495..7ab0bcd 100644
--- a/test/lish/package_creation_provides_a_malformed_error_test.dart
+++ b/test/lish/package_creation_provides_a_malformed_error_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:shelf/shelf.dart' as shelf;
@@ -18,15 +16,15 @@
 
   test('package creation provides a malformed error', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
-    handleUploadForm(globalPackageServer);
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer);
+    handleUpload(globalServer);
 
     var body = {'error': 'Your package was too boring.'};
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.notFound(jsonEncode(body));
     });
 
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 67c10ef..089d09e 100644
--- a/test/lish/package_creation_provides_a_malformed_success_test.dart
+++ b/test/lish/package_creation_provides_a_malformed_success_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:shelf/shelf.dart' as shelf;
@@ -18,15 +16,15 @@
 
   test('package creation provides a malformed success', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
-    handleUploadForm(globalPackageServer);
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer);
+    handleUpload(globalServer);
 
     var body = {'success': 'Your package was awesome.'};
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.ok(jsonEncode(body));
     });
 
diff --git a/test/lish/package_creation_provides_an_error_test.dart b/test/lish/package_creation_provides_an_error_test.dart
index 49166c1..f5ff128 100644
--- a/test/lish/package_creation_provides_an_error_test.dart
+++ b/test/lish/package_creation_provides_an_error_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:shelf/shelf.dart' as shelf;
@@ -18,14 +16,14 @@
 
   test('package creation provides an error', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
-    handleUploadForm(globalPackageServer);
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer);
+    handleUpload(globalServer);
 
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.notFound(jsonEncode({
         'error': {'message': 'Your package was too boring.'}
       }));
diff --git a/test/lish/package_creation_provides_invalid_json_test.dart b/test/lish/package_creation_provides_invalid_json_test.dart
index 8cdfd5b..2cd6212 100644
--- a/test/lish/package_creation_provides_invalid_json_test.dart
+++ b/test/lish/package_creation_provides_invalid_json_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
 
@@ -16,14 +14,14 @@
 
   test('package creation provides invalid JSON', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
-    handleUploadForm(globalPackageServer);
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer);
+    handleUpload(globalServer);
 
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.ok('{not json');
     });
 
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 ec55be9..c39dbc4 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
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -24,13 +22,13 @@
     await d.dir(appPath, [d.pubspec(pkg)]).create();
 
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
     pub.stdin.writeln('y');
-    handleUploadForm(globalPackageServer);
-    handleUpload(globalPackageServer);
+    handleUploadForm(globalServer);
+    handleUpload(globalServer);
 
-    globalPackageServer.expect('GET', '/create', (request) {
+    globalServer.expect('GET', '/create', (request) {
       return shelf.Response.ok(jsonEncode({
         'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
       }));
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 fbdacc4..0d5a563 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
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -20,7 +18,7 @@
     await d.dir(appPath, [d.pubspec(pkg)]).create();
 
     await servePackages();
-    var pub = await startPublish(globalPackageServer);
+    var pub = await startPublish(globalServer);
 
     pub.stdin.writeln('n');
     await pub.shouldExit(exit_codes.DATA);
diff --git a/test/lish/package_validation_has_an_error_test.dart b/test/lish/package_validation_has_an_error_test.dart
index 9fab3a5..14c83c0 100644
--- a/test/lish/package_validation_has_an_error_test.dart
+++ b/test/lish/package_validation_has_an_error_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
@@ -23,7 +21,7 @@
     ]).create();
 
     await servePackages();
-    var pub = await startPublish(globalPackageServer);
+    var pub = await startPublish(globalServer);
 
     await pub.shouldExit(exit_codes.DATA);
     expect(
diff --git a/test/lish/preview_errors_if_private_test.dart b/test/lish/preview_errors_if_private_test.dart
index c816c6e..fb7160a 100644
--- a/test/lish/preview_errors_if_private_test.dart
+++ b/test/lish/preview_errors_if_private_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 
 import 'package:test/test.dart';
diff --git a/test/lish/preview_package_validation_has_a_warning_test.dart b/test/lish/preview_package_validation_has_a_warning_test.dart
index c3aa01d..69f59af 100644
--- a/test/lish/preview_package_validation_has_a_warning_test.dart
+++ b/test/lish/preview_package_validation_has_a_warning_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 
 import 'package:test/test.dart';
@@ -21,7 +19,7 @@
     await d.dir(appPath, [d.pubspec(pkg)]).create();
 
     await servePackages();
-    var pub = await startPublish(globalPackageServer, args: ['--dry-run']);
+    var pub = await startPublish(globalServer, args: ['--dry-run']);
 
     await pub.shouldExit(exit_codes.DATA);
     expect(
diff --git a/test/lish/preview_package_validation_has_no_warnings_test.dart b/test/lish/preview_package_validation_has_no_warnings_test.dart
index 586708c..179c648 100644
--- a/test/lish/preview_package_validation_has_no_warnings_test.dart
+++ b/test/lish/preview_package_validation_has_no_warnings_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 
 import 'package:test/test.dart';
@@ -19,8 +17,8 @@
         packageMap('test_pkg', '1.0.0', null, null, {'sdk': '>=1.8.0 <2.0.0'});
     await d.dir(appPath, [d.pubspec(pkg)]).create();
 
-    await servePackages((_) {});
-    var pub = await startPublish(globalPackageServer, args: ['--dry-run']);
+    await servePackages();
+    var pub = await startPublish(globalServer, args: ['--dry-run']);
 
     await pub.shouldExit(exit_codes.SUCCESS);
     expect(pub.stderr, emitsThrough('Package has 0 warnings.'));
diff --git a/test/lish/server_arg_does_not_override_private_test.dart b/test/lish/server_arg_does_not_override_private_test.dart
index baba7d6..58a1af1 100644
--- a/test/lish/server_arg_does_not_override_private_test.dart
+++ b/test/lish/server_arg_does_not_override_private_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 
 import 'package:test/test.dart';
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 508c0b3..1597146 100644
--- a/test/lish/server_arg_overrides_publish_to_url_test.dart
+++ b/test/lish/server_arg_overrides_publish_to_url_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 
 import 'package:test/test.dart';
@@ -15,16 +13,15 @@
   test('an explicit --server argument overrides a "publish_to" url', () async {
     // Create a real server that can reject requests because validators will
     // try to ping it, and will use multiple retries when doing so.
-    final packageServer = await DescriptorServer.start();
-    final fakePackageServer = 'http://localhost:${packageServer.port}';
+    final packageServer = await startPackageServer();
 
     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', fakePackageServer],
-        output: contains(fakePackageServer),
+        args: ['lish', '--dry-run', '--server', packageServer.url],
+        output: contains(packageServer.url),
         exitCode: exit_codes.DATA);
 
     await packageServer.close();
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 15f1cbb..78a54fa 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
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:test/test.dart';
@@ -16,9 +14,9 @@
   setUp(d.validPackage.create);
 
   test('upload form fields has a non-string value', () async {
-    await servePackages((_) {});
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await servePackages();
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
 
@@ -26,7 +24,7 @@
       'url': 'http://example.com/upload',
       'fields': {'field': 12}
     };
-    handleUploadForm(globalPackageServer, body: body);
+    handleUploadForm(globalServer, body: body);
     expect(pub.stderr, emits('Invalid server response:'));
     expect(pub.stderr, emits(jsonEncode(body)));
     await pub.shouldExit(1);
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 aea6454..d18c1ee 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
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:test/test.dart';
@@ -17,13 +15,13 @@
 
   test('upload form fields is not a map', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
 
     var body = {'url': 'http://example.com/upload', 'fields': 12};
-    handleUploadForm(globalPackageServer, body: body);
+    handleUploadForm(globalServer, body: body);
     expect(pub.stderr, emits('Invalid server response:'));
     expect(pub.stderr, emits(jsonEncode(body)));
     await pub.shouldExit(1);
diff --git a/test/lish/upload_form_is_missing_fields_test.dart b/test/lish/upload_form_is_missing_fields_test.dart
index 3a36672..b0032f8 100644
--- a/test/lish/upload_form_is_missing_fields_test.dart
+++ b/test/lish/upload_form_is_missing_fields_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:test/test.dart';
@@ -17,13 +15,13 @@
 
   test('upload form is missing fields', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
 
     var body = {'url': 'http://example.com/upload'};
-    handleUploadForm(globalPackageServer, body: body);
+    handleUploadForm(globalServer, body: body);
     expect(pub.stderr, emits('Invalid server response:'));
     expect(pub.stderr, emits(jsonEncode(body)));
     await pub.shouldExit(1);
diff --git a/test/lish/upload_form_is_missing_url_test.dart b/test/lish/upload_form_is_missing_url_test.dart
index 96224e4..eae43ea 100644
--- a/test/lish/upload_form_is_missing_url_test.dart
+++ b/test/lish/upload_form_is_missing_url_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:test/test.dart';
@@ -17,8 +15,8 @@
 
   test('upload form is missing url', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
 
@@ -26,7 +24,7 @@
       'fields': {'field1': 'value1', 'field2': 'value2'}
     };
 
-    handleUploadForm(globalPackageServer, body: body);
+    handleUploadForm(globalServer, body: body);
     expect(pub.stderr, emits('Invalid server response:'));
     expect(pub.stderr, emits(jsonEncode(body)));
     await pub.shouldExit(1);
diff --git a/test/lish/upload_form_provides_an_error_test.dart b/test/lish/upload_form_provides_an_error_test.dart
index c5fd41e..35932b8 100644
--- a/test/lish/upload_form_provides_an_error_test.dart
+++ b/test/lish/upload_form_provides_an_error_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:shelf/shelf.dart' as shelf;
@@ -16,15 +14,13 @@
   setUp(d.validPackage.create);
 
   test('upload form provides an error', () async {
-    await servePackages((_) {});
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await servePackages();
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
 
-    globalPackageServer.extraHandlers['/api/packages/versions/new'] =
-        expectAsync1((request) {
-      expect(request.method, 'GET');
+    globalServer.expect('GET', '/api/packages/versions/new', (request) async {
       return shelf.Response.notFound(jsonEncode({
         'error': {'message': 'your request sucked'}
       }));
diff --git a/test/lish/upload_form_provides_invalid_json_test.dart b/test/lish/upload_form_provides_invalid_json_test.dart
index a4fa5d7..a046755 100644
--- a/test/lish/upload_form_provides_invalid_json_test.dart
+++ b/test/lish/upload_form_provides_invalid_json_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
 
@@ -15,12 +13,12 @@
 
   test('upload form provides invalid JSON', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
 
-    globalPackageServer.expect('GET', '/api/packages/versions/new',
+    globalServer.expect('GET', '/api/packages/versions/new',
         (request) => shelf.Response.ok('{not json'));
 
     expect(
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 ba7559a..f69fd1f 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
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:test/test.dart';
@@ -17,8 +15,8 @@
 
   test('upload form url is not a string', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
 
@@ -27,7 +25,7 @@
       'fields': {'field1': 'value1', 'field2': 'value2'}
     };
 
-    handleUploadForm(globalPackageServer, body: body);
+    handleUploadForm(globalServer, body: body);
     expect(pub.stderr, emits('Invalid server response:'));
     expect(pub.stderr, emits(jsonEncode(body)));
     await pub.shouldExit(1);
diff --git a/test/lish/uses_publish_to_url_test.dart b/test/lish/uses_publish_to_url_test.dart
index e7f9cf3..47496f7 100644
--- a/test/lish/uses_publish_to_url_test.dart
+++ b/test/lish/uses_publish_to_url_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 
 import 'package:test/test.dart';
diff --git a/test/lish/utils.dart b/test/lish/utils.dart
index ae0960e..f134e4a 100644
--- a/test/lish/utils.dart
+++ b/test/lish/utils.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:shelf/shelf.dart' as shelf;
@@ -11,7 +9,7 @@
 
 import '../test_pub.dart';
 
-void handleUploadForm(PackageServer server, {Map body, String path = ''}) {
+void handleUploadForm(PackageServer server, {Map? body, String path = ''}) {
   server.expect('GET', '$path/api/packages/versions/new', (request) {
     expect(
         request.headers, containsPair('authorization', 'Bearer access token'));
diff --git a/test/list_package_dirs/ignores_updated_pubspec_test.dart b/test/list_package_dirs/ignores_updated_pubspec_test.dart
index edec570..2524681 100644
--- a/test/list_package_dirs/ignores_updated_pubspec_test.dart
+++ b/test/list_package_dirs/ignores_updated_pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/io.dart';
 
diff --git a/test/list_package_dirs/includes_dev_dependencies_test.dart b/test/list_package_dirs/includes_dev_dependencies_test.dart
index 10f4f56..61cc56b 100644
--- a/test/list_package_dirs/includes_dev_dependencies_test.dart
+++ b/test/list_package_dirs/includes_dev_dependencies_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/io.dart';
 
diff --git a/test/list_package_dirs/lists_dependency_directories_test.dart b/test/list_package_dirs/lists_dependency_directories_test.dart
index 5d5b982..2cd9664 100644
--- a/test/list_package_dirs/lists_dependency_directories_test.dart
+++ b/test/list_package_dirs/lists_dependency_directories_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/io.dart';
 
@@ -14,7 +12,8 @@
 
 void main() {
   test('prints the local paths to all packages in the lockfile', () async {
-    await servePackages((builder) => builder.serve('bar', '1.0.0'));
+    final server = await servePackages()
+      ..serve('bar', '1.0.0');
 
     await d
         .dir('foo', [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
@@ -39,7 +38,7 @@
       'packages': {
         'foo': path.join(d.sandbox, 'foo', 'lib'),
         'bar': path.join(d.sandbox, cachePath, 'hosted',
-            'localhost%58${globalServer.port}', 'bar-1.0.0', 'lib'),
+            'localhost%58${server.port}', 'bar-1.0.0', 'lib'),
         'myapp': canonicalize(path.join(d.sandbox, appPath, 'lib'))
       },
       'input_files': [
diff --git a/test/list_package_dirs/lockfile_error_test.dart b/test/list_package_dirs/lockfile_error_test.dart
index 16860f4..f4440ec 100644
--- a/test/list_package_dirs/lockfile_error_test.dart
+++ b/test/list_package_dirs/lockfile_error_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:pub/src/io.dart';
diff --git a/test/list_package_dirs/missing_pubspec_test.dart b/test/list_package_dirs/missing_pubspec_test.dart
index d3c61de..83a58c2 100644
--- a/test/list_package_dirs/missing_pubspec_test.dart
+++ b/test/list_package_dirs/missing_pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:pub/src/io.dart';
diff --git a/test/list_package_dirs/no_lockfile_test.dart b/test/list_package_dirs/no_lockfile_test.dart
index 9e1078b..5939099 100644
--- a/test/list_package_dirs/no_lockfile_test.dart
+++ b/test/list_package_dirs/no_lockfile_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 
 import 'package:test/test.dart';
diff --git a/test/list_package_dirs/pubspec_error_test.dart b/test/list_package_dirs/pubspec_error_test.dart
index 321e555..c282c5c 100644
--- a/test/list_package_dirs/pubspec_error_test.dart
+++ b/test/list_package_dirs/pubspec_error_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:pub/src/io.dart';
diff --git a/test/lock_file_test.dart b/test/lock_file_test.dart
index 2faf8c5..4360c7c 100644
--- a/test/lock_file_test.dart
+++ b/test/lock_file_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/language_version.dart';
 import 'package:pub/src/lock_file.dart';
 import 'package:pub/src/package_name.dart';
@@ -24,14 +22,14 @@
 
   @override
   PackageRef parseRef(String name, description,
-      {String containingPath, LanguageVersion languageVersion}) {
+      {String? containingPath, LanguageVersion? languageVersion}) {
     if (!description.endsWith(' desc')) throw FormatException('Bad');
     return PackageRef(name, this, description);
   }
 
   @override
   PackageId parseId(String name, Version version, description,
-      {String containingPath}) {
+      {String? containingPath}) {
     if (!description.endsWith(' desc')) throw FormatException('Bad');
     return PackageId(name, this, version, description);
   }
@@ -81,13 +79,13 @@
 
         expect(lockFile.packages.length, equals(2));
 
-        var bar = lockFile.packages['bar'];
+        var bar = lockFile.packages['bar']!;
         expect(bar.name, equals('bar'));
         expect(bar.version, equals(Version(1, 2, 3)));
         expect(bar.source, equals(fakeSource));
         expect(bar.description, equals('bar desc'));
 
-        var foo = lockFile.packages['foo'];
+        var foo = lockFile.packages['foo']!;
         expect(foo.name, equals('foo'));
         expect(foo.version, equals(Version(2, 3, 4)));
         expect(foo.source, equals(fakeSource));
@@ -102,7 +100,7 @@
     version: 1.2.3
     description: foo desc
 ''', sources);
-        var foo = lockFile.packages['foo'];
+        var foo = lockFile.packages['foo']!;
         expect(foo.source, equals(sources['bad']));
       });
 
@@ -263,7 +261,7 @@
       });
 
       expect(
-          loadYaml(lockfile.serialize(null)),
+          loadYaml(lockfile.serialize('')),
           equals({
             'sdks': {'dart': 'any'},
             'packages': {
diff --git a/test/must_pub_get_test.dart b/test/must_pub_get_test.dart
index edea182..dfc09d7 100644
--- a/test/must_pub_get_test.dart
+++ b/test/must_pub_get_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
@@ -16,12 +14,14 @@
 import 'descriptor.dart' as d;
 import 'test_pub.dart';
 
+late PackageServer server;
+
 void main() {
   setUp(() async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '2.0.0');
-    });
+    server = await servePackages();
+
+    server.serve('foo', '1.0.0');
+    server.serve('foo', '2.0.0');
 
     await d.dir(appPath, [
       d.appPubspec(),
@@ -334,10 +334,8 @@
       setUp(() async {
         // Avoid using a path dependency because it triggers the full validation
         // logic. We want to be sure SDK-validation works without that logic.
-        globalPackageServer.add((builder) {
-          builder.serve('foo', '3.0.0', pubspec: {
-            'environment': {'sdk': '>=1.0.0 <2.0.0'}
-          });
+        server.serve('foo', '3.0.0', pubspec: {
+          'environment': {'sdk': '>=1.0.0 <2.0.0'}
         });
 
         await d.dir(appPath, [
@@ -362,10 +360,8 @@
         'current Flutter SDK', () async {
       // Avoid using a path dependency because it triggers the full validation
       // logic. We want to be sure SDK-validation works without that logic.
-      globalPackageServer.add((builder) {
-        builder.serve('foo', '3.0.0', pubspec: {
-          'environment': {'flutter': '>=1.0.0 <2.0.0'}
-        });
+      server.serve('foo', '3.0.0', pubspec: {
+        'environment': {'flutter': '>=1.0.0 <2.0.0'}
       });
 
       await d.dir('flutter', [d.file('version', '1.2.3')]).create();
@@ -524,10 +520,8 @@
 
     group("an overridden dependency's SDK constraint is unmatched", () {
       setUp(() async {
-        globalPackageServer.add((builder) {
-          builder.serve('bar', '1.0.0', pubspec: {
-            'environment': {'sdk': '0.0.0-fake'}
-          });
+        server.serve('bar', '1.0.0', pubspec: {
+          'environment': {'sdk': '0.0.0-fake'}
         });
 
         await d.dir(appPath, [
@@ -549,10 +543,8 @@
         () async {
       // Avoid using a path dependency because it triggers the full validation
       // logic. We want to be sure SDK-validation works without that logic.
-      globalPackageServer.add((builder) {
-        builder.serve('foo', '3.0.0', pubspec: {
-          'environment': {'flutter': '>=1.0.0 <2.0.0'}
-        });
+      server.serve('foo', '3.0.0', pubspec: {
+        'environment': {'flutter': '>=1.0.0 <2.0.0'}
       });
 
       await d.dir('flutter', [d.file('version', '1.2.3')]).create();
diff --git a/test/no_packages_dir_test.dart b/test/no_packages_dir_test.dart
index cdd6351..3a88bc5 100644
--- a/test/no_packages_dir_test.dart
+++ b/test/no_packages_dir_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import 'descriptor.dart' as d;
diff --git a/test/oauth2/logout_test.dart b/test/oauth2/logout_test.dart
index 81d4125..a12a652 100644
--- a/test/oauth2/logout_test.dart
+++ b/test/oauth2/logout_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -13,7 +11,7 @@
   test('with an existing credentials file, deletes it.', () async {
     await servePackages();
     await d
-        .credentialsFile(globalPackageServer, 'access token',
+        .credentialsFile(globalServer, 'access token',
             refreshToken: 'refresh token',
             expiration: DateTime.now().add(Duration(hours: 1)))
         .create();
@@ -30,7 +28,7 @@
     await servePackages();
     await d
         .credentialsFile(
-          globalPackageServer,
+          globalServer,
           'access token',
           refreshToken: 'refresh token',
           expiration: DateTime.now().add(Duration(hours: 1)),
@@ -39,7 +37,7 @@
 
     await d
         .legacyCredentialsFile(
-          globalPackageServer,
+          globalServer,
           'access token',
           refreshToken: 'refresh token',
           expiration: DateTime.now().add(Duration(hours: 1)),
diff --git a/test/oauth2/utils.dart b/test/oauth2/utils.dart
index b7d765e..dab8c92 100644
--- a/test/oauth2/utils.dart
+++ b/test/oauth2/utils.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async';
 import 'dart:convert';
 
@@ -24,10 +22,10 @@
 
   var line = await pub.stdout.next;
   var match =
-      RegExp(r'[?&]redirect_uri=([0-9a-zA-Z.%+-]+)[$&]').firstMatch(line);
+      RegExp(r'[?&]redirect_uri=([0-9a-zA-Z.%+-]+)[$&]').firstMatch(line)!;
   expect(match, isNotNull);
 
-  var redirectUrl = Uri.parse(Uri.decodeComponent(match.group(1)));
+  var redirectUrl = Uri.parse(Uri.decodeComponent(match.group(1)!));
   redirectUrl = _addQueryParameters(redirectUrl, {'code': 'access code'});
 
   // Expect the /token request
@@ -61,8 +59,8 @@
 }
 
 /// Convert a [Map] from parameter names to values to a URL query string.
-String _mapToQuery(Map<String, String> map) {
-  var pairs = <List<String>>[];
+String _mapToQuery(Map<String, String?> map) {
+  var pairs = <List<String?>>[];
   map.forEach((key, value) {
     key = Uri.encodeQueryComponent(key);
     value = (value == null || value.isEmpty)
diff --git a/test/oauth2/with_a_malformed_credentials_authenticates_again_test.dart b/test/oauth2/with_a_malformed_credentials_authenticates_again_test.dart
index 5585526..75b47ab 100644
--- a/test/oauth2/with_a_malformed_credentials_authenticates_again_test.dart
+++ b/test/oauth2/with_a_malformed_credentials_authenticates_again_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
 
@@ -21,11 +19,11 @@
     await d.dir(
         configPath, [d.file('pub-credentials.json', '{bad json')]).create();
 
-    var pub = await startPublish(globalPackageServer);
+    var pub = await startPublish(globalServer);
     await confirmPublish(pub);
-    await authorizePub(pub, globalPackageServer, 'new access token');
+    await authorizePub(pub, globalServer, 'new access token');
 
-    globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+    globalServer.expect('GET', '/api/packages/versions/new', (request) {
       expect(request.headers,
           containsPair('authorization', 'Bearer new access token'));
 
@@ -36,6 +34,6 @@
     // do so rather than killing it so it'll write out the credentials file.
     await pub.shouldExit(1);
 
-    await d.credentialsFile(globalPackageServer, 'new access token').validate();
+    await d.credentialsFile(globalServer, 'new access token').validate();
   });
 }
diff --git a/test/oauth2/with_a_pre_existing_credentials_does_not_authenticate_test.dart b/test/oauth2/with_a_pre_existing_credentials_does_not_authenticate_test.dart
index ad6559f..3c22994 100644
--- a/test/oauth2/with_a_pre_existing_credentials_does_not_authenticate_test.dart
+++ b/test/oauth2/with_a_pre_existing_credentials_does_not_authenticate_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -14,8 +12,8 @@
     await d.validPackage.create();
 
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
 
diff --git a/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart b/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart
index 3354bbc..624f427 100644
--- a/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart
+++ b/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async';
 import 'dart:convert';
 
@@ -23,14 +21,14 @@
 
     await servePackages();
     await d
-        .credentialsFile(globalPackageServer, 'access token',
+        .credentialsFile(globalServer, 'access token',
             refreshToken: 'bad refresh token',
             expiration: DateTime.now().subtract(Duration(hours: 1)))
         .create();
 
-    var pub = await startPublish(globalPackageServer);
+    var pub = await startPublish(globalServer);
 
-    globalPackageServer.expect('POST', '/token', (request) {
+    globalServer.expect('POST', '/token', (request) {
       return request.read().drain().then((_) {
         return shelf.Response(400,
             body: jsonEncode({'error': 'invalid_request'}),
@@ -41,11 +39,10 @@
     await confirmPublish(pub);
 
     await expectLater(pub.stdout, emits(startsWith('Uploading...')));
-    await authorizePub(pub, globalPackageServer, 'new access token');
+    await authorizePub(pub, globalServer, 'new access token');
 
     var done = Completer();
-    globalPackageServer.expect('GET', '/api/packages/versions/new',
-        (request) async {
+    globalServer.expect('GET', '/api/packages/versions/new', (request) async {
       expect(request.headers,
           containsPair('authorization', 'Bearer new access token'));
 
diff --git a/test/oauth2/with_an_expired_credentials_refreshes_and_saves_test.dart b/test/oauth2/with_an_expired_credentials_refreshes_and_saves_test.dart
index 16062a7..7fbbb9f 100644
--- a/test/oauth2/with_an_expired_credentials_refreshes_and_saves_test.dart
+++ b/test/oauth2/with_an_expired_credentials_refreshes_and_saves_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:shelf/shelf.dart' as shelf;
@@ -20,15 +18,15 @@
 
     await servePackages();
     await d
-        .credentialsFile(globalPackageServer, 'access token',
+        .credentialsFile(globalServer, 'access token',
             refreshToken: 'refresh token',
             expiration: DateTime.now().subtract(Duration(hours: 1)))
         .create();
 
-    var pub = await startPublish(globalPackageServer);
+    var pub = await startPublish(globalServer);
     await confirmPublish(pub);
 
-    globalPackageServer.expect('POST', '/token', (request) {
+    globalServer.expect('POST', '/token', (request) {
       return request.readAsString().then((body) {
         expect(
             body, matches(RegExp(r'(^|&)refresh_token=refresh\+token(&|$)')));
@@ -40,7 +38,7 @@
       });
     });
 
-    globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+    globalServer.expect('GET', '/api/packages/versions/new', (request) {
       expect(request.headers,
           containsPair('authorization', 'Bearer new access token'));
 
@@ -50,7 +48,7 @@
     await pub.shouldExit();
 
     await d
-        .credentialsFile(globalPackageServer, 'new access token',
+        .credentialsFile(globalServer, 'new access token',
             refreshToken: 'refresh token')
         .validate();
   });
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 6437a5c..803c529 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
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
 
@@ -19,20 +17,20 @@
 
     await servePackages();
     await d
-        .credentialsFile(globalPackageServer, 'access token',
+        .credentialsFile(globalServer, 'access token',
             expiration: DateTime.now().subtract(Duration(hours: 1)))
         .create();
 
-    var pub = await startPublish(globalPackageServer);
+    var pub = await startPublish(globalServer);
     await confirmPublish(pub);
 
     await expectLater(
         pub.stderr,
         emits("Pub's authorization to upload packages has expired and "
             "can't be automatically refreshed."));
-    await authorizePub(pub, globalPackageServer, 'new access token');
+    await authorizePub(pub, globalServer, 'new access token');
 
-    globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+    globalServer.expect('GET', '/api/packages/versions/new', (request) {
       expect(request.headers,
           containsPair('authorization', 'Bearer new access token'));
 
@@ -43,6 +41,6 @@
     // do so rather than killing it so it'll write out the credentials file.
     await pub.shouldExit(1);
 
-    await d.credentialsFile(globalPackageServer, 'new access token').validate();
+    await d.credentialsFile(globalServer, 'new access token').validate();
   });
 }
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 2106960..961a465 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
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
 
@@ -18,11 +16,11 @@
     await d.validPackage.create();
 
     await servePackages();
-    var pub = await startPublish(globalPackageServer);
+    var pub = await startPublish(globalServer);
     await confirmPublish(pub);
-    await authorizePub(pub, globalPackageServer);
+    await authorizePub(pub, globalServer);
 
-    globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+    globalServer.expect('GET', '/api/packages/versions/new', (request) {
       expect(request.headers,
           containsPair('authorization', 'Bearer access token'));
 
@@ -33,6 +31,6 @@
     // do so rather than killing it so it'll write out the credentials file.
     await pub.shouldExit(1);
 
-    await d.credentialsFile(globalPackageServer, 'access token').validate();
+    await d.credentialsFile(globalServer, 'access token').validate();
   });
 }
diff --git a/test/oauth2/with_server_rejected_credentials_authenticates_again_test.dart b/test/oauth2/with_server_rejected_credentials_authenticates_again_test.dart
index 9ef5e69..2e3b62f 100644
--- a/test/oauth2/with_server_rejected_credentials_authenticates_again_test.dart
+++ b/test/oauth2/with_server_rejected_credentials_authenticates_again_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:shelf/shelf.dart' as shelf;
@@ -18,12 +16,12 @@
       'credentials.json', () async {
     await d.validPackage.create();
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPublish(globalPackageServer);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPublish(globalServer);
 
     await confirmPublish(pub);
 
-    globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+    globalServer.expect('GET', '/api/packages/versions/new', (request) {
       return shelf.Response(401,
           body: jsonEncode({
             'error': {'message': 'your token sucks'}
diff --git a/test/outdated/outdated_test.dart b/test/outdated/outdated_test.dart
index 2f47bbd..31113c7 100644
--- a/test/outdated/outdated_test.dart
+++ b/test/outdated/outdated_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import '../descriptor.dart' as d;
 import '../golden_file.dart';
 import '../test_pub.dart';
@@ -12,8 +10,8 @@
   /// Try running 'pub outdated' with a number of different sets of arguments.
   /// And compare to results from test/testdata/goldens/...
   Future<void> runOutdatedTests({
-    Map<String, String> environment,
-    String workingDirectory,
+    Map<String, String>? environment,
+    String? workingDirectory,
   }) async {
     const commands = [
       ['outdated', '--json'],
@@ -47,10 +45,10 @@
 
   testWithGolden('no lockfile', (ctx) async {
     await d.appDir({'foo': '^1.0.0', 'bar': '^1.0.0'}).create();
-    await servePackages((builder) => builder
+    await servePackages()
       ..serve('foo', '1.2.3')
       ..serve('bar', '1.2.3')
-      ..serve('bar', '2.0.0'));
+      ..serve('bar', '2.0.0');
 
     await ctx.runOutdatedTests();
   });
@@ -63,7 +61,8 @@
   });
 
   testWithGolden('newer versions available', (ctx) async {
-    await servePackages((builder) => builder
+    final builder = await servePackages();
+    builder
       ..serve('foo', '1.2.3', deps: {'transitive': '^1.0.0'})
       ..serve('bar', '1.0.0')
       ..serve('builder', '1.2.3', deps: {
@@ -71,7 +70,7 @@
         'dev_trans': '^1.0.0',
       })
       ..serve('transitive', '1.2.3')
-      ..serve('dev_trans', '1.0.0'));
+      ..serve('dev_trans', '1.0.0');
 
     await d.dir('local_package', [
       d.libDir('local_package'),
@@ -90,7 +89,7 @@
       })
     ]).create();
     await pubGet();
-    globalPackageServer.add((builder) => builder
+    builder
       ..serve('foo', '1.3.0', deps: {'transitive': '>=1.0.0<3.0.0'})
       ..serve('foo', '2.0.0',
           deps: {'transitive': '>=1.0.0<3.0.0', 'transitive2': '^1.0.0'})
@@ -106,15 +105,13 @@
       ..serve('transitive', '2.0.0')
       ..serve('transitive2', '1.0.0')
       ..serve('transitive3', '1.0.0')
-      ..serve('dev_trans', '2.0.0'));
-
+      ..serve('dev_trans', '2.0.0');
     await ctx.runOutdatedTests();
   });
 
   testWithGolden('circular dependency on root', (ctx) async {
-    await servePackages(
-      (builder) => builder..serve('foo', '1.2.3', deps: {'app': '^1.0.0'}),
-    );
+    final server = await servePackages();
+    server.serve('foo', '1.2.3', deps: {'app': '^1.0.0'});
 
     await d.dir(appPath, [
       d.pubspec({
@@ -128,10 +125,7 @@
 
     await pubGet();
 
-    globalPackageServer.add(
-      (builder) => builder..serve('foo', '1.3.0', deps: {'app': '^1.0.1'}),
-    );
-
+    server.serve('foo', '1.3.0', deps: {'app': '^1.0.1'});
     await ctx.runOutdatedTests();
   });
 
@@ -147,11 +141,11 @@
       })
     ]).create();
 
-    await servePackages((builder) => builder
+    await servePackages()
       ..serve('foo', '1.0.0', deps: {'bar': '^1.0.0'})
       ..serve('bar', '1.0.0', deps: {'foo': '^1.0.0'})
       ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
-      ..serve('bar', '2.0.0', deps: {'foo': '^1.0.0'}));
+      ..serve('bar', '2.0.0', deps: {'foo': '^1.0.0'});
     await pubGet();
 
     await ctx.runOutdatedTests();
@@ -174,62 +168,60 @@
       }),
     ]).create();
 
-    await servePackages(
-      (builder) => builder
-        ..serve('foo', '1.0.0', deps: {
-          'bar': '^1.0.0'
-        }, pubspec: {
-          'environment': {'sdk': '>=2.9.0 < 3.0.0'}
-        })
-        ..serve('bar', '1.0.0', pubspec: {
-          'environment': {'sdk': '>=2.9.0 < 3.0.0'}
-        })
-        ..serve('foo', '2.0.0-nullsafety.0', deps: {
-          'bar': '^2.0.0'
-        }, pubspec: {
-          'environment': {'sdk': '>=2.12.0 < 3.0.0'}
-        })
-        ..serve('foo', '2.0.0', deps: {
-          'bar': '^1.0.0'
-        }, pubspec: {
-          'environment': {'sdk': '>=2.12.0 < 3.0.0'}
-        })
-        ..serve('bar', '2.0.0', pubspec: {
-          'environment': {'sdk': '>=2.13.0 < 3.0.0'}
-        })
-        ..serve('file_opts_out', '1.0.0', pubspec: {
-          'environment': {'sdk': '>=2.12.0 < 3.0.0'},
-        }, contents: [
-          d.dir('lib', [d.file('main.dart', '// @dart = 2.9\n')])
-        ])
-        ..serve('file_opts_out', '2.0.0', pubspec: {
-          'environment': {'sdk': '>=2.12.0 < 3.0.0'},
-        })
-        ..serve('fails_analysis', '1.0.0', pubspec: {
-          'environment': {'sdk': '>=2.12.0 < 3.0.0'},
-        }, contents: [
-          d.dir('lib', [d.file('main.dart', 'syntax error\n')])
-        ])
-        ..serve('fails_analysis', '2.0.0', pubspec: {
-          'environment': {'sdk': '>=2.12.0 < 3.0.0'},
-        })
-        ..serve('file_in_dependency_opts_out', '1.0.0', deps: {
-          'file_opts_out': '^1.0.0'
-        }, pubspec: {
-          'environment': {'sdk': '>=2.12.0 < 3.0.0'},
-        })
-        ..serve('file_in_dependency_opts_out', '2.0.0', pubspec: {
-          'environment': {'sdk': '>=2.12.0 < 3.0.0'},
-        })
-        ..serve('fails_analysis_in_dependency', '1.0.0', deps: {
-          'fails_analysis': '^1.0.0'
-        }, pubspec: {
-          'environment': {'sdk': '>=2.12.0 < 3.0.0'},
-        })
-        ..serve('fails_analysis_in_dependency', '2.0.0', pubspec: {
-          'environment': {'sdk': '>=2.12.0 < 3.0.0'},
-        }),
-    );
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {
+        'bar': '^1.0.0'
+      }, pubspec: {
+        'environment': {'sdk': '>=2.9.0 < 3.0.0'}
+      })
+      ..serve('bar', '1.0.0', pubspec: {
+        'environment': {'sdk': '>=2.9.0 < 3.0.0'}
+      })
+      ..serve('foo', '2.0.0-nullsafety.0', deps: {
+        'bar': '^2.0.0'
+      }, pubspec: {
+        'environment': {'sdk': '>=2.12.0 < 3.0.0'}
+      })
+      ..serve('foo', '2.0.0', deps: {
+        'bar': '^1.0.0'
+      }, pubspec: {
+        'environment': {'sdk': '>=2.12.0 < 3.0.0'}
+      })
+      ..serve('bar', '2.0.0', pubspec: {
+        'environment': {'sdk': '>=2.13.0 < 3.0.0'}
+      })
+      ..serve('file_opts_out', '1.0.0', pubspec: {
+        'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+      }, contents: [
+        d.dir('lib', [d.file('main.dart', '// @dart = 2.9\n')])
+      ])
+      ..serve('file_opts_out', '2.0.0', pubspec: {
+        'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+      })
+      ..serve('fails_analysis', '1.0.0', pubspec: {
+        'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+      }, contents: [
+        d.dir('lib', [d.file('main.dart', 'syntax error\n')])
+      ])
+      ..serve('fails_analysis', '2.0.0', pubspec: {
+        'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+      })
+      ..serve('file_in_dependency_opts_out', '1.0.0', deps: {
+        'file_opts_out': '^1.0.0'
+      }, pubspec: {
+        'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+      })
+      ..serve('file_in_dependency_opts_out', '2.0.0', pubspec: {
+        'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+      })
+      ..serve('fails_analysis_in_dependency', '1.0.0', deps: {
+        'fails_analysis': '^1.0.0'
+      }, pubspec: {
+        'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+      })
+      ..serve('fails_analysis_in_dependency', '2.0.0', pubspec: {
+        'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+      });
     await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '2.13.0'});
 
     await ctx.runOutdatedTests(environment: {
@@ -238,7 +230,7 @@
   });
 
   testWithGolden('null-safety no resolution', (ctx) async {
-    await servePackages((builder) => builder
+    await servePackages()
       ..serve('foo', '1.0.0', pubspec: {
         'environment': {'sdk': '>=2.9.0 < 3.0.0'}
       })
@@ -254,7 +246,7 @@
         'foo': '^1.0.0'
       }, pubspec: {
         'environment': {'sdk': '>=2.12.0 < 3.0.0'}
-      }));
+      });
 
     await d.dir(appPath, [
       d.pubspec({
@@ -276,7 +268,7 @@
   });
 
   testWithGolden('null-safety already migrated', (ctx) async {
-    await servePackages((builder) => builder
+    await servePackages()
       ..serve('foo', '1.0.0', pubspec: {
         'environment': {'sdk': '>=2.9.0 < 3.0.0'}
       })
@@ -293,7 +285,7 @@
       })
       ..serve('devTransitive', '1.0.0', pubspec: {
         'environment': {'sdk': '>=2.9.0 < 3.0.0'}
-      }));
+      });
 
     await d.dir(appPath, [
       d.pubspec({
@@ -318,15 +310,13 @@
 
   testWithGolden('overridden dependencies', (ctx) async {
     ensureGit();
-    await servePackages(
-      (builder) => builder
-        ..serve('foo', '1.0.0')
-        ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
-        ..serve('bar', '1.0.0')
-        ..serve('bar', '2.0.0')
-        ..serve('baz', '1.0.0')
-        ..serve('baz', '2.0.0'),
-    );
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
+      ..serve('bar', '1.0.0')
+      ..serve('bar', '2.0.0')
+      ..serve('baz', '1.0.0')
+      ..serve('baz', '2.0.0');
 
     await d.git('foo.git', [
       d.libPubspec('foo', '1.0.1'),
@@ -362,13 +352,11 @@
 
   testWithGolden('overridden dependencies - no resolution', (ctx) async {
     ensureGit();
-    await servePackages(
-      (builder) => builder
-        ..serve('foo', '1.0.0', deps: {'bar': '^2.0.0'})
-        ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
-        ..serve('bar', '1.0.0', deps: {'foo': '^1.0.0'})
-        ..serve('bar', '2.0.0', deps: {'foo': '^2.0.0'}),
-    );
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '^2.0.0'})
+      ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
+      ..serve('bar', '1.0.0', deps: {'foo': '^1.0.0'})
+      ..serve('bar', '2.0.0', deps: {'foo': '^2.0.0'});
 
     await d.dir(appPath, [
       d.pubspec({
@@ -393,7 +381,7 @@
   testWithGolden(
       'latest version reported while locked on a prerelease can be a prerelease',
       (ctx) async {
-    await servePackages((builder) => builder
+    await servePackages()
       ..serve('foo', '0.9.0')
       ..serve('foo', '1.0.0-dev.1')
       ..serve('foo', '1.0.0-dev.2')
@@ -402,7 +390,7 @@
       ..serve('bar', '1.0.0-dev.2')
       ..serve('mop', '0.10.0-dev')
       ..serve('mop', '0.10.0')
-      ..serve('mop', '1.0.0-dev'));
+      ..serve('mop', '1.0.0-dev');
     await d.dir(appPath, [
       d.pubspec({
         'name': 'app',
@@ -421,7 +409,7 @@
   });
 
   testWithGolden('Handles SDK dependencies', (ctx) async {
-    await servePackages((builder) => builder
+    await servePackages()
       ..serve('foo', '1.0.0', pubspec: {
         'environment': {'sdk': '>=2.10.0 <3.0.0'}
       })
@@ -430,7 +418,7 @@
       })
       ..serve('foo', '2.0.0', pubspec: {
         'environment': {'sdk': '>=2.12.0 <3.0.0'}
-      }));
+      });
 
     await d.dir('flutter-root', [
       d.file('version', '1.2.3'),
diff --git a/test/package_config_file_test.dart b/test/package_config_file_test.dart
index 8cb03f0..763ce42 100644
--- a/test/package_config_file_test.dart
+++ b/test/package_config_file_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 
 import 'package:test/test.dart';
@@ -14,13 +12,12 @@
 void main() {
   forBothPubGetAndUpgrade((command) {
     test('package_config.json file is created', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3',
-            deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])]);
-        builder.serve('bar', '3.2.1', contents: [d.dir('lib', [])]);
-        builder.serve('baz', '2.2.2',
+      await servePackages()
+        ..serve('foo', '1.2.3',
+            deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])])
+        ..serve('bar', '3.2.1', contents: [d.dir('lib', [])])
+        ..serve('baz', '2.2.2',
             deps: {'bar': '3.2.1'}, contents: [d.dir('lib', [])]);
-      });
 
       await d.dir(appPath, [
         d.appPubspec({'foo': '1.2.3'}),
@@ -56,13 +53,12 @@
     });
 
     test('package_config.json file is overwritten', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3',
-            deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])]);
-        builder.serve('bar', '3.2.1', contents: [d.dir('lib', [])]);
-        builder.serve('baz', '2.2.2',
+      await servePackages()
+        ..serve('foo', '1.2.3',
+            deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])])
+        ..serve('bar', '3.2.1', contents: [d.dir('lib', [])])
+        ..serve('baz', '2.2.2',
             deps: {'bar': '3.2.1'}, contents: [d.dir('lib', [])]);
-      });
 
       await d.dir(appPath, [
         d.appPubspec({'foo': '1.2.3'}),
@@ -119,6 +115,8 @@
           args: ['--offline'], error: equalsIgnoringWhitespace("""
             Because myapp depends on foo any which doesn't exist (could not find
               package foo in cache), version solving failed.
+
+            Try again without --offline!
           """), exitCode: exit_codes.UNAVAILABLE);
 
       await d.dir(appPath, [
@@ -129,11 +127,10 @@
     test(
         '.dart_tool/package_config.json file has relative path to path dependency',
         () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3',
-            deps: {'baz': 'any'}, contents: [d.dir('lib', [])]);
-        builder.serve('baz', '9.9.9', deps: {}, contents: [d.dir('lib', [])]);
-      });
+      await servePackages()
+        ..serve('foo', '1.2.3',
+            deps: {'baz': 'any'}, contents: [d.dir('lib', [])])
+        ..serve('baz', '9.9.9', deps: {}, contents: [d.dir('lib', [])]);
 
       await d.dir('local_baz', [
         d.libDir('baz', 'baz 3.2.1'),
@@ -180,18 +177,17 @@
     });
 
     test('package_config.json has language version', () async {
-      await servePackages((builder) {
-        builder.serve(
-          'foo',
-          '1.2.3',
-          pubspec: {
-            'environment': {
-              'sdk': '>=0.0.1 <=0.2.2+2', // tests runs with '0.1.2+3'
-            },
+      final server = await servePackages();
+      server.serve(
+        'foo',
+        '1.2.3',
+        pubspec: {
+          'environment': {
+            'sdk': '>=0.0.1 <=0.2.2+2', // tests runs with '0.1.2+3'
           },
-          contents: [d.dir('lib', [])],
-        );
-      });
+        },
+        contents: [d.dir('lib', [])],
+      );
 
       await d.dir(appPath, [
         d.pubspec({
@@ -225,18 +221,17 @@
     });
 
     test('package_config.json has 2.7 default language version', () async {
-      await servePackages((builder) {
-        builder.serve(
-          'foo',
-          '1.2.3',
-          pubspec: {
-            'environment': {
-              'sdk': 'any',
-            },
+      final server = await servePackages();
+      server.serve(
+        'foo',
+        '1.2.3',
+        pubspec: {
+          'environment': {
+            'sdk': 'any',
           },
-          contents: [d.dir('lib', [])],
-        );
-      });
+        },
+        contents: [d.dir('lib', [])],
+      );
 
       await d.dir(appPath, [
         d.pubspec({
diff --git a/test/package_list_files_test.dart b/test/package_list_files_test.dart
index 921175d..091001b 100644
--- a/test/package_list_files_test.dart
+++ b/test/package_list_files_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:path/path.dart' as p;
@@ -15,8 +13,8 @@
 import 'descriptor.dart' as d;
 import 'test_pub.dart';
 
-String root;
-Entrypoint entrypoint;
+late String root;
+Entrypoint? entrypoint;
 
 void main() {
   test('lists files recursively', () async {
@@ -35,7 +33,7 @@
     createEntrypoint();
 
     expect(
-        entrypoint.root.listFiles(),
+        entrypoint!.root.listFiles(),
         unorderedEquals([
           p.join(root, 'pubspec.yaml'),
           p.join(root, 'file1.txt'),
@@ -71,7 +69,7 @@
     createEntrypoint();
 
     expect(
-      () => entrypoint.root.listFiles(),
+      () => entrypoint!.root.listFiles(),
       throwsA(
         isA<DataException>().having(
           (e) => e.message,
@@ -123,7 +121,7 @@
     createEntrypoint();
 
     expect(
-      () => entrypoint.root.listFiles(),
+      () => entrypoint!.root.listFiles(),
       throwsA(
         isA<DataException>().having(
           (e) => e.message,
@@ -151,7 +149,7 @@
     createEntrypoint();
 
     expect(
-      () => entrypoint.root.listFiles(),
+      () => entrypoint!.root.listFiles(),
       throwsA(
         isA<DataException>().having(
           (e) => e.message,
@@ -169,13 +167,13 @@
       d.file('.foo', ''),
     ]).create();
     createEntrypoint();
-    expect(entrypoint.root.listFiles(), {
+    expect(entrypoint!.root.listFiles(), {
       p.join(root, '.foo'),
       p.join(root, 'pubspec.yaml'),
     });
   });
   group('with git', () {
-    d.GitRepoDescriptor repo;
+    late d.GitRepoDescriptor repo;
     setUp(() async {
       ensureGit();
       repo = d.git(appPath, [d.appPubspec()]);
@@ -193,7 +191,7 @@
         ])
       ]).create();
 
-      expect(entrypoint.root.listFiles(), {
+      expect(entrypoint!.root.listFiles(), {
         p.join(root, 'pubspec.yaml'),
         p.join(root, 'file1.txt'),
         p.join(root, 'file2.txt'),
@@ -213,7 +211,7 @@
         ])
       ]).create();
 
-      expect(entrypoint.root.listFiles(), {
+      expect(entrypoint!.root.listFiles(), {
         p.join(root, 'pubspec.yaml'),
         p.join(root, 'file2.text'),
         p.join(root, 'subdir', 'subfile2.text')
@@ -246,7 +244,7 @@
 
       createEntrypoint(p.join(appPath, 'rep', 'sub'));
 
-      expect(entrypoint.root.listFiles(), {
+      expect(entrypoint!.root.listFiles(), {
         p.join(root, 'pubspec.yaml'),
         p.join(root, 'file2.text'),
         p.join(root, 'file4.gak'),
@@ -266,7 +264,7 @@
 
       createEntrypoint(p.join(appPath, 'packages', 'app'));
 
-      expect(entrypoint.root.listFiles(), {
+      expect(entrypoint!.root.listFiles(), {
         p.join(root, 'pubspec.yaml'),
       });
     });
@@ -286,7 +284,7 @@
       });
 
       test('respects its .gitignore with useGitIgnore', () {
-        expect(entrypoint.root.listFiles(), {
+        expect(entrypoint!.root.listFiles(), {
           p.join(root, 'pubspec.yaml'),
           p.join(root, 'submodule', 'file2.text'),
         });
@@ -299,7 +297,7 @@
         d.dir('subdir', [d.file('pubspec.lock')])
       ]).create();
 
-      expect(entrypoint.root.listFiles(), {p.join(root, 'pubspec.yaml')});
+      expect(entrypoint!.root.listFiles(), {p.join(root, 'pubspec.yaml')});
     });
 
     test('ignores packages directories', () async {
@@ -310,7 +308,7 @@
         ])
       ]).create();
 
-      expect(entrypoint.root.listFiles(), {p.join(root, 'pubspec.yaml')});
+      expect(entrypoint!.root.listFiles(), {p.join(root, 'pubspec.yaml')});
     });
 
     test('allows pubspec.lock directories', () async {
@@ -320,7 +318,7 @@
         ])
       ]).create();
 
-      expect(entrypoint.root.listFiles(), {
+      expect(entrypoint!.root.listFiles(), {
         p.join(root, 'pubspec.yaml'),
         p.join(root, 'pubspec.lock', 'file.txt')
       });
@@ -341,7 +339,7 @@
           ])
         ]).create();
 
-        expect(entrypoint.root.listFiles(beneath: 'subdir'), {
+        expect(entrypoint!.root.listFiles(beneath: 'subdir'), {
           p.join(root, 'subdir', 'subfile1.txt'),
           p.join(root, 'subdir', 'subfile2.txt'),
           p.join(root, 'subdir', 'subsubdir', 'subsubfile1.txt'),
@@ -360,7 +358,7 @@
         d.dir('lib', [d.file('not_ignored.dart', 'content')]),
       ]).create();
       createEntrypoint();
-      expect(entrypoint.root.listFiles(), {
+      expect(entrypoint!.root.listFiles(), {
         p.join(root, 'LICENSE'),
         p.join(root, 'CHANGELOG.md'),
         p.join(root, 'README.md'),
@@ -412,7 +410,7 @@
     ]).create();
 
     createEntrypoint();
-    expect(entrypoint.root.listFiles(), {
+    expect(entrypoint!.root.listFiles(), {
       p.join(root, 'pubspec.yaml'),
       p.join(root, 'not_ignored_by_gitignore.txt'),
       p.join(root, 'ignored_by_gitignore.txt'),
@@ -427,7 +425,7 @@
   });
 }
 
-void createEntrypoint([String path]) {
+void createEntrypoint([String? path]) {
   path ??= appPath;
   root = p.join(d.sandbox, path);
   entrypoint = Entrypoint(root, SystemCache(rootDir: root));
diff --git a/test/package_server.dart b/test/package_server.dart
index ec960ca..952c189 100644
--- a/test/package_server.dart
+++ b/test/package_server.dart
@@ -2,162 +2,158 @@
 // 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.
 
-// @dart=2.10
-
 import 'dart:async';
 import 'dart:convert';
+import 'dart:io';
 
 import 'package:path/path.dart' as p;
+import 'package:pub/src/third_party/tar/tar.dart';
 import 'package:pub_semver/pub_semver.dart';
 import 'package:shelf/shelf.dart' as shelf;
+import 'package:shelf/shelf_io.dart' as shelf_io;
 import 'package:test/test.dart';
 import 'package:test/test.dart' as test show expect;
 
 import 'descriptor.dart' as d;
 import 'test_pub.dart';
 
-/// The current global [PackageServer].
-PackageServer get globalPackageServer => _globalPackageServer;
-PackageServer _globalPackageServer;
-
-/// Creates an HTTP server that replicates the structure of pub.dartlang.org and
-/// makes it the current [globalServer].
-///
-/// Calls [callback] with a [PackageServerBuilder] that's used to specify
-/// which packages to serve.
-Future servePackages([void Function(PackageServerBuilder) callback]) async {
-  _globalPackageServer = await PackageServer.start(callback ?? (_) {});
-  globalServer = _globalPackageServer._inner;
-
-  addTearDown(() {
-    _globalPackageServer = null;
-  });
-}
-
-/// Like [servePackages], but instead creates an empty server with no packages
-/// registered.
-///
-/// This will always replace a previous server.
-Future serveNoPackages() => servePackages((_) {});
-
-/// Sets up the global package server to report an error on any request.
-///
-/// If no server has been set up, an empty server will be started.
-Future serveErrors() async {
-  if (globalPackageServer == null) {
-    await serveNoPackages();
-  }
-  globalPackageServer.serveErrors();
-}
-
 class PackageServer {
   /// The inner [DescriptorServer] that this uses to serve its descriptors.
-  final DescriptorServer _inner;
+  final shelf.Server _inner;
 
-  /// The [d.DirectoryDescriptor] describing the server layout of
-  /// `/api/packages` on the test server.
-  ///
-  /// This contains metadata for packages that are being served via
-  /// [servePackages].
-  final _servedApiPackageDir = d.dir('packages', []);
+  /// Handlers of requests. Last matching handler will be used.
+  final List<_PatternAndHandler> _handlers = [];
 
-  /// The [d.DirectoryDescriptor] describing the server layout of `/packages` on
-  /// the test server.
-  ///
-  /// This contains the tarballs for packages that are being served via
-  /// [servePackages].
-  final _servedPackageDir = d.dir('packages', []);
+  // A list of all the requests recieved up till now.
+  final List<String> requestedPaths = <String>[];
 
-  /// The current [PackageServerBuilder] that a user uses to specify which
-  /// package to serve.
-  ///
-  /// This is preserved so that additional packages can be added.
-  PackageServerBuilder _builder;
+  PackageServer._(this._inner) {
+    _inner.mount((request) {
+      final path = request.url.path;
+      requestedPaths.add(path);
 
-  /// The port used for the server.
-  int get port => _inner.port;
+      final pathWithInitialSlash = '/$path';
+      for (final entry in _handlers.reversed) {
+        final match = entry.pattern.matchAsPrefix(pathWithInitialSlash);
+        if (match != null && match.end == pathWithInitialSlash.length) {
+          final a = entry.handler(request);
+          return a;
+        }
+      }
+      return shelf.Response.notFound('Could not find ${request.url}');
+    });
+  }
 
-  /// The URL for the server.
-  String get url => 'http://localhost:$port';
+  static final _versionInfoPattern = RegExp(r'/api/packages/([a-zA-Z_0-9]*)');
+  static final _downloadPattern =
+      RegExp(r'/packages/([^/]*)/versions/([^/]*).tar.gz');
 
-  /// Handlers for requests not easily described as packages.
-  Map<Pattern, shelf.Handler> get extraHandlers => _inner.extraHandlers;
+  static Future<PackageServer> start() async {
+    final server =
+        PackageServer._(await shelf_io.IOServer.bind('localhost', 0));
+    server.handle(
+      _versionInfoPattern,
+      (shelf.Request request) {
+        final parts = request.url.pathSegments;
+        assert(parts[0] == 'api');
+        assert(parts[1] == 'packages');
+        final name = parts[2];
 
-  /// From now on report errors on any request.
-  void serveErrors() => extraHandlers
-    ..clear()
-    ..[RegExp('.*')] = (request) {
-      fail('The HTTP server received an unexpected request:\n'
-          '${request.method} ${request.requestedUri}');
-    };
+        final package = server._packages[name];
+        if (package == null) {
+          return shelf.Response.notFound('No package named $name');
+        }
+        return shelf.Response.ok(jsonEncode({
+          'name': name,
+          'uploaders': ['nweiz@google.com'],
+          'versions': package.versions.values
+              .map((version) => packageVersionApiMap(
+                    server._inner.url.toString(),
+                    version.pubspec,
+                    retracted: version.isRetracted,
+                  ))
+              .toList(),
+          if (package.isDiscontinued) 'isDiscontinued': true,
+          if (package.discontinuedReplacementText != null)
+            'replacedBy': package.discontinuedReplacementText,
+        }));
+      },
+    );
 
-  /// Creates an HTTP server that replicates the structure of pub.dartlang.org.
-  ///
-  /// Calls [callback] with a [PackageServerBuilder] that's used to specify
-  /// which packages to serve.
-  static Future<PackageServer> start(
-      void Function(PackageServerBuilder) callback) async {
-    var descriptorServer = await DescriptorServer.start();
-    var server = PackageServer._(descriptorServer);
-    descriptorServer.contents
-      ..add(d.dir('api', [server._servedApiPackageDir]))
-      ..add(server._servedPackageDir);
-    server.add(callback);
+    server.handle(
+      _downloadPattern,
+      (shelf.Request request) {
+        final parts = request.url.pathSegments;
+        assert(parts[0] == 'packages');
+        final name = parts[1];
+        assert(parts[2] == 'versions');
+        final package = server._packages[name];
+        if (package == null) {
+          return shelf.Response.notFound('No package $name');
+        }
+
+        final version = Version.parse(
+            parts[3].substring(0, parts[3].length - '.tar.gz'.length));
+        assert(parts[3].endsWith('.tar.gz'));
+
+        for (final packageVersion in package.versions.values) {
+          if (packageVersion.version == version) {
+            return shelf.Response.ok(packageVersion.contents());
+          }
+        }
+        return shelf.Response.notFound('No version $version of $name');
+      },
+    );
     return server;
   }
 
-  PackageServer._(this._inner) {
-    _builder = PackageServerBuilder._(this);
+  Future<void> close() async {
+    await _inner.close();
   }
 
-  /// Add to the current set of packages that are being served.
-  void add(void Function(PackageServerBuilder) callback) {
-    callback(_builder);
+  /// The port used for the server.
+  int get port => _inner.url.port;
 
-    _servedApiPackageDir.contents.clear();
-    _servedPackageDir.contents.clear();
+  /// The URL for the server.
+  String get url => _inner.url.toString();
 
-    _builder._packages.forEach((name, package) {
-      _servedApiPackageDir.contents.addAll([
-        d.file(
-            name,
-            jsonEncode({
-              'name': name,
-              'uploaders': ['nweiz@google.com'],
-              'versions': package.versions.values
-                  .map((version) => packageVersionApiMap(url, version.pubspec,
-                      retracted: version.isRetracted))
-                  .toList(),
-              if (package.isDiscontinued) 'isDiscontinued': true,
-              if (package.discontinuedReplacementText != null)
-                'replacedBy': package.discontinuedReplacementText,
-            })),
-        d.dir(name, [
-          d.dir('versions', package.versions.values.map((version) {
-            return d.file(
-                version.version.toString(),
-                jsonEncode(packageVersionApiMap(url, version.pubspec,
-                    retracted: version.isRetracted, full: true)));
-          }))
-        ])
-      ]);
+  /// From now on report errors on any request.
+  void serveErrors() => _handlers
+    ..clear()
+    ..add(
+      _PatternAndHandler(
+        RegExp('.*'),
+        (request) {
+          fail('The HTTP server received an unexpected request:\n'
+              '${request.method} ${request.requestedUri}');
+        },
+      ),
+    );
 
-      _servedPackageDir.contents.add(d.dir(name, [
-        d.dir(
-            'versions',
-            package.versions.values.map((version) =>
-                d.tar('${version.version}.tar.gz', version.contents)))
-      ]));
-    });
+  void handle(Pattern pattern, shelf.Handler handler) {
+    _handlers.add(
+      _PatternAndHandler(
+        pattern,
+        handler,
+      ),
+    );
   }
 
   // Installs a handler at [pattern] that expects to be called exactly once with
   // the given [method].
+  //
+  // The handler is installed as the start to give it priority over more general
+  // handlers.
   void expect(String method, Pattern pattern, shelf.Handler handler) {
-    extraHandlers[pattern] = expectAsync1((request) {
-      test.expect(request.method, method);
-      return handler(request);
-    });
+    handle(
+      pattern,
+      expectAsync1(
+        (request) {
+          test.expect(request.method, method);
+          return handler(request);
+        },
+      ),
+    );
   }
 
   /// Returns the path of [package] at [version], installed from this server, in
@@ -169,26 +165,9 @@
   String get cachingPath =>
       p.join(d.sandbox, cachePath, 'hosted', 'localhost%58$port');
 
-  /// Replace the current set of packages that are being served.
-  void replace(void Function(PackageServerBuilder) callback) {
-    _builder._clear();
-    add(callback);
-  }
-}
-
-/// A builder for specifying which packages should be served by [servePackages].
-class PackageServerBuilder {
   /// A map from package names to the concrete packages to serve.
   final _packages = <String, _ServedPackage>{};
 
-  /// The package server that this builder is associated with.
-  final PackageServer _server;
-
-  /// The URL for the server that this builder is associated with.
-  String get serverUrl => _server.url;
-
-  PackageServerBuilder._(this._server);
-
   /// Specifies that a package named [name] with [version] should be served.
   ///
   /// If [deps] is passed, it's used as the "dependencies" field of the pubspec.
@@ -197,9 +176,9 @@
   /// If [contents] is passed, it's used as the contents of the package. By
   /// default, a package just contains a dummy lib directory.
   void serve(String name, String version,
-      {Map<String, dynamic> deps,
-      Map<String, dynamic> pubspec,
-      Iterable<d.Descriptor> contents}) {
+      {Map<String, dynamic>? deps,
+      Map<String, dynamic>? pubspec,
+      List<d.Descriptor>? contents}) {
     var pubspecFields = <String, dynamic>{'name': name, 'version': version};
     if (pubspec != null) pubspecFields.addAll(pubspec);
     if (deps != null) pubspecFields['dependencies'] = deps;
@@ -208,40 +187,84 @@
     contents = [d.file('pubspec.yaml', yaml(pubspecFields)), ...contents];
 
     var package = _packages.putIfAbsent(name, () => _ServedPackage());
-    package.versions[version] = _ServedPackageVersion(pubspecFields, contents);
+    package.versions[version] = _ServedPackageVersion(
+      pubspecFields,
+      contents: () {
+        final entries = <TarEntry>[];
+
+        void addDescriptor(d.Descriptor descriptor, String path) {
+          if (descriptor is d.DirectoryDescriptor) {
+            for (final e in descriptor.contents) {
+              addDescriptor(e, p.posix.join(path, descriptor.name));
+            }
+          } else {
+            entries.add(
+              TarEntry(
+                TarHeader(
+                  // Ensure paths in tar files use forward slashes
+                  name: p.posix.join(path, descriptor.name),
+                  // We want to keep executable bits, but otherwise use the default
+                  // file mode
+                  mode: 420,
+                  // size: 100,
+                  modified: DateTime.now(),
+                  userName: 'pub',
+                  groupName: 'pub',
+                ),
+                (descriptor as d.FileDescriptor).readAsBytes(),
+              ),
+            );
+          }
+        }
+
+        for (final e in contents ?? <d.Descriptor>[]) {
+          addDescriptor(e, '');
+        }
+        return Stream.fromIterable(entries)
+            .transform(tarWriterWith(format: OutputFormat.gnuLongName))
+            .transform(gzip.encoder);
+      },
+    );
   }
 
   // Mark a package discontinued.
   void discontinue(String name,
-      {bool isDiscontinued = true, String replacementText}) {
-    _packages[name]
+      {bool isDiscontinued = true, String? replacementText}) {
+    _packages[name]!
       ..isDiscontinued = isDiscontinued
       ..discontinuedReplacementText = replacementText;
   }
 
   /// Clears all existing packages from this builder.
-  void _clear() {
+  void clearPackages() {
     _packages.clear();
   }
 
   void retractPackageVersion(String name, String version) {
-    _packages[name].versions[version].isRetracted = true;
+    _packages[name]!.versions[version]!.isRetracted = true;
   }
 }
 
 class _ServedPackage {
   final versions = <String, _ServedPackageVersion>{};
   bool isDiscontinued = false;
-  String discontinuedReplacementText;
+  String? discontinuedReplacementText;
 }
 
 /// A package that's intended to be served.
 class _ServedPackageVersion {
   final Map pubspec;
-  final List<d.Descriptor> contents;
+  final Stream<List<int>> Function() contents;
   bool isRetracted = false;
 
   Version get version => Version.parse(pubspec['version']);
 
-  _ServedPackageVersion(this.pubspec, this.contents);
+  _ServedPackageVersion(this.pubspec, {required this.contents});
+}
+
+class _PatternAndHandler {
+  Pattern pattern;
+  shelf.Handler handler;
+
+  _PatternAndHandler(this.pattern, this.handler);
 }
diff --git a/test/packages_file_test.dart b/test/packages_file_test.dart
index ce87d7c..e7736be 100644
--- a/test/packages_file_test.dart
+++ b/test/packages_file_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 
 import 'package:test/test.dart';
@@ -14,13 +12,12 @@
 void main() {
   forBothPubGetAndUpgrade((command) {
     test('.packages file is created', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3',
-            deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])]);
-        builder.serve('bar', '3.2.1', contents: [d.dir('lib', [])]);
-        builder.serve('baz', '2.2.2',
+      await servePackages()
+        ..serve('foo', '1.2.3',
+            deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])])
+        ..serve('bar', '3.2.1', contents: [d.dir('lib', [])])
+        ..serve('baz', '2.2.2',
             deps: {'bar': '3.2.1'}, contents: [d.dir('lib', [])]);
-      });
 
       await d.dir(appPath, [
         d.appPubspec({'foo': '1.2.3'}),
@@ -36,13 +33,12 @@
     });
 
     test('.packages file is overwritten', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3',
-            deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])]);
-        builder.serve('bar', '3.2.1', contents: [d.dir('lib', [])]);
-        builder.serve('baz', '2.2.2',
+      await servePackages()
+        ..serve('foo', '1.2.3',
+            deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])])
+        ..serve('bar', '3.2.1', contents: [d.dir('lib', [])])
+        ..serve('baz', '2.2.2',
             deps: {'bar': '3.2.1'}, contents: [d.dir('lib', [])]);
-      });
 
       await d.dir(appPath, [
         d.appPubspec({'foo': '1.2.3'}),
@@ -73,17 +69,18 @@
           args: ['--offline'], error: equalsIgnoringWhitespace("""
             Because myapp depends on foo any which doesn't exist (could not find
               package foo in cache), version solving failed.
+
+            Try again without --offline!
           """), exitCode: exit_codes.UNAVAILABLE);
 
       await d.dir(appPath, [d.nothing('.packages')]).validate();
     });
 
     test('.packages file has relative path to path dependency', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3',
-            deps: {'baz': 'any'}, contents: [d.dir('lib', [])]);
-        builder.serve('baz', '9.9.9', deps: {}, contents: [d.dir('lib', [])]);
-      });
+      await servePackages()
+        ..serve('foo', '1.2.3',
+            deps: {'baz': 'any'}, contents: [d.dir('lib', [])])
+        ..serve('baz', '9.9.9', deps: {}, contents: [d.dir('lib', [])]);
 
       await d.dir('local_baz', [
         d.libDir('baz', 'baz 3.2.1'),
diff --git a/test/pub_get_and_upgrade_test.dart b/test/pub_get_and_upgrade_test.dart
index b93d10f..62004a4 100644
--- a/test/pub_get_and_upgrade_test.dart
+++ b/test/pub_get_and_upgrade_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 
 import 'package:test/test.dart';
diff --git a/test/pub_uploader_test.dart b/test/pub_uploader_test.dart
index c45c8ed..47d50d3 100644
--- a/test/pub_uploader_test.dart
+++ b/test/pub_uploader_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async';
 import 'dart:convert';
 
@@ -42,12 +40,11 @@
 
   test('adds an uploader', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
+    await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPubUploader(
-        globalPackageServer, ['--package', 'pkg', 'add', 'email']);
+        globalServer, ['--package', 'pkg', 'add', 'email']);
 
-    globalPackageServer.expect('POST', '/api/packages/pkg/uploaders',
-        (request) {
+    globalServer.expect('POST', '/api/packages/pkg/uploaders', (request) {
       return request.readAsString().then((body) {
         expect(body, equals('email=email'));
 
@@ -65,11 +62,11 @@
 
   test('removes an uploader', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
+    await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPubUploader(
-        globalPackageServer, ['--package', 'pkg', 'remove', 'email']);
+        globalServer, ['--package', 'pkg', 'remove', 'email']);
 
-    globalPackageServer.expect('DELETE', '/api/packages/pkg/uploaders/email',
+    globalServer.expect('DELETE', '/api/packages/pkg/uploaders/email',
         (request) {
       return shelf.Response.ok(
           jsonEncode({
@@ -86,11 +83,10 @@
     await d.validPackage.create();
 
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
-    var pub = await startPubUploader(globalPackageServer, ['add', 'email']);
+    await d.credentialsFile(globalServer, 'access token').create();
+    var pub = await startPubUploader(globalServer, ['add', 'email']);
 
-    globalPackageServer.expect('POST', '/api/packages/test_pkg/uploaders',
-        (request) {
+    globalServer.expect('POST', '/api/packages/test_pkg/uploaders', (request) {
       return shelf.Response.ok(
           jsonEncode({
             'success': {'message': 'Good job!'}
@@ -104,12 +100,11 @@
 
   test('add provides an error', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
+    await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPubUploader(
-        globalPackageServer, ['--package', 'pkg', 'add', 'email']);
+        globalServer, ['--package', 'pkg', 'add', 'email']);
 
-    globalPackageServer.expect('POST', '/api/packages/pkg/uploaders',
-        (request) {
+    globalServer.expect('POST', '/api/packages/pkg/uploaders', (request) {
       return shelf.Response(400,
           body: jsonEncode({
             'error': {'message': 'Bad job!'}
@@ -123,11 +118,11 @@
 
   test('remove provides an error', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
+    await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPubUploader(
-        globalPackageServer, ['--package', 'pkg', 'remove', 'e/mail']);
+        globalServer, ['--package', 'pkg', 'remove', 'e/mail']);
 
-    globalPackageServer.expect('DELETE', '/api/packages/pkg/uploaders/e%2Fmail',
+    globalServer.expect('DELETE', '/api/packages/pkg/uploaders/e%2Fmail',
         (request) {
       return shelf.Response(400,
           body: jsonEncode({
@@ -142,11 +137,11 @@
 
   test('add provides invalid JSON', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
+    await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPubUploader(
-        globalPackageServer, ['--package', 'pkg', 'add', 'email']);
+        globalServer, ['--package', 'pkg', 'add', 'email']);
 
-    globalPackageServer.expect('POST', '/api/packages/pkg/uploaders',
+    globalServer.expect('POST', '/api/packages/pkg/uploaders',
         (request) => shelf.Response.ok('{not json'));
 
     expect(
@@ -158,11 +153,11 @@
 
   test('remove provides invalid JSON', () async {
     await servePackages();
-    await d.credentialsFile(globalPackageServer, 'access token').create();
+    await d.credentialsFile(globalServer, 'access token').create();
     var pub = await startPubUploader(
-        globalPackageServer, ['--package', 'pkg', 'remove', 'email']);
+        globalServer, ['--package', 'pkg', 'remove', 'email']);
 
-    globalPackageServer.expect('DELETE', '/api/packages/pkg/uploaders/email',
+    globalServer.expect('DELETE', '/api/packages/pkg/uploaders/email',
         (request) => shelf.Response.ok('{not json'));
 
     expect(
diff --git a/test/pubspec_test.dart b/test/pubspec_test.dart
index c293d85..62f77c4 100644
--- a/test/pubspec_test.dart
+++ b/test/pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/language_version.dart';
 import 'package:pub/src/package_name.dart';
 import 'package:pub/src/pubspec.dart';
@@ -24,14 +22,14 @@
 
   @override
   PackageRef parseRef(String name, description,
-      {String containingPath, LanguageVersion languageVersion}) {
+      {String? containingPath, LanguageVersion? languageVersion}) {
     if (description != 'ok') throw FormatException('Bad');
     return PackageRef(name, this, description);
   }
 
   @override
   PackageId parseId(String name, Version version, description,
-          {String containingPath}) =>
+          {String? containingPath}) =>
       PackageId(name, this, version, description);
 
   @override
@@ -52,7 +50,7 @@
     var throwsPubspecException = throwsA(const TypeMatcher<PubspecException>());
 
     void expectPubspecException(String contents, void Function(Pubspec) fn,
-        [String expectedContains]) {
+        [String? expectedContains]) {
       var expectation = const TypeMatcher<PubspecException>();
       if (expectedContains != null) {
         expectation = expectation.having(
@@ -90,7 +88,7 @@
     version: ">=1.2.3 <3.4.5"
 ''', sources);
 
-      var foo = pubspec.dependencies['foo'];
+      var foo = pubspec.dependencies['foo']!;
       expect(foo.name, equals('foo'));
       expect(foo.constraint.allows(Version(1, 2, 3)), isTrue);
       expect(foo.constraint.allows(Version(1, 2, 5)), isTrue);
@@ -105,7 +103,7 @@
     version: ">=1.2.3 <0.0.0"
 ''', sources);
 
-      var foo = pubspec.dependencies['foo'];
+      var foo = pubspec.dependencies['foo']!;
       expect(foo.name, equals('foo'));
       expect(foo.constraint.isEmpty, isTrue);
     });
@@ -126,7 +124,7 @@
     version: ">=1.2.3 <3.4.5"
 ''', sources);
 
-      var foo = pubspec.devDependencies['foo'];
+      var foo = pubspec.devDependencies['foo']!;
       expect(foo.name, equals('foo'));
       expect(foo.constraint.allows(Version(1, 2, 3)), isTrue);
       expect(foo.constraint.allows(Version(1, 2, 5)), isTrue);
@@ -149,7 +147,7 @@
     version: ">=1.2.3 <3.4.5"
 ''', sources);
 
-      var foo = pubspec.dependencyOverrides['foo'];
+      var foo = pubspec.dependencyOverrides['foo']!;
       expect(foo.name, equals('foo'));
       expect(foo.constraint.allows(Version(1, 2, 3)), isTrue);
       expect(foo.constraint.allows(Version(1, 2, 5)), isTrue);
@@ -171,7 +169,7 @@
     unknown: blah
 ''', sources);
 
-      var foo = pubspec.dependencies['foo'];
+      var foo = pubspec.dependencies['foo']!;
       expect(foo.name, equals('foo'));
       expect(foo.source, equals(sources['unknown']));
     });
@@ -183,7 +181,7 @@
     version: 1.2.3
 ''', sources);
 
-      var foo = pubspec.dependencies['foo'];
+      var foo = pubspec.dependencies['foo']!;
       expect(foo.name, equals('foo'));
       expect(foo.source, equals(sources['hosted']));
     });
@@ -310,10 +308,10 @@
           sources,
         );
 
-        var foo = pubspec.dependencies['foo'];
+        var foo = pubspec.dependencies['foo']!;
         expect(foo.name, equals('foo'));
-        expect(foo.source.name, 'hosted');
-        expect(foo.source.serializeDescription(null, foo.description), {
+        expect(foo.source!.name, 'hosted');
+        expect(foo.source!.serializeDescription('', foo.description), {
           'url': 'https://example.org/pub/',
           'name': 'bar',
         });
@@ -333,10 +331,10 @@
           sources,
         );
 
-        var foo = pubspec.dependencies['foo'];
+        var foo = pubspec.dependencies['foo']!;
         expect(foo.name, equals('foo'));
-        expect(foo.source.name, 'hosted');
-        expect(foo.source.serializeDescription(null, foo.description), {
+        expect(foo.source!.name, 'hosted');
+        expect(foo.source!.serializeDescription('', foo.description), {
           'url': 'https://example.org/pub/',
           'name': 'foo',
         });
@@ -355,10 +353,10 @@
           sources,
         );
 
-        var foo = pubspec.dependencies['foo'];
+        var foo = pubspec.dependencies['foo']!;
         expect(foo.name, equals('foo'));
-        expect(foo.source.name, 'hosted');
-        expect(foo.source.serializeDescription(null, foo.description), {
+        expect(foo.source!.name, 'hosted');
+        expect(foo.source!.serializeDescription('', foo.description), {
           'url': 'https://example.org/pub/',
           'name': 'foo',
         });
@@ -377,10 +375,10 @@
           sources,
         );
 
-        var foo = pubspec.dependencies['foo'];
+        var foo = pubspec.dependencies['foo']!;
         expect(foo.name, equals('foo'));
-        expect(foo.source.name, 'hosted');
-        expect(foo.source.serializeDescription(null, foo.description), {
+        expect(foo.source!.name, 'hosted');
+        expect(foo.source!.serializeDescription('', foo.description), {
           'url': 'https://pub.dartlang.org',
           'name': 'bar',
         });
@@ -402,7 +400,7 @@
             () => pubspec.dependencies,
             throwsA(
               isA<PubspecException>()
-                  .having((e) => e.span.text, 'span.text', 'invalid value'),
+                  .having((e) => e.span!.text, 'span.text', 'invalid value'),
             ),
           );
         },
@@ -418,10 +416,10 @@
           sources,
         );
 
-        var foo = pubspec.dependencies['foo'];
+        var foo = pubspec.dependencies['foo']!;
         expect(foo.name, equals('foo'));
-        expect(foo.source.name, 'hosted');
-        expect(foo.source.serializeDescription(null, foo.description), {
+        expect(foo.source!.name, 'hosted');
+        expect(foo.source!.serializeDescription('', foo.description), {
           'url': 'https://pub.dartlang.org',
           'name': 'foo',
         });
@@ -714,7 +712,7 @@
 ''', sources);
         expect(pubspec.features, contains('foobar'));
 
-        var feature = pubspec.features['foobar'];
+        var feature = pubspec.features['foobar']!;
         expect(feature.name, equals('foobar'));
         expect(feature.onByDefault, isTrue);
         expect(feature.dependencies, isEmpty);
@@ -751,7 +749,7 @@
 
         expect(pubspec.features, contains('foobar'));
 
-        var feature = pubspec.features['foobar'];
+        var feature = pubspec.features['foobar']!;
         expect(feature.sdkConstraints,
             containsPair('dart', VersionConstraint.parse('^1.0.0')));
         expect(feature.sdkConstraints,
@@ -770,7 +768,7 @@
             Pubspec.parse('features: {foobar: {default: false}}', sources);
 
         expect(pubspec.features, contains('foobar'));
-        expect(pubspec.features['foobar'].onByDefault, isFalse);
+        expect(pubspec.features['foobar']!.onByDefault, isFalse);
       });
 
       test('parses valid dependency specifications', () {
@@ -784,7 +782,7 @@
 
         expect(pubspec.features, contains('foobar'));
 
-        var feature = pubspec.features['foobar'];
+        var feature = pubspec.features['foobar']!;
         expect(feature.name, equals('foobar'));
         expect(feature.onByDefault, isTrue);
         expect(feature.dependencies, hasLength(2));
@@ -800,7 +798,7 @@
         test('can be null', () {
           var pubspec =
               Pubspec.parse('features: {foobar: {requires: null}}', sources);
-          expect(pubspec.features['foobar'].requires, isEmpty);
+          expect(pubspec.features['foobar']!.requires, isEmpty);
         });
 
         test('must be a list', () {
diff --git a/test/pubspec_utils_test.dart b/test/pubspec_utils_test.dart
index 60863f4..6622c1c 100644
--- a/test/pubspec_utils_test.dart
+++ b/test/pubspec_utils_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/pubspec_utils.dart';
 import 'package:pub_semver/pub_semver.dart';
 import 'package:test/test.dart';
@@ -47,8 +45,10 @@
     });
 
     test('works on compatible version union', () {
-      final constraint1 = VersionConstraint.parse('>=1.2.3 <2.0.0');
-      final constraint2 = VersionConstraint.parse('>2.2.3 <=4.0.0');
+      final constraint1 =
+          VersionConstraint.parse('>=1.2.3 <2.0.0') as VersionRange;
+      final constraint2 =
+          VersionConstraint.parse('>2.2.3 <=4.0.0') as VersionRange;
       final constraint = VersionUnion.fromRanges([constraint1, constraint2]);
 
       final removedUpperBound = stripUpperBound(constraint) as VersionRange;
diff --git a/test/rate_limited_scheduler_test.dart b/test/rate_limited_scheduler_test.dart
index 632efbf..8562b07 100644
--- a/test/rate_limited_scheduler_test.dart
+++ b/test/rate_limited_scheduler_test.dart
@@ -2,11 +2,8 @@
 // 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.
 
-// @dart=2.10
-
 import 'dart:async';
 
-import 'package:pedantic/pedantic.dart';
 import 'package:pub/src/rate_limited_scheduler.dart';
 import 'package:test/test.dart';
 
@@ -19,8 +16,8 @@
     final isBeingProcessed = threeCompleters();
 
     Future<String> f(String i) async {
-      isBeingProcessed[i].complete();
-      await completers[i].future;
+      isBeingProcessed[i]!.complete();
+      await completers[i]!.future;
       return i.toUpperCase();
     }
 
@@ -30,11 +27,11 @@
       preschedule('b');
       preschedule('c');
       await Future.wait(
-          [isBeingProcessed['a'].future, isBeingProcessed['b'].future]);
-      expect(isBeingProcessed['c'].isCompleted, isFalse);
-      completers['a'].complete();
-      await isBeingProcessed['c'].future;
-      completers['c'].complete();
+          [isBeingProcessed['a']!.future, isBeingProcessed['b']!.future]);
+      expect(isBeingProcessed['c']!.isCompleted, isFalse);
+      completers['a']!.complete();
+      await isBeingProcessed['c']!.future;
+      completers['c']!.complete();
       expect(await scheduler.schedule('c'), 'C');
     });
   });
@@ -45,8 +42,8 @@
     final isBeingProcessed = threeCompleters();
 
     Future<String> f(String i) async {
-      isBeingProcessed[i].complete();
-      await completers[i].future;
+      isBeingProcessed[i]!.complete();
+      await completers[i]!.future;
       return i.toUpperCase();
     }
 
@@ -57,18 +54,18 @@
         preschedule1('a');
         preschedule2('b');
         preschedule1('c');
-        await isBeingProcessed['a'].future;
+        await isBeingProcessed['a']!.future;
         // b, c should not start processing due to rate-limiting.
-        expect(isBeingProcessed['b'].isCompleted, isFalse);
-        expect(isBeingProcessed['c'].isCompleted, isFalse);
+        expect(isBeingProcessed['b']!.isCompleted, isFalse);
+        expect(isBeingProcessed['c']!.isCompleted, isFalse);
       });
-      completers['a'].complete();
+      completers['a']!.complete();
       // b is removed from the queue, now c should start processing.
-      await isBeingProcessed['c'].future;
-      completers['c'].complete();
+      await isBeingProcessed['c']!.future;
+      completers['c']!.complete();
       expect(await scheduler.schedule('c'), 'C');
       // b is not on the queue anymore.
-      expect(isBeingProcessed['b'].isCompleted, isFalse);
+      expect(isBeingProcessed['b']!.isCompleted, isFalse);
     });
   });
 
@@ -78,27 +75,27 @@
     final isBeingProcessed = threeCompleters();
 
     Future<String> f(String i) async {
-      isBeingProcessed[i].complete();
-      await completers[i].future;
+      isBeingProcessed[i]!.complete();
+      await completers[i]!.future;
       return i.toUpperCase();
     }
 
     final scheduler = RateLimitedScheduler(f, maxConcurrentOperations: 1);
 
-    Future b;
+    Future? b;
     await scheduler.withPrescheduling((preschedule) async {
       preschedule('a');
       preschedule('b');
-      await isBeingProcessed['a'].future;
+      await isBeingProcessed['a']!.future;
       // b should not start processing due to rate-limiting.
-      expect(isBeingProcessed['b'].isCompleted, isFalse);
+      expect(isBeingProcessed['b']!.isCompleted, isFalse);
       b = scheduler.schedule('b');
     });
-    completers['a'].complete();
+    completers['a']!.complete();
     expect(await scheduler.schedule('a'), 'A');
     // b was scheduled, so it should get processed now
-    await isBeingProcessed['b'].future;
-    completers['b'].complete();
+    await isBeingProcessed['b']!.future;
+    completers['b']!.complete();
     expect(await b, 'B');
   });
 
@@ -107,14 +104,14 @@
     final isBeingProcessed = threeCompleters();
 
     Future<String> f(String i) async {
-      isBeingProcessed[i].complete();
-      await completers[i].future;
+      isBeingProcessed[i]!.complete();
+      await completers[i]!.future;
       return i.toUpperCase();
     }
 
     final scheduler = RateLimitedScheduler(f, maxConcurrentOperations: 2);
 
-    completers['a'].complete();
+    completers['a']!.complete();
     expect(await scheduler.schedule('a'), 'A');
     // Would fail if isBeingProcessed['a'] was completed twice
     expect(await scheduler.schedule('a'), 'A');
@@ -125,8 +122,8 @@
     final isBeingProcessed = threeCompleters();
 
     Future<String> f(String i) async {
-      isBeingProcessed[i].complete();
-      await completers[i].future;
+      isBeingProcessed[i]!.complete();
+      await completers[i]!.future;
       return i.toUpperCase();
     }
 
@@ -134,12 +131,12 @@
     await scheduler.withPrescheduling((preschedule) async {
       preschedule('a');
       preschedule('b');
-      await isBeingProcessed['a'].future;
+      await isBeingProcessed['a']!.future;
       final cResult = scheduler.schedule('c');
-      expect(isBeingProcessed['b'].isCompleted, isFalse);
-      completers['a'].complete();
-      completers['c'].complete();
-      await isBeingProcessed['c'].future;
+      expect(isBeingProcessed['b']!.isCompleted, isFalse);
+      completers['a']!.complete();
+      completers['c']!.complete();
+      await isBeingProcessed['c']!.future;
       // 'c' is done before we allow 'b' to finish processing
       expect(await cResult, 'C');
     });
@@ -150,8 +147,8 @@
     final isBeingProcessed = threeCompleters();
 
     Future<String> f(String i) async {
-      isBeingProcessed[i].complete();
-      await completers[i].future;
+      isBeingProcessed[i]!.complete();
+      await completers[i]!.future;
       return i.toUpperCase();
     }
 
@@ -161,14 +158,15 @@
       preschedule('a');
       preschedule('b');
       preschedule('c');
-      await isBeingProcessed['a'].future;
-      await isBeingProcessed['b'].future;
-      expect(isBeingProcessed['c'].isCompleted, isFalse);
-      unawaited(completers['c'].future.catchError((_) {}));
-      completers['c'].completeError('errorC');
-      completers['a'].completeError('errorA');
-      await isBeingProcessed['c'].future;
-      completers['b'].completeError('errorB');
+
+      await isBeingProcessed['a']!.future;
+      await isBeingProcessed['b']!.future;
+      expect(isBeingProcessed['c']!.isCompleted, isFalse);
+      unawaited(completers['c']!.future.catchError((_) {}));
+      completers['c']!.completeError('errorC');
+      completers['a']!.completeError('errorA');
+      await isBeingProcessed['c']!.future;
+      completers['b']!.completeError('errorB');
       expect(() async => await scheduler.schedule('a'), throwsA('errorA'));
       expect(() async => await scheduler.schedule('b'), throwsA('errorB'));
       expect(() async => await scheduler.schedule('c'), throwsA('errorC'));
@@ -179,9 +177,9 @@
     final completers = threeCompleters();
     final isBeingProcessed = threeCompleters();
 
-    Future<String> f(String i) async {
-      isBeingProcessed[i].complete();
-      await completers[i].future;
+    Future<String?> f(String i) async {
+      isBeingProcessed[i]!.complete();
+      await completers[i]!.future;
       return Zone.current['zoneValue'];
     }
 
@@ -198,16 +196,16 @@
       }, zoneValues: {'zoneValue': 'C'});
 
       await runZoned(() async {
-        await isBeingProcessed['a'].future;
-        await isBeingProcessed['b'].future;
+        await isBeingProcessed['a']!.future;
+        await isBeingProcessed['b']!.future;
         // This will put 'c' in front of the queue, but in a zone with zoneValue
         // bound to S.
         final f = expectLater(scheduler.schedule('c'), completion('S'));
-        completers['a'].complete();
-        completers['b'].complete();
+        completers['a']!.complete();
+        completers['b']!.complete();
         expect(await scheduler.schedule('a'), 'A');
         expect(await scheduler.schedule('b'), 'B');
-        completers['c'].complete();
+        completers['c']!.complete();
         await f;
       }, zoneValues: {'zoneValue': 'S'});
     });
diff --git a/test/real_version_test.dart b/test/real_version_test.dart
index 484a7f6..80afab7 100644
--- a/test/real_version_test.dart
+++ b/test/real_version_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io';
 
 import 'package:path/path.dart' as path;
diff --git a/test/reformat_ranges_test.dart b/test/reformat_ranges_test.dart
index 4af9cf7..35b085f 100644
--- a/test/reformat_ranges_test.dart
+++ b/test/reformat_ranges_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/package_name.dart';
 import 'package:pub/src/solver/reformat_ranges.dart';
 import 'package:pub/src/utils.dart';
diff --git a/test/remove/remove_test.dart b/test/remove/remove_test.dart
index 777d41b..e369c85 100644
--- a/test/remove/remove_test.dart
+++ b/test/remove/remove_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:io' show File;
 
 import 'package:path/path.dart' as p;
@@ -14,7 +12,8 @@
 
 void main() {
   test('removes a package from dependencies', () async {
-    await servePackages((builder) => builder.serve('foo', '1.2.3'));
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
 
     await d.appDir({'foo': '1.2.3'}).create();
     await pubGet();
@@ -28,11 +27,10 @@
 
   test('removing a package from dependencies does not affect dev_dependencies',
       () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.3');
-      builder.serve('foo', '1.2.2');
-      builder.serve('bar', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.2.3')
+      ..serve('foo', '1.2.2')
+      ..serve('bar', '2.0.0');
 
     await d.dir(appPath, [
       d.file('pubspec.yaml', '''
@@ -62,7 +60,8 @@
   });
 
   test('dry-run does not actually remove dependency', () async {
-    await servePackages((builder) => builder.serve('foo', '1.2.3'));
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
 
     await d.appDir({'foo': '1.2.3'}).create();
     await pubGet();
@@ -100,7 +99,8 @@
   });
 
   test('removes a package from dev_dependencies', () async {
-    await servePackages((builder) => builder.serve('foo', '1.2.3'));
+    final server = await servePackages();
+    server.serve('foo', '1.2.3');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -122,12 +122,11 @@
 
   test('removes multiple packages from dependencies and dev_dependencies',
       () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.3');
-      builder.serve('bar', '2.3.4');
-      builder.serve('baz', '3.2.1');
-      builder.serve('jfj', '0.2.1');
-    });
+    await servePackages()
+      ..serve('foo', '1.2.3')
+      ..serve('bar', '2.3.4')
+      ..serve('baz', '3.2.1')
+      ..serve('jfj', '0.2.1');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -152,7 +151,8 @@
   });
 
   test('removes git dependencies', () async {
-    await servePackages((builder) => builder.serve('bar', '1.2.3'));
+    final server = await servePackages();
+    server.serve('bar', '1.2.3');
 
     ensureGit();
     final repo = d.git('foo.git', [
@@ -175,7 +175,8 @@
   });
 
   test('removes path dependencies', () async {
-    await servePackages((builder) => builder.serve('bar', '1.2.3'));
+    final server = await servePackages();
+    server.serve('bar', '1.2.3');
     await d
         .dir('foo', [d.libDir('foo'), d.libPubspec('foo', '0.0.1')]).create();
 
@@ -192,16 +193,16 @@
   });
 
   test('removes hosted dependencies', () async {
-    await servePackages((builder) => builder.serve('bar', '2.0.1'));
+    final server = await servePackages();
+    server.serve('bar', '2.0.1');
 
-    var server = await PackageServer.start((builder) {
-      builder.serve('foo', '1.2.3');
-    });
+    var custom = await startPackageServer();
+    custom.serve('foo', '1.2.3');
 
     await d.appDir({
       'foo': {
         'version': '1.2.3',
-        'hosted': {'name': 'foo', 'url': 'http://localhost:${server.port}'}
+        'hosted': {'name': 'foo', 'url': 'http://localhost:${custom.port}'}
       },
       'bar': '2.0.1'
     }).create();
@@ -214,10 +215,9 @@
   });
 
   test('preserves comments', () async {
-    await servePackages((builder) {
-      builder.serve('bar', '1.0.0');
-      builder.serve('foo', '1.0.0');
-    });
+    await servePackages()
+      ..serve('bar', '1.0.0')
+      ..serve('foo', '1.0.0');
 
     await d.dir(appPath, [
       d.file('pubspec.yaml', '''
diff --git a/test/run/allows_dart_extension_test.dart b/test/run/allows_dart_extension_test.dart
index f88e9bd..962270f 100644
--- a/test/run/allows_dart_extension_test.dart
+++ b/test/run/allows_dart_extension_test.dart
@@ -2,14 +2,12 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
-const SCRIPT = """
+const _script = """
 import 'dart:io';
 
 main() {
@@ -23,7 +21,7 @@
   test('allows a ".dart" extension on the argument', () async {
     await d.dir(appPath, [
       d.appPubspec(),
-      d.dir('bin', [d.file('script.dart', SCRIPT)])
+      d.dir('bin', [d.file('script.dart', _script)])
     ]).create();
 
     await pubGet();
diff --git a/test/run/app_can_read_from_stdin_test.dart b/test/run/app_can_read_from_stdin_test.dart
index a0c3983..20f9b32 100644
--- a/test/run/app_can_read_from_stdin_test.dart
+++ b/test/run/app_can_read_from_stdin_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
diff --git a/test/run/enable_experiments_test.dart b/test/run/enable_experiments_test.dart
index 95468f0..dd6512b 100644
--- a/test/run/enable_experiments_test.dart
+++ b/test/run/enable_experiments_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
diff --git a/test/run/errors_if_no_executable_is_given_test.dart b/test/run/errors_if_no_executable_is_given_test.dart
index 92f0073..3e5abd6 100644
--- a/test/run/errors_if_no_executable_is_given_test.dart
+++ b/test/run/errors_if_no_executable_is_given_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/run/errors_if_only_transitive_dependency_test.dart b/test/run/errors_if_only_transitive_dependency_test.dart
index d5d1601..71fcd3d 100644
--- a/test/run/errors_if_only_transitive_dependency_test.dart
+++ b/test/run/errors_if_only_transitive_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/run/errors_if_path_in_dependency_test.dart b/test/run/errors_if_path_in_dependency_test.dart
index 2affef7..329650b 100644
--- a/test/run/errors_if_path_in_dependency_test.dart
+++ b/test/run/errors_if_path_in_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/run/forwards_signal_posix_test.dart b/test/run/forwards_signal_posix_test.dart
index 17fb0ea..5205145 100644
--- a/test/run/forwards_signal_posix_test.dart
+++ b/test/run/forwards_signal_posix_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 // Windows doesn't support sending signals.
 // TODO(sigurdm): Test this when vm-args are provided.
 // This test doesn't work when we subprocess instead of an isolate
@@ -25,7 +23,7 @@
   ProcessSignal.sigwinch,
 ];
 
-const SCRIPT = """
+const _script = """
 import 'dart:io';
 
 main() {
@@ -43,7 +41,7 @@
   test('forwards signals to the inner script', () async {
     await d.dir(appPath, [
       d.appPubspec(),
-      d.dir('bin', [d.file('script.dart', SCRIPT)])
+      d.dir('bin', [d.file('script.dart', _script)])
     ]).create();
 
     await pubGet();
diff --git a/test/run/includes_parent_directories_of_entrypoint_test.dart b/test/run/includes_parent_directories_of_entrypoint_test.dart
index f17b548..6bc4e27 100644
--- a/test/run/includes_parent_directories_of_entrypoint_test.dart
+++ b/test/run/includes_parent_directories_of_entrypoint_test.dart
@@ -2,15 +2,13 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
-const SCRIPT = r"""
+const _script = r"""
 import '../../a.dart';
 import '../b.dart';
 main() {
@@ -28,7 +26,7 @@
         d.file('a.dart', "var a = 'a';"),
         d.dir('a', [
           d.file('b.dart', "var b = 'b';"),
-          d.dir('b', [d.file('app.dart', SCRIPT)])
+          d.dir('b', [d.file('app.dart', _script)])
         ])
       ])
     ]).create();
diff --git a/test/run/loads_package_imports_in_a_dependency_test.dart b/test/run/loads_package_imports_in_a_dependency_test.dart
index 66c261d..7bfb047 100644
--- a/test/run/loads_package_imports_in_a_dependency_test.dart
+++ b/test/run/loads_package_imports_in_a_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
diff --git a/test/run/nonexistent_dependency_test.dart b/test/run/nonexistent_dependency_test.dart
index 5b0f941..2051149 100644
--- a/test/run/nonexistent_dependency_test.dart
+++ b/test/run/nonexistent_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/run/nonexistent_script_in_dependency_test.dart b/test/run/nonexistent_script_in_dependency_test.dart
index 5153c25..62816df 100644
--- a/test/run/nonexistent_script_in_dependency_test.dart
+++ b/test/run/nonexistent_script_in_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
diff --git a/test/run/nonexistent_script_test.dart b/test/run/nonexistent_script_test.dart
index 9930430..0e12ee1 100644
--- a/test/run/nonexistent_script_test.dart
+++ b/test/run/nonexistent_script_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
diff --git a/test/run/package_api_test.dart b/test/run/package_api_test.dart
index e7b814f..4d05408 100644
--- a/test/run/package_api_test.dart
+++ b/test/run/package_api_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
 
@@ -51,11 +49,10 @@
   });
 
   test('a snapshotted application sees a file: package root', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', contents: [
-        d.dir('bin', [d.file('script.dart', _script)])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', contents: [
+      d.dir('bin', [d.file('script.dart', _script)])
+    ]);
 
     await d.dir(appPath, [
       d.appPubspec({'foo': 'any'})
@@ -75,8 +72,8 @@
             .toString()));
     expect(pub.stdout,
         emits(p.toUri(p.join(d.sandbox, 'myapp/lib/resource.txt')).toString()));
-    var fooResourcePath = p.join(
-        globalPackageServer.pathInCache('foo', '1.0.0'), 'lib/resource.txt');
+    var fooResourcePath =
+        p.join(globalServer.pathInCache('foo', '1.0.0'), 'lib/resource.txt');
     expect(pub.stdout, emits(p.toUri(fooResourcePath).toString()));
     await pub.shouldExit(0);
   });
diff --git a/test/run/passes_along_arguments_test.dart b/test/run/passes_along_arguments_test.dart
index d2beebf..624d9f2 100644
--- a/test/run/passes_along_arguments_test.dart
+++ b/test/run/passes_along_arguments_test.dart
@@ -2,14 +2,12 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
-const SCRIPT = '''
+const _script = '''
 main(List<String> args) {
   print(args.join(" "));
 }
@@ -19,7 +17,7 @@
   test('passes arguments to the spawned script', () async {
     await d.dir(appPath, [
       d.appPubspec(),
-      d.dir('bin', [d.file('args.dart', SCRIPT)])
+      d.dir('bin', [d.file('args.dart', _script)])
     ]).create();
 
     await pubGet();
diff --git a/test/run/precompile_test.dart b/test/run/precompile_test.dart
index ac663d5..2d70b4c 100644
--- a/test/run/precompile_test.dart
+++ b/test/run/precompile_test.dart
@@ -2,14 +2,12 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
-const SCRIPT = r'''
+const _script = r'''
 import 'dart:io';
 
 main(List<String> args) {
@@ -23,11 +21,11 @@
       d.appPubspec({'test': '1.0.0'}),
     ]).create();
 
-    await servePackages((server) => server
-      ..serve('test', '1.0.0', contents: [
-        d.dir('bin',
-            [d.file('test.dart', 'main(List<String> args) => print("hello");')])
-      ]));
+    final server = await servePackages();
+    server.serve('test', '1.0.0', contents: [
+      d.dir('bin',
+          [d.file('test.dart', 'main(List<String> args) => print("hello");')])
+    ]);
 
     await pubGet(args: ['--no-precompile']);
   }
@@ -59,10 +57,10 @@
       d.appPubspec({'test': '1.0.0'}),
     ]).create();
 
-    await servePackages((server) => server
-      ..serve('test', '1.0.0', contents: [
-        d.dir('bin', [d.file('test.dart', SCRIPT)])
-      ]));
+    final server = await servePackages();
+    server.serve('test', '1.0.0', contents: [
+      d.dir('bin', [d.file('test.dart', _script)])
+    ]);
 
     await pubGet(
         args: ['--no-precompile'], environment: {'PUB_CACHE': '.pub_cache'});
@@ -82,10 +80,10 @@
       d.appPubspec({'test': '1.0.0'}),
     ]).create();
 
-    await servePackages((server) => server
-      ..serve('test', '1.0.0', contents: [
-        d.dir('bin', [d.file('test.dart', SCRIPT)])
-      ]));
+    final server = await servePackages();
+    server.serve('test', '1.0.0', contents: [
+      d.dir('bin', [d.file('test.dart', _script)])
+    ]);
 
     await pubGet(
         args: ['--precompile'],
@@ -106,10 +104,10 @@
       d.appPubspec({'test': '1.0.0'}),
     ]).create();
 
-    await servePackages((server) => server
-      ..serve('test', '1.0.0', contents: [
-        d.dir('bin', [d.file('test.dart', SCRIPT)])
-      ]));
+    final server = await servePackages();
+    server.serve('test', '1.0.0', contents: [
+      d.dir('bin', [d.file('test.dart', _script)])
+    ]);
 
     await pubGet(
         args: ['--precompile'],
diff --git a/test/run/runs_app_in_directory_in_entrypoint_test.dart b/test/run/runs_app_in_directory_in_entrypoint_test.dart
index ef720c5..ac8af0d 100644
--- a/test/run/runs_app_in_directory_in_entrypoint_test.dart
+++ b/test/run/runs_app_in_directory_in_entrypoint_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
diff --git a/test/run/runs_app_in_entrypoint_test.dart b/test/run/runs_app_in_entrypoint_test.dart
index 3f3ed38..6cb932a 100644
--- a/test/run/runs_app_in_entrypoint_test.dart
+++ b/test/run/runs_app_in_entrypoint_test.dart
@@ -2,14 +2,12 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
-const SCRIPT = """
+const _script = """
 import 'dart:io';
 
 main() {
@@ -23,7 +21,7 @@
   test('runs a Dart application in the entrypoint package', () async {
     await d.dir(appPath, [
       d.appPubspec(),
-      d.dir('bin', [d.file('script.dart', SCRIPT)])
+      d.dir('bin', [d.file('script.dart', _script)])
     ]).create();
 
     await pubGet();
diff --git a/test/run/runs_from_a_dependency_override_after_dependency_test.dart b/test/run/runs_from_a_dependency_override_after_dependency_test.dart
index c3cde77..c11bacb 100644
--- a/test/run/runs_from_a_dependency_override_after_dependency_test.dart
+++ b/test/run/runs_from_a_dependency_override_after_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -12,14 +10,13 @@
 void main() {
   // Regression test for issue 23113
   test('runs a named Dart application in a dependency', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'name': 'foo',
-        'version': '1.0.0'
-      }, contents: [
-        d.dir('bin', [d.file('bar.dart', "main() => print('foobar');")])
-      ]);
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'name': 'foo',
+      'version': '1.0.0'
+    }, contents: [
+      d.dir('bin', [d.file('bar.dart', "main() => print('foobar');")])
+    ]);
 
     await d.dir(appPath, [
       d.appPubspec({'foo': null})
diff --git a/test/run/runs_named_app_in_dependency_test.dart b/test/run/runs_named_app_in_dependency_test.dart
index d554eb4..8f3d73d 100644
--- a/test/run/runs_named_app_in_dependency_test.dart
+++ b/test/run/runs_named_app_in_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
diff --git a/test/run/runs_named_app_in_dev_dependency_test.dart b/test/run/runs_named_app_in_dev_dependency_test.dart
index f1493d4..287f05b 100644
--- a/test/run/runs_named_app_in_dev_dependency_test.dart
+++ b/test/run/runs_named_app_in_dev_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
diff --git a/test/run/runs_shorthand_app_in_dependency_test.dart b/test/run/runs_shorthand_app_in_dependency_test.dart
index cd3c66a..455e049 100644
--- a/test/run/runs_shorthand_app_in_dependency_test.dart
+++ b/test/run/runs_shorthand_app_in_dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
diff --git a/test/run/runs_the_script_in_checked_mode_test.dart b/test/run/runs_the_script_in_checked_mode_test.dart
index 8b8e214..8b4010a 100644
--- a/test/run/runs_the_script_in_checked_mode_test.dart
+++ b/test/run/runs_the_script_in_checked_mode_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
diff --git a/test/run/runs_the_script_in_unchecked_mode_test.dart b/test/run/runs_the_script_in_unchecked_mode_test.dart
index da86989..026a748 100644
--- a/test/run/runs_the_script_in_unchecked_mode_test.dart
+++ b/test/run/runs_the_script_in_unchecked_mode_test.dart
@@ -2,14 +2,12 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
-const SCRIPT = '''
+const _script = '''
 main() {
   assert(false);
   print("no checks");
@@ -20,7 +18,7 @@
   test('runs the script without assertions by default', () async {
     await d.dir(appPath, [
       d.appPubspec(),
-      d.dir('bin', [d.file('script.dart', SCRIPT)])
+      d.dir('bin', [d.file('script.dart', _script)])
     ]).create();
 
     await pubGet();
diff --git a/test/sdk_test.dart b/test/sdk_test.dart
index e9b7f1d..6e50ff0 100644
--- a/test/sdk_test.dart
+++ b/test/sdk_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:pub/src/io.dart';
@@ -15,9 +13,8 @@
 void main() {
   forBothPubGetAndUpgrade((command) {
     setUp(() async {
-      await servePackages((builder) {
-        builder.serve('bar', '1.0.0');
-      });
+      final server = await servePackages();
+      server.serve('bar', '1.0.0');
 
       await d.dir('flutter', [
         d.dir('packages', [
diff --git a/test/snapshot_test.dart b/test/snapshot_test.dart
index 6ad44f6..8143f7e 100644
--- a/test/snapshot_test.dart
+++ b/test/snapshot_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
 
@@ -13,17 +11,15 @@
 void main() {
   group('creates a snapshot', () {
     test('for an immediate dependency', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3', contents: [
-          d.dir('bin', [
-            d.file('hello.dart', "void main() => print('hello!');"),
-            d.file('goodbye.dart', "void main() => print('goodbye!');"),
-            d.file('shell.sh', 'echo shell'),
-            d.dir(
-                'subdir', [d.file('sub.dart', "void main() => print('sub!');")])
-          ])
-        ]);
-      });
+      final server = await servePackages();
+      server.serve('foo', '1.2.3', contents: [
+        d.dir('bin', [
+          d.file('hello.dart', "void main() => print('hello!');"),
+          d.file('goodbye.dart', "void main() => print('goodbye!');"),
+          d.file('shell.sh', 'echo shell'),
+          d.dir('subdir', [d.file('sub.dart', "void main() => print('sub!');")])
+        ])
+      ]);
 
       await d.appDir({'foo': '1.2.3'}).create();
 
@@ -51,8 +47,8 @@
     });
 
     test("for an immediate dependency that's also transitive", () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.2.3', contents: [
+      await servePackages()
+        ..serve('foo', '1.2.3', contents: [
           d.dir('bin', [
             d.file('hello.dart', "void main() => print('hello!');"),
             d.file('goodbye.dart', "void main() => print('goodbye!');"),
@@ -60,9 +56,8 @@
             d.dir(
                 'subdir', [d.file('sub.dart', "void main() => print('sub!');")])
           ])
-        ]);
-        builder.serve('bar', '1.2.3', deps: {'foo': '1.2.3'});
-      });
+        ])
+        ..serve('bar', '1.2.3', deps: {'foo': '1.2.3'});
 
       await d.appDir({'foo': '1.2.3'}).create();
 
@@ -91,12 +86,11 @@
 
     group('again if', () {
       test('its package is updated', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3', contents: [
-            d.dir('bin',
-                [d.file('hello.dart', "void main() => print('hello!');")])
-          ]);
-        });
+        final server = await servePackages();
+        server.serve('foo', '1.2.3', contents: [
+          d.dir(
+              'bin', [d.file('hello.dart', "void main() => print('hello!');")])
+        ]);
 
         await d.appDir({'foo': 'any'}).create();
 
@@ -107,12 +101,10 @@
           d.file('hello.dart-$versionSuffix.snapshot', contains('hello!'))
         ]).validate();
 
-        globalPackageServer.add((builder) {
-          builder.serve('foo', '1.2.4', contents: [
-            d.dir('bin',
-                [d.file('hello.dart', "void main() => print('hello 2!');")])
-          ]);
-        });
+        server.serve('foo', '1.2.4', contents: [
+          d.dir('bin',
+              [d.file('hello.dart', "void main() => print('hello 2!');")])
+        ]);
 
         await pubUpgrade(
             args: ['--precompile'], output: contains('Built foo:hello.'));
@@ -127,22 +119,22 @@
       });
 
       test('a dependency of its package is updated', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.2.3', pubspec: {
-            'dependencies': {'bar': 'any'}
-          }, contents: [
-            d.dir('bin', [
-              d.file('hello.dart', """
+        final server = await servePackages();
+
+        server.serve('foo', '1.2.3', pubspec: {
+          'dependencies': {'bar': 'any'}
+        }, contents: [
+          d.dir('bin', [
+            d.file('hello.dart', """
             import 'package:bar/bar.dart';
 
             void main() => print(message);
           """)
-            ])
-          ]);
-          builder.serve('bar', '1.2.3', contents: [
-            d.dir('lib', [d.file('bar.dart', "final message = 'hello!';")])
-          ]);
-        });
+          ])
+        ]);
+        server.serve('bar', '1.2.3', contents: [
+          d.dir('lib', [d.file('bar.dart', "final message = 'hello!';")])
+        ]);
 
         await d.appDir({'foo': 'any'}).create();
 
@@ -153,11 +145,9 @@
           d.file('hello.dart-$versionSuffix.snapshot', contains('hello!'))
         ]).validate();
 
-        globalPackageServer.add((builder) {
-          builder.serve('bar', '1.2.4', contents: [
-            d.dir('lib', [d.file('bar.dart', "final message = 'hello 2!';")]),
-          ]);
-        });
+        server.serve('bar', '1.2.4', contents: [
+          d.dir('lib', [d.file('bar.dart', "final message = 'hello 2!';")]),
+        ]);
 
         await pubUpgrade(
             args: ['--precompile'], output: contains('Built foo:hello.'));
@@ -209,12 +199,11 @@
       });
 
       test('the SDK is out of date', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '5.6.7', contents: [
-            d.dir('bin',
-                [d.file('hello.dart', "void main() => print('hello!');")])
-          ]);
-        });
+        final server = await servePackages();
+        server.serve('foo', '5.6.7', contents: [
+          d.dir(
+              'bin', [d.file('hello.dart', "void main() => print('hello!');")])
+        ]);
 
         await d.appDir({'foo': '5.6.7'}).create();
 
diff --git a/test/test_pub.dart b/test/test_pub.dart
index 0f77615..025a0a4 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -2,15 +2,13 @@
 // 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.
 
-// @dart=2.10
-
 /// Test infrastructure for testing pub.
 ///
 /// Unlike typical unit tests, most pub tests are integration tests that stage
 /// some stuff on the file system, run pub, and then validate the results. This
 /// library provides an API to build tests like that.
-import 'dart:async';
 import 'dart:convert';
+import 'dart:core';
 import 'dart:io';
 import 'dart:isolate';
 import 'dart:math';
@@ -28,7 +26,6 @@
 import 'package:pub/src/io.dart';
 import 'package:pub/src/lock_file.dart';
 import 'package:pub/src/log.dart' as log;
-import 'package:pub/src/sdk.dart';
 import 'package:pub/src/source_registry.dart';
 import 'package:pub/src/system_cache.dart';
 import 'package:pub/src/utils.dart';
@@ -39,11 +36,9 @@
 import 'package:test_process/test_process.dart';
 
 import 'descriptor.dart' as d;
-import 'descriptor_server.dart';
 import 'package_server.dart';
 
-export 'descriptor_server.dart';
-export 'package_server.dart';
+export 'package_server.dart' show PackageServer;
 
 /// A [Matcher] that matches JavaScript generated by dart2js with minification
 /// enabled.
@@ -82,7 +77,7 @@
         orElse: () => null) as Map<String, dynamic>;
 
 /// The suffix appended to a built snapshot.
-final versionSuffix = testVersion ?? sdk.version;
+final versionSuffix = testVersion;
 
 /// Enum identifying a pub command that can be run with a well-defined success
 /// output.
@@ -130,14 +125,14 @@
 // TODO(rnystrom): Clean up other tests to call this when possible.
 Future<void> pubCommand(
   RunCommand command, {
-  Iterable<String> args,
-  output,
-  error,
-  silent,
-  warning,
-  int exitCode,
-  Map<String, String> environment,
-  String workingDirectory,
+  Iterable<String>? args,
+  Object? output,
+  Object? error,
+  Object? silent,
+  Object? warning,
+  int? exitCode,
+  Map<String, String?>? environment,
+  String? workingDirectory,
   includeParentEnvironment = true,
 }) async {
   if (error != null && warning != null) {
@@ -167,13 +162,13 @@
 }
 
 Future<void> pubAdd({
-  Iterable<String> args,
-  output,
-  error,
-  warning,
-  int exitCode,
-  Map<String, String> environment,
-  String workingDirectory,
+  Iterable<String>? args,
+  Object? output,
+  Object? error,
+  Object? warning,
+  int? exitCode,
+  Map<String, String>? environment,
+  String? workingDirectory,
 }) async =>
     await pubCommand(
       RunCommand.add,
@@ -187,13 +182,13 @@
     );
 
 Future<void> pubGet({
-  Iterable<String> args,
-  output,
-  error,
-  warning,
-  int exitCode,
-  Map<String, String> environment,
-  String workingDirectory,
+  Iterable<String>? args,
+  Object? output,
+  Object? error,
+  Object? warning,
+  int? exitCode,
+  Map<String, String?>? environment,
+  String? workingDirectory,
   bool includeParentEnvironment = true,
 }) async =>
     await pubCommand(
@@ -209,13 +204,13 @@
     );
 
 Future<void> pubUpgrade(
-        {Iterable<String> args,
-        output,
-        error,
-        warning,
-        int exitCode,
-        Map<String, String> environment,
-        String workingDirectory}) async =>
+        {Iterable<String>? args,
+        Object? output,
+        Object? error,
+        Object? warning,
+        int? exitCode,
+        Map<String, String>? environment,
+        String? workingDirectory}) async =>
     await pubCommand(
       RunCommand.upgrade,
       args: args,
@@ -228,13 +223,13 @@
     );
 
 Future<void> pubDowngrade({
-  Iterable<String> args,
-  output,
-  error,
-  warning,
-  int exitCode,
-  Map<String, String> environment,
-  String workingDirectory,
+  Iterable<String>? args,
+  Object? output,
+  Object? error,
+  Object? warning,
+  int? exitCode,
+  Map<String, String>? environment,
+  String? workingDirectory,
 }) async =>
     await pubCommand(
       RunCommand.downgrade,
@@ -248,13 +243,13 @@
     );
 
 Future<void> pubRemove({
-  Iterable<String> args,
-  output,
-  error,
-  warning,
-  int exitCode,
-  Map<String, String> environment,
-  String workingDirectory,
+  Iterable<String>? args,
+  Object? output,
+  Object? error,
+  Object? warning,
+  int? exitCode,
+  Map<String, String>? environment,
+  String? workingDirectory,
 }) async =>
     await pubCommand(
       RunCommand.remove,
@@ -276,8 +271,8 @@
 /// Returns the `pub run` process.
 Future<PubProcess> pubRun(
     {bool global = false,
-    Iterable<String> args,
-    Map<String, String> environment,
+    required Iterable<String> args,
+    Map<String, String>? environment,
     bool verbose = true}) async {
   var pubArgs = global ? ['global', 'run'] : ['run'];
   pubArgs.addAll(args);
@@ -321,15 +316,15 @@
 /// If [environment] is given, any keys in it will override the environment
 /// variables passed to the spawned process.
 Future<void> runPub(
-    {List<String> args,
-    output,
-    error,
-    outputJson,
-    silent,
-    int exitCode,
-    String workingDirectory,
-    Map<String, String> environment,
-    List<String> input,
+    {List<String>? args,
+    Object? output,
+    Object? error,
+    Object? outputJson,
+    Object? silent,
+    int? exitCode,
+    String? workingDirectory,
+    Map<String, String?>? environment,
+    List<String>? input,
     includeParentEnvironment = true}) async {
   exitCode ??= exit_codes.SUCCESS;
   // Cannot pass both output and outputJson.
@@ -375,9 +370,9 @@
 /// Any futures in [args] will be resolved before the process is started.
 Future<PubProcess> startPublish(
   PackageServer server, {
-  List<String> args,
+  List<String>? args,
   String authMethod = 'oauth2',
-  Map<String, String> environment,
+  Map<String, String>? environment,
   String path = '',
 }) async {
   var tokenEndpoint = Uri.parse(server.url).resolve('/token').toString();
@@ -416,28 +411,19 @@
 String testVersion = '0.1.2+3';
 
 /// Gets the environment variables used to run pub in a test context.
-Map<String, String> getPubTestEnvironment([String tokenEndpoint]) {
-  var environment = {
-    'CI': 'false', // unless explicitly given tests don't run pub in CI mode
-    '_PUB_TESTING': 'true',
-    '_PUB_TEST_CONFIG_DIR': _pathInSandbox(configPath),
-    'PUB_CACHE': _pathInSandbox(cachePath),
-    'PUB_ENVIRONMENT': 'test-environment',
+Map<String, String> getPubTestEnvironment([String? tokenEndpoint]) => {
+      'CI': 'false', // unless explicitly given tests don't run pub in CI mode
+      '_PUB_TESTING': 'true',
+      '_PUB_TEST_CONFIG_DIR': _pathInSandbox(configPath),
+      'PUB_CACHE': _pathInSandbox(cachePath),
+      'PUB_ENVIRONMENT': 'test-environment',
 
-    // Ensure a known SDK version is set for the tests that rely on that.
-    '_PUB_TEST_SDK_VERSION': testVersion
-  };
-
-  if (tokenEndpoint != null) {
-    environment['_PUB_TEST_TOKEN_ENDPOINT'] = tokenEndpoint;
-  }
-
-  if (globalServer != null) {
-    environment['PUB_HOSTED_URL'] = 'http://localhost:${globalServer.port}';
-  }
-
-  return environment;
-}
+      // Ensure a known SDK version is set for the tests that rely on that.
+      '_PUB_TEST_SDK_VERSION': testVersion,
+      if (tokenEndpoint != null) '_PUB_TEST_TOKEN_ENDPOINT': tokenEndpoint,
+      if (_globalServer?.port != null)
+        'PUB_HOSTED_URL': 'http://localhost:${_globalServer?.port}'
+    };
 
 /// The path to the root of pub's sources in the pub repo.
 final String _pubRoot = (() {
@@ -456,10 +442,10 @@
 /// If [environment] is given, any keys in it will override the environment
 /// variables passed to the spawned process.
 Future<PubProcess> startPub(
-    {Iterable<String> args,
-    String tokenEndpoint,
-    String workingDirectory,
-    Map<String, String> environment,
+    {Iterable<String>? args,
+    String? tokenEndpoint,
+    String? workingDirectory,
+    Map<String, String?>? environment,
     bool verbose = true,
     includeParentEnvironment = true}) async {
   args ??= [];
@@ -485,10 +471,11 @@
 
   final mergedEnvironment = getPubTestEnvironment(tokenEndpoint);
   for (final e in (environment ?? {}).entries) {
-    if (e.value == null) {
+    var value = e.value;
+    if (value == null) {
       mergedEnvironment.remove(e.key);
     } else {
-      mergedEnvironment[e.key] = e.value;
+      mergedEnvironment[e.key] = value;
     }
   }
 
@@ -503,23 +490,23 @@
 /// makes [stdout] and [stderr] work as though pub weren't running in verbose
 /// mode.
 class PubProcess extends TestProcess {
-  StreamSplitter<Pair<log.Level, String>> get _logSplitter {
-    __logSplitter ??= StreamSplitter(StreamGroup.merge([
-      _outputToLog(super.stdoutStream(), log.Level.MESSAGE),
-      _outputToLog(super.stderrStream(), log.Level.ERROR)
+  late final StreamSplitter<Pair<log.Level, String>> _logSplitter =
+      createLogSplitter();
+
+  StreamSplitter<Pair<log.Level, String>> createLogSplitter() {
+    return StreamSplitter(StreamGroup.merge([
+      _outputToLog(super.stdoutStream(), log.Level.message),
+      _outputToLog(super.stderrStream(), log.Level.error)
     ]));
-    return __logSplitter;
   }
 
-  StreamSplitter<Pair<log.Level, String>> __logSplitter;
-
   static Future<PubProcess> start(String executable, Iterable<String> arguments,
-      {String workingDirectory,
-      Map<String, String> environment,
+      {String? workingDirectory,
+      Map<String, String>? environment,
       bool includeParentEnvironment = true,
       bool runInShell = false,
-      String description,
-      Encoding encoding,
+      String? description,
+      Encoding encoding = utf8,
       bool forwardStdio = false}) async {
     var process = await Process.start(executable, arguments.toList(),
         workingDirectory: workingDirectory,
@@ -534,25 +521,24 @@
       description = '$humanExecutable ${arguments.join(' ')}';
     }
 
-    encoding ??= utf8;
     return PubProcess(process, description,
         encoding: encoding, forwardStdio: forwardStdio);
   }
 
   /// This is protected.
   PubProcess(process, description,
-      {Encoding encoding, bool forwardStdio = false})
+      {Encoding encoding = utf8, bool forwardStdio = false})
       : super(process, description,
             encoding: encoding, forwardStdio: forwardStdio);
 
   final _logLineRegExp = RegExp(r'^([A-Z ]{4})[:|] (.*)$');
   final Map<String, log.Level> _logLevels = [
-    log.Level.ERROR,
-    log.Level.WARNING,
-    log.Level.MESSAGE,
-    log.Level.IO,
-    log.Level.SOLVER,
-    log.Level.FINE
+    log.Level.error,
+    log.Level.warning,
+    log.Level.message,
+    log.Level.io,
+    log.Level.solver,
+    log.Level.fine
   ].fold({}, (levels, level) {
     levels[level.name] = level;
     return levels;
@@ -560,21 +546,21 @@
 
   Stream<Pair<log.Level, String>> _outputToLog(
       Stream<String> stream, log.Level defaultLevel) {
-    log.Level lastLevel;
+    late log.Level lastLevel;
     return stream.map((line) {
       var match = _logLineRegExp.firstMatch(line);
       if (match == null) return Pair<log.Level, String>(defaultLevel, line);
 
       var level = _logLevels[match[1]] ?? lastLevel;
       lastLevel = level;
-      return Pair<log.Level, String>(level, match[2]);
+      return Pair<log.Level, String>(level, match[2]!);
     });
   }
 
   @override
   Stream<String> stdoutStream() {
     return _logSplitter.split().expand((entry) {
-      if (entry.first != log.Level.MESSAGE) return [];
+      if (entry.first != log.Level.message) return [];
       return [entry.last];
     });
   }
@@ -582,7 +568,7 @@
   @override
   Stream<String> stderrStream() {
     return _logSplitter.split().expand((entry) {
-      if (entry.first != log.Level.ERROR && entry.first != log.Level.WARNING) {
+      if (entry.first != log.Level.error && entry.first != log.Level.warning) {
         return [];
       }
       return [entry.last];
@@ -592,9 +578,9 @@
   /// A stream of log messages that are silent by default.
   Stream<String> silentStream() {
     return _logSplitter.split().expand((entry) {
-      if (entry.first == log.Level.MESSAGE) return [];
-      if (entry.first == log.Level.ERROR) return [];
-      if (entry.first == log.Level.WARNING) return [];
+      if (entry.first == log.Level.message) return [];
+      if (entry.first == log.Level.error) return [];
+      if (entry.first == log.Level.warning) return [];
       return [entry.last];
     });
   }
@@ -617,15 +603,15 @@
 /// [hosted] is a list of package names to version strings for dependencies on
 /// hosted packages.
 Future<void> createLockFile(String package,
-    {Iterable<String> dependenciesInSandBox,
-    Map<String, String> hosted}) async {
+    {Iterable<String>? dependenciesInSandBox,
+    Map<String, String>? hosted}) async {
   var cache = SystemCache(rootDir: _pathInSandbox(cachePath));
 
   var lockFile = _createLockFile(cache.sources,
       sandbox: dependenciesInSandBox, hosted: hosted);
 
   await d.dir(package, [
-    d.file('pubspec.lock', lockFile.serialize(null)),
+    d.file('pubspec.lock', lockFile.serialize(p.join(d.sandbox, package))),
     d.file(
       '.packages',
       lockFile.packagesFile(
@@ -640,8 +626,8 @@
 /// Like [createLockFile], but creates only a `.packages` file without a
 /// lockfile.
 Future<void> createPackagesFile(String package,
-    {Iterable<String> dependenciesInSandBox,
-    Map<String, String> hosted}) async {
+    {Iterable<String>? dependenciesInSandBox,
+    Map<String, String>? hosted}) async {
   var cache = SystemCache(rootDir: _pathInSandbox(cachePath));
   var lockFile = _createLockFile(cache.sources,
       sandbox: dependenciesInSandBox, hosted: hosted);
@@ -666,7 +652,7 @@
 /// [hosted] is a list of package names to version strings for dependencies on
 /// hosted packages.
 LockFile _createLockFile(SourceRegistry sources,
-    {Iterable<String> sandbox, Map<String, String> hosted}) {
+    {Iterable<String>? sandbox, Map<String, String>? hosted}) {
   var dependencies = {};
 
   if (sandbox != null) {
@@ -677,7 +663,9 @@
 
   var packages = dependencies.keys.map((name) {
     var dependencyPath = dependencies[name];
-    return sources.path.idFor(name, Version(0, 0, 0), dependencyPath);
+    return sources.path.parseId(
+        name, Version(0, 0, 0), {'path': dependencyPath, 'relative': true},
+        containingPath: p.join(d.sandbox, appPath));
   }).toList();
 
   if (hosted != null) {
@@ -704,14 +692,14 @@
 
 /// Describes a map representing a library package with the given [name],
 /// [version], and [dependencies].
-Map packageMap(
+Map<String, Object> packageMap(
   String name,
   String version, [
-  Map dependencies,
-  Map devDependencies,
-  Map environment,
+  Map? dependencies,
+  Map? devDependencies,
+  Map? environment,
 ]) {
-  var package = <String, dynamic>{
+  var package = <String, Object>{
     'name': name,
     'version': version,
     'homepage': 'http://pub.dartlang.org',
@@ -833,7 +821,7 @@
 /// which may be a literal JSON object, or any other [Matcher].
 void _validateOutputJson(
     List<String> failures, String pipe, expected, String actualText) {
-  Map actual;
+  late Map actual;
   try {
     actual = jsonDecode(actualText);
   } on FormatException {
@@ -914,8 +902,9 @@
     line = line
         .replaceAll(d.sandbox, r'$SANDBOX')
         .replaceAll(Platform.pathSeparator, '/');
-    if (globalPackageServer != null) {
-      line = line.replaceAll(globalPackageServer.port.toString(), '\$PORT');
+    var port = _globalServer?.port;
+    if (port != null) {
+      line = line.replaceAll(port.toString(), '\$PORT');
     }
     return line;
   });
@@ -925,8 +914,8 @@
 Future<void> runPubIntoBuffer(
   List<String> args,
   StringBuffer buffer, {
-  Map<String, String> environment,
-  String workingDirectory,
+  Map<String, String>? environment,
+  String? workingDirectory,
 }) async {
   final process = await startPub(
     args: args,
@@ -956,3 +945,28 @@
   }
   buffer.write('\n');
 }
+
+/// The current global [PackageServer].
+PackageServer get globalServer => _globalServer!;
+PackageServer? _globalServer;
+
+/// Creates an HTTP server that replicates the structure of pub.dartlang.org and
+/// makes it the current [globalServer].
+Future<PackageServer> servePackages() async {
+  final server = await startPackageServer();
+  _globalServer = server;
+
+  addTearDown(() {
+    _globalServer = null;
+  });
+  return server;
+}
+
+Future<PackageServer> startPackageServer() async {
+  final server = await PackageServer.start();
+
+  addTearDown(() async {
+    await server.close();
+  });
+  return server;
+}
diff --git a/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401-with-message.txt b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401-with-message.txt
new file mode 100644
index 0000000..8dcaaf5
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401-with-message.txt
@@ -0,0 +1,13 @@
+# GENERATED BY: test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+
+## Section 0
+$ pub get
+Resolving dependencies...
+[STDERR] Because myapp depends on foo any which doesn't exist (authentication failed), version solving failed.
+[STDERR] 
+[STDERR] http://localhost:$PORT package repository requested authentication!
+[STDERR] You can provide credentials using:
+[STDERR]     pub token add http://localhost:$PORT
+[STDERR] <message>
+[EXIT CODE] 69
+
diff --git a/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401.txt b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401.txt
new file mode 100644
index 0000000..68d5bd0
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401.txt
@@ -0,0 +1,12 @@
+# GENERATED BY: test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+
+## Section 0
+$ pub get
+Resolving dependencies...
+[STDERR] Because myapp depends on foo any which doesn't exist (authentication failed), version solving failed.
+[STDERR] 
+[STDERR] http://localhost:$PORT package repository requested authentication!
+[STDERR] You can provide credentials using:
+[STDERR]     pub token add http://localhost:$PORT
+[EXIT CODE] 69
+
diff --git a/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403-with-message.txt b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403-with-message.txt
new file mode 100644
index 0000000..882660c
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403-with-message.txt
@@ -0,0 +1,13 @@
+# GENERATED BY: test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+
+## Section 0
+$ pub get
+Resolving dependencies...
+[STDERR] Because myapp depends on foo any which doesn't exist (authorization failed), version solving failed.
+[STDERR] 
+[STDERR] Insufficient permissions to the resource at the http://localhost:$PORT package repository.
+[STDERR] You can modify credentials using:
+[STDERR]     pub token add http://localhost:$PORT
+[STDERR] <message>
+[EXIT CODE] 69
+
diff --git a/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403.txt b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403.txt
new file mode 100644
index 0000000..f8a5af9
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403.txt
@@ -0,0 +1,12 @@
+# GENERATED BY: test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+
+## Section 0
+$ pub get
+Resolving dependencies...
+[STDERR] Because myapp depends on foo any which doesn't exist (authorization failed), version solving failed.
+[STDERR] 
+[STDERR] Insufficient permissions to the resource at the http://localhost:$PORT package repository.
+[STDERR] You can modify credentials using:
+[STDERR]     pub token add http://localhost:$PORT
+[EXIT CODE] 69
+
diff --git a/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/bad_json.txt b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/bad_json.txt
new file mode 100644
index 0000000..8e446c2
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/bad_json.txt
@@ -0,0 +1,10 @@
+# GENERATED BY: test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+
+## Section 0
+$ pub get
+Resolving dependencies...
+[STDERR] Because myapp depends on foo any which doesn't exist (Got badly formatted response trying to find package foo at http://localhost:$PORT), version solving failed.
+[STDERR] 
+[STDERR] Check that "http://localhost:$PORT" is a valid package repository.
+[EXIT CODE] 65
+
diff --git a/test/testdata/goldens/hosted/fail_gracefully_with_hint_test/supports two hints.txt b/test/testdata/goldens/hosted/fail_gracefully_with_hint_test/supports two hints.txt
new file mode 100644
index 0000000..a45b0f0
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_with_hint_test/supports two hints.txt
@@ -0,0 +1,13 @@
+# GENERATED BY: test/hosted/fail_gracefully_with_hint_test.dart
+
+## Section 0
+$ pub get --offline
+Resolving dependencies...
+[STDERR] Because foo <1.2.4 requires the Flutter SDK and foo >=1.2.4 depends on bar any, every version of foo requires bar any.
+[STDERR] So, because bar doesn't exist (could not find package bar in cache) and myapp depends on foo any, version solving failed.
+[STDERR] 
+[STDERR] Flutter users should run `flutter pub get` instead of `dart pub get`.
+[STDERR] 
+[STDERR] Try again without --offline!
+[EXIT CODE] 69
+
diff --git a/test/token/add_token_test.dart b/test/token/add_token_test.dart
index 5e6b1f7..ca68c41 100644
--- a/test/token/add_token_test.dart
+++ b/test/token/add_token_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/token/error_message_test.dart b/test/token/error_message_test.dart
index c5ebc80..53431a5 100644
--- a/test/token/error_message_test.dart
+++ b/test/token/error_message_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
 
@@ -11,7 +9,7 @@
 import '../test_pub.dart';
 
 void respondWithWwwAuthenticate(String headerValue) {
-  globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+  globalServer.expect('GET', '/api/packages/versions/new', (request) {
     return shelf.Response(403, headers: {'www-authenticate': headerValue});
   });
 }
@@ -20,7 +18,7 @@
   return runPub(
     args: ['lish'],
     environment: {
-      'PUB_HOSTED_URL': globalPackageServer.url,
+      'PUB_HOSTED_URL': globalServer.url,
       '_PUB_TEST_AUTH_METHOD': 'token',
     },
     exitCode: 65,
@@ -36,7 +34,7 @@
     await d.tokensFile({
       'version': 1,
       'hosted': [
-        {'url': globalPackageServer.url, 'token': 'access token'},
+        {'url': globalServer.url, 'token': 'access token'},
       ]
     }).create();
   });
diff --git a/test/token/remove_token_test.dart b/test/token/remove_token_test.dart
index 24fefa2..bfe2428 100644
--- a/test/token/remove_token_test.dart
+++ b/test/token/remove_token_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/token/token_authentication_test.dart b/test/token/token_authentication_test.dart
index 94574c7..c020ac0 100644
--- a/test/token/token_authentication_test.dart
+++ b/test/token/token_authentication_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -18,14 +16,14 @@
     await d.tokensFile({
       'version': 1,
       'hosted': [
-        {'url': globalPackageServer.url, 'env': 'TOKEN'},
+        {'url': globalServer.url, 'env': 'TOKEN'},
       ]
     }).create();
-    var pub = await startPublish(globalPackageServer,
+    var pub = await startPublish(globalServer,
         authMethod: 'token', environment: {'TOKEN': 'access token'});
     await confirmPublish(pub);
 
-    handleUploadForm(globalPackageServer);
+    handleUploadForm(globalServer);
 
     await pub.shouldExit(1);
   });
@@ -35,13 +33,13 @@
     await d.tokensFile({
       'version': 1,
       'hosted': [
-        {'url': globalPackageServer.url, 'token': 'access token'},
+        {'url': globalServer.url, 'token': 'access token'},
       ]
     }).create();
-    var pub = await startPublish(globalPackageServer, authMethod: 'token');
+    var pub = await startPublish(globalServer, authMethod: 'token');
     await confirmPublish(pub);
 
-    handleUploadForm(globalPackageServer);
+    handleUploadForm(globalServer);
 
     await pub.shouldExit(1);
   });
diff --git a/test/token/when_receives_401_removes_token_test.dart b/test/token/when_receives_401_removes_token_test.dart
index cb1f3e4..86c0559 100644
--- a/test/token/when_receives_401_removes_token_test.dart
+++ b/test/token/when_receives_401_removes_token_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
 
@@ -14,17 +12,17 @@
   setUp(d.validPackage.create);
 
   test('when receives 401 response removes saved token', () async {
-    await servePackages();
+    final server = await servePackages();
     await d.tokensFile({
       'version': 1,
       'hosted': [
-        {'url': globalPackageServer.url, 'token': 'access token'},
+        {'url': server.url, 'token': 'access token'},
       ]
     }).create();
-    var pub = await startPublish(globalPackageServer, authMethod: 'token');
+    var pub = await startPublish(server, authMethod: 'token');
     await confirmPublish(pub);
 
-    globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+    server.expect('GET', '/api/packages/versions/new', (request) {
       return shelf.Response(401);
     });
 
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 4035e5f..45fc7a4 100644
--- a/test/token/when_receives_403_persists_saved_token_test.dart
+++ b/test/token/when_receives_403_persists_saved_token_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:test/test.dart';
 
@@ -14,17 +12,17 @@
   setUp(d.validPackage.create);
 
   test('when receives 403 response persists saved token', () async {
-    await servePackages();
+    final server = await servePackages();
     await d.tokensFile({
       'version': 1,
       'hosted': [
-        {'url': globalPackageServer.url, 'token': 'access token'},
+        {'url': server.url, 'token': 'access token'},
       ]
     }).create();
-    var pub = await startPublish(globalPackageServer, authMethod: 'token');
+    var pub = await startPublish(server, authMethod: 'token');
     await confirmPublish(pub);
 
-    globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+    server.expect('GET', '/api/packages/versions/new', (request) {
       return shelf.Response(403);
     });
 
@@ -33,7 +31,7 @@
     await d.tokensFile({
       'version': 1,
       'hosted': [
-        {'url': globalPackageServer.url, 'token': 'access token'},
+        {'url': server.url, 'token': 'access token'},
       ]
     }).validate();
   });
diff --git a/test/unknown_source_test.dart b/test/unknown_source_test.dart
index 241f9c7..fc53621 100644
--- a/test/unknown_source_test.dart
+++ b/test/unknown_source_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:convert';
 
 import 'package:test/test.dart';
diff --git a/test/upgrade/dry_run_does_not_apply_changes_test.dart b/test/upgrade/dry_run_does_not_apply_changes_test.dart
index e77d3b8..8c942ca 100644
--- a/test/upgrade/dry_run_does_not_apply_changes_test.dart
+++ b/test/upgrade/dry_run_does_not_apply_changes_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/io.dart';
 import 'package:test/test.dart';
@@ -13,10 +11,9 @@
 
 void main() {
   test('--dry-run: shows report, changes nothing', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '2.0.0');
 
     // Create the first lockfile.
     await d.appDir({'foo': '1.0.0'}).create();
@@ -52,10 +49,9 @@
   });
 
   test('--dry-run --major-versions: shows report, changes nothing', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '2.0.0');
 
     await d.appDir({'foo': '^1.0.0'}).create();
 
diff --git a/test/upgrade/example_warns_about_major_versions_test.dart b/test/upgrade/example_warns_about_major_versions_test.dart
index 259e787..b5c9a67 100644
--- a/test/upgrade/example_warns_about_major_versions_test.dart
+++ b/test/upgrade/example_warns_about_major_versions_test.dart
@@ -2,8 +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.
 
-// @dart = 2.11
-
 import '../descriptor.dart' as d;
 import '../golden_file.dart';
 import '../test_pub.dart';
@@ -12,11 +10,11 @@
   testWithGolden(
       'pub upgrade --major-versions does not update major versions in example/',
       (ctx) async {
-    await servePackages((b) => b
+    await servePackages()
       ..serve('foo', '1.0.0')
       ..serve('foo', '2.0.0')
       ..serve('bar', '1.0.0')
-      ..serve('bar', '2.0.0'));
+      ..serve('bar', '2.0.0');
     await d.dir(appPath, [
       d.pubspec({
         'name': 'myapp',
@@ -41,7 +39,7 @@
   testWithGolden(
       'pub upgrade --null-safety does not update null-safety of dependencies in example/',
       (ctx) async {
-    await servePackages((b) => b
+    await servePackages()
       ..serve('foo', '1.0.0', pubspec: {
         'environment': {'sdk': '>=2.7.0 <3.0.0'},
       })
@@ -53,7 +51,7 @@
       })
       ..serve('bar', '2.0.0', pubspec: {
         'environment': {'sdk': '>=2.12.0 <3.0.0'},
-      }));
+      });
     await d.dir(appPath, [
       d.pubspec({
         'name': 'myapp',
diff --git a/test/upgrade/git/do_not_upgrade_if_unneeded_test.dart b/test/upgrade/git/do_not_upgrade_if_unneeded_test.dart
index dffb433..5638fb9 100644
--- a/test/upgrade/git/do_not_upgrade_if_unneeded_test.dart
+++ b/test/upgrade/git/do_not_upgrade_if_unneeded_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
 
diff --git a/test/upgrade/git/upgrade_locked_test.dart b/test/upgrade/git/upgrade_locked_test.dart
index 55938de..a8e744f 100644
--- a/test/upgrade/git/upgrade_locked_test.dart
+++ b/test/upgrade/git/upgrade_locked_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/upgrade/git/upgrade_one_locked_test.dart b/test/upgrade/git/upgrade_one_locked_test.dart
index 14fa010..5c41fa6 100644
--- a/test/upgrade/git/upgrade_one_locked_test.dart
+++ b/test/upgrade/git/upgrade_one_locked_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/upgrade/git/upgrade_to_incompatible_pubspec_test.dart b/test/upgrade/git/upgrade_to_incompatible_pubspec_test.dart
index 33f584c..e74a11e 100644
--- a/test/upgrade/git/upgrade_to_incompatible_pubspec_test.dart
+++ b/test/upgrade/git/upgrade_to_incompatible_pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/exit_codes.dart' as exit_codes;
 import 'package:test/test.dart';
 
diff --git a/test/upgrade/git/upgrade_to_nonexistent_pubspec_test.dart b/test/upgrade/git/upgrade_to_nonexistent_pubspec_test.dart
index e1e160f..ae865eb 100644
--- a/test/upgrade/git/upgrade_to_nonexistent_pubspec_test.dart
+++ b/test/upgrade/git/upgrade_to_nonexistent_pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
diff --git a/test/upgrade/hosted/unlock_if_necessary_test.dart b/test/upgrade/hosted/unlock_if_necessary_test.dart
index 9bd78fb..c285e66 100644
--- a/test/upgrade/hosted/unlock_if_necessary_test.dart
+++ b/test/upgrade/hosted/unlock_if_necessary_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -13,10 +11,10 @@
   test(
       "upgrades one locked pub server package's dependencies if it's "
       'necessary', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'foo_dep': 'any'});
-      builder.serve('foo_dep', '1.0.0');
-    });
+    final server = await servePackages();
+
+    server.serve('foo', '1.0.0', deps: {'foo_dep': 'any'});
+    server.serve('foo_dep', '1.0.0');
 
     await d.appDir({'foo': 'any'}).create();
 
@@ -24,10 +22,8 @@
 
     await d.appPackagesFile({'foo': '1.0.0', 'foo_dep': '1.0.0'}).validate();
 
-    globalPackageServer.add((builder) {
-      builder.serve('foo', '2.0.0', deps: {'foo_dep': '>1.0.0'});
-      builder.serve('foo_dep', '2.0.0');
-    });
+    server.serve('foo', '2.0.0', deps: {'foo_dep': '>1.0.0'});
+    server.serve('foo_dep', '2.0.0');
 
     await pubUpgrade(args: ['foo']);
 
diff --git a/test/upgrade/hosted/unlock_single_package_test.dart b/test/upgrade/hosted/unlock_single_package_test.dart
index ba3d80f..bc78a3d 100644
--- a/test/upgrade/hosted/unlock_single_package_test.dart
+++ b/test/upgrade/hosted/unlock_single_package_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,10 +9,10 @@
 
 void main() {
   test('can unlock a single package only in upgrade', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
-      builder.serve('bar', '1.0.0');
-    });
+    final server = await servePackages();
+
+    server.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
+    server.serve('bar', '1.0.0');
 
     await d.appDir({'foo': 'any', 'bar': 'any'}).create();
 
@@ -22,10 +20,8 @@
 
     await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.0.0'}).validate();
 
-    globalPackageServer.add((builder) {
-      builder.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
-      builder.serve('bar', '2.0.0');
-    });
+    server.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
+    server.serve('bar', '2.0.0');
 
     // This can't upgrade 'bar'
     await pubUpgrade(args: ['bar']);
@@ -33,10 +29,8 @@
     await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.0.0'}).validate();
 
     // Introducing foo and bar 1.1.0, to show that only 'bar' will be upgraded
-    globalPackageServer.add((builder) {
-      builder.serve('foo', '1.1.0', deps: {'bar': '<2.0.0'});
-      builder.serve('bar', '1.1.0');
-    });
+    server.serve('foo', '1.1.0', deps: {'bar': '<2.0.0'});
+    server.serve('bar', '1.1.0');
 
     await pubUpgrade(args: ['bar']);
     await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
diff --git a/test/upgrade/hosted/upgrade_removed_constraints_test.dart b/test/upgrade/hosted/upgrade_removed_constraints_test.dart
index bb73ddc..248ac90 100644
--- a/test/upgrade/hosted/upgrade_removed_constraints_test.dart
+++ b/test/upgrade/hosted/upgrade_removed_constraints_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,12 +9,11 @@
 
 void main() {
   test('upgrades dependencies whose constraints have been removed', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'shared_dep': 'any'});
-      builder.serve('bar', '1.0.0', deps: {'shared_dep': '<2.0.0'});
-      builder.serve('shared_dep', '1.0.0');
-      builder.serve('shared_dep', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'shared_dep': 'any'})
+      ..serve('bar', '1.0.0', deps: {'shared_dep': '<2.0.0'})
+      ..serve('shared_dep', '1.0.0')
+      ..serve('shared_dep', '2.0.0');
 
     await d.appDir({'foo': 'any', 'bar': 'any'}).create();
 
diff --git a/test/upgrade/hosted/warn_about_discontinued_test.dart b/test/upgrade/hosted/warn_about_discontinued_test.dart
index 426e14d..ba7fc57 100644
--- a/test/upgrade/hosted/warn_about_discontinued_test.dart
+++ b/test/upgrade/hosted/warn_about_discontinued_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.
 
-// @dart=2.10
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -10,15 +9,15 @@
 
 void main() {
   test('Warns about discontinued dependencies', () async {
-    await servePackages((builder) => builder
+    final server = await servePackages()
       ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
-      ..serve('transitive', '1.0.0'));
+      ..serve('transitive', '1.0.0');
     await d.appDir({'foo': '1.2.3'}).create();
     await pubGet();
 
-    globalPackageServer.add((builder) => builder
+    server
       ..discontinue('foo')
-      ..discontinue('transitive'));
+      ..discontinue('transitive');
     // We warn only about the direct dependency here:
     await pubUpgrade(output: '''
 Resolving dependencies...
@@ -27,8 +26,7 @@
   No dependencies changed.
   1 package is discontinued.
 ''');
-    globalPackageServer
-        .add((builder) => builder.discontinue('foo', replacementText: 'bar'));
+    server.discontinue('foo', replacementText: 'bar');
     // We warn only about the direct dependency here:
     await pubUpgrade(output: '''
 Resolving dependencies...
@@ -40,9 +38,9 @@
   });
 
   test('Warns about discontinued dev_dependencies', () async {
-    await servePackages((builder) => builder
+    final server = await servePackages()
       ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
-      ..serve('transitive', '1.0.0'));
+      ..serve('transitive', '1.0.0');
 
     await d.dir(appPath, [
       d.file('pubspec.yaml', '''
@@ -57,9 +55,9 @@
     ]).create();
     await pubGet();
 
-    globalPackageServer.add((builder) => builder
+    server
       ..discontinue('foo')
-      ..discontinue('transitive'));
+      ..discontinue('transitive');
 
     // We warn only about the direct dependency here:
     await pubUpgrade(output: '''
@@ -69,8 +67,7 @@
   No dependencies changed.
   1 package is discontinued.
 ''');
-    globalPackageServer
-        .add((builder) => builder.discontinue('foo', replacementText: 'bar'));
+    server.discontinue('foo', replacementText: 'bar');
     // We warn only about the direct dependency here:
     await pubUpgrade(output: '''
 Resolving dependencies...
diff --git a/test/upgrade/renamed_package_circular_dependency.dart b/test/upgrade/renamed_package_circular_dependency.dart
index 84ce151..ec10b82 100644
--- a/test/upgrade/renamed_package_circular_dependency.dart
+++ b/test/upgrade/renamed_package_circular_dependency.dart
@@ -2,18 +2,15 @@
 // 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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
 void main() {
   test('The upgrade report handles a package becoming root', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'myapp': 'any'});
-      builder.serve('myapp', '1.0.0', deps: {'foo': 'any'});
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'myapp': 'any'})
+      ..serve('myapp', '1.0.0', deps: {'foo': 'any'});
 
     await d.dir(appPath, [
       d.pubspec({
diff --git a/test/upgrade/report/describes_change_test.dart b/test/upgrade/report/describes_change_test.dart
index 382deb0..96410cb 100644
--- a/test/upgrade/report/describes_change_test.dart
+++ b/test/upgrade/report/describes_change_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,11 +9,11 @@
 
 void main() {
   test('Shows count of discontinued packages', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '2.0.0');
-    });
+    final server = await servePackages();
 
-    globalPackageServer.add((builder) => builder..discontinue('foo'));
+    server.serve('foo', '2.0.0');
+
+    server.discontinue('foo');
 
     // Create the first lockfile.
     await d.appDir({'foo': '2.0.0'}).create();
@@ -35,12 +33,11 @@
   });
 
   test('shows how package changed from previous lockfile', () async {
-    await servePackages((builder) {
-      builder.serve('unchanged', '1.0.0');
-      builder.serve('version_changed', '1.0.0');
-      builder.serve('version_changed', '2.0.0');
-      builder.serve('source_changed', '1.0.0');
-    });
+    await servePackages()
+      ..serve('unchanged', '1.0.0')
+      ..serve('version_changed', '1.0.0')
+      ..serve('version_changed', '2.0.0')
+      ..serve('source_changed', '1.0.0');
 
     await d.dir('source_changed', [
       d.libDir('source_changed'),
diff --git a/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart b/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
index 41f90d0..ef987b9 100644
--- a/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
+++ b/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -13,14 +11,13 @@
   test(
       'Shows newer versions available for packages that are locked and not being upgraded',
       () async {
-    await servePackages((builder) {
-      builder.serve('not_upgraded', '1.0.0');
-      builder.serve('not_upgraded', '2.0.0');
-      builder.serve('not_upgraded', '3.0.0-dev');
-      builder.serve('upgraded', '1.0.0');
-      builder.serve('upgraded', '2.0.0');
-      builder.serve('upgraded', '3.0.0-dev');
-    });
+    await servePackages()
+      ..serve('not_upgraded', '1.0.0')
+      ..serve('not_upgraded', '2.0.0')
+      ..serve('not_upgraded', '3.0.0-dev')
+      ..serve('upgraded', '1.0.0')
+      ..serve('upgraded', '2.0.0')
+      ..serve('upgraded', '3.0.0-dev');
 
     // Constraint everything to the first version.
     await d.appDir({'not_upgraded': '1.0.0', 'upgraded': '1.0.0'}).create();
diff --git a/test/upgrade/report/highlights_overrides_test.dart b/test/upgrade/report/highlights_overrides_test.dart
index 04ae0ba..93f9f3b 100644
--- a/test/upgrade/report/highlights_overrides_test.dart
+++ b/test/upgrade/report/highlights_overrides_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,7 +9,8 @@
 
 void main() {
   test('highlights overridden packages', () async {
-    await servePackages((builder) => builder.serve('overridden', '1.0.0'));
+    final server = await servePackages();
+    server.serve('overridden', '1.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
diff --git a/test/upgrade/report/leading_character_shows_change_test.dart b/test/upgrade/report/leading_character_shows_change_test.dart
index e7438d8..88f7ed2 100644
--- a/test/upgrade/report/leading_character_shows_change_test.dart
+++ b/test/upgrade/report/leading_character_shows_change_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,17 +9,16 @@
 
 void main() {
   test('the character before each package describes the change', () async {
-    await servePackages((builder) {
-      builder.serve('added', '1.0.0');
-      builder.serve('downgraded', '1.0.0');
-      builder.serve('downgraded', '2.0.0');
-      builder.serve('overridden', '1.0.0');
-      builder.serve('removed', '1.0.0');
-      builder.serve('source_changed', '1.0.0');
-      builder.serve('upgraded', '1.0.0');
-      builder.serve('upgraded', '2.0.0');
-      builder.serve('unchanged', '1.0.0');
-    });
+    await servePackages()
+      ..serve('added', '1.0.0')
+      ..serve('downgraded', '1.0.0')
+      ..serve('downgraded', '2.0.0')
+      ..serve('overridden', '1.0.0')
+      ..serve('removed', '1.0.0')
+      ..serve('source_changed', '1.0.0')
+      ..serve('upgraded', '1.0.0')
+      ..serve('upgraded', '2.0.0')
+      ..serve('unchanged', '1.0.0');
 
     await d.dir('description_changed_1', [
       d.libDir('description_changed'),
diff --git a/test/upgrade/report/shows_newer_available_versions_test.dart b/test/upgrade/report/shows_newer_available_versions_test.dart
index 54c32ad..39d4e1a 100644
--- a/test/upgrade/report/shows_newer_available_versions_test.dart
+++ b/test/upgrade/report/shows_newer_available_versions_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,28 +9,26 @@
 
 void main() {
   test('shows how many newer versions are available', () async {
-    await servePackages((builder) {
-      builder.serve('multiple_newer', '1.0.0');
-      builder.serve('multiple_newer', '1.0.1-unstable.1');
-      builder.serve('multiple_newer', '1.0.1');
-      builder.serve('multiple_newer', '1.0.2-unstable.1');
-      builder.serve('multiple_newer_stable', '1.0.0');
-      builder.serve('multiple_newer_stable', '1.0.1');
-      builder.serve('multiple_newer_stable', '1.0.2');
-      builder.serve('multiple_newer_unstable', '1.0.0');
-      builder.serve('multiple_newer_unstable', '1.0.1-unstable.1');
-      builder.serve('multiple_newer_unstable', '1.0.1-unstable.2');
-      builder.serve('multiple_newer_unstable2', '1.0.1-unstable.1');
-      builder.serve('multiple_newer_unstable2', '1.0.1-unstable.2');
-      builder.serve('multiple_newer_unstable2', '1.0.1-unstable.2');
-      builder.serve('no_newer', '1.0.0');
-      builder.serve('one_newer_unstable', '1.0.0');
-      builder.serve('one_newer_unstable', '1.0.1-unstable.1');
-      builder.serve('one_newer_unstable2', '1.0.1-unstable.1');
-      builder.serve('one_newer_unstable2', '1.0.1-unstable.2');
-      builder.serve('one_newer_stable', '1.0.0');
-      builder.serve('one_newer_stable', '1.0.1');
-    });
+    await servePackages()
+      ..serve('multiple_newer', '1.0.0')
+      ..serve('multiple_newer', '1.0.1-unstable.1')
+      ..serve('multiple_newer', '1.0.1')
+      ..serve('multiple_newer', '1.0.2-unstable.1')
+      ..serve('multiple_newer_stable', '1.0.0')
+      ..serve('multiple_newer_stable', '1.0.1')
+      ..serve('multiple_newer_stable', '1.0.2')
+      ..serve('multiple_newer_unstable', '1.0.0')
+      ..serve('multiple_newer_unstable', '1.0.1-unstable.1')
+      ..serve('multiple_newer_unstable', '1.0.1-unstable.2')
+      ..serve('multiple_newer_unstable2', '1.0.1-unstable.1')
+      ..serve('multiple_newer_unstable2', '1.0.1-unstable.2')
+      ..serve('no_newer', '1.0.0')
+      ..serve('one_newer_unstable', '1.0.0')
+      ..serve('one_newer_unstable', '1.0.1-unstable.1')
+      ..serve('one_newer_unstable2', '1.0.1-unstable.1')
+      ..serve('one_newer_unstable2', '1.0.1-unstable.2')
+      ..serve('one_newer_stable', '1.0.0')
+      ..serve('one_newer_stable', '1.0.1');
 
     // Constraint everything to the first version.
     await d.appDir({
diff --git a/test/upgrade/report/shows_number_of_changed_dependencies_test.dart b/test/upgrade/report/shows_number_of_changed_dependencies_test.dart
index 1c79302..91ba5aa 100644
--- a/test/upgrade/report/shows_number_of_changed_dependencies_test.dart
+++ b/test/upgrade/report/shows_number_of_changed_dependencies_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -13,11 +11,10 @@
   test(
       'does not show how many newer versions are available for '
       'packages that are locked and not being upgraded', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('b', '1.0.0');
-      builder.serve('c', '2.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('b', '1.0.0')
+      ..serve('c', '2.0.0');
 
     await d.appDir({'a': 'any'}).create();
 
diff --git a/test/upgrade/report/shows_pub_outdated_test.dart b/test/upgrade/report/shows_pub_outdated_test.dart
index 11d50da..0fdb322 100644
--- a/test/upgrade/report/shows_pub_outdated_test.dart
+++ b/test/upgrade/report/shows_pub_outdated_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../../descriptor.dart' as d;
@@ -11,24 +9,23 @@
 
 void main() {
   test('shows pub outdated', () async {
-    await servePackages((builder) {
-      builder.serve('multiple_newer', '1.0.0');
-      builder.serve('multiple_newer', '1.0.1-unstable.1');
-      builder.serve('multiple_newer', '1.0.1');
-      builder.serve('multiple_newer', '1.0.2-unstable.1');
-      builder.serve('multiple_newer', '1.0.2-unstable.2');
-      builder.serve('multiple_newer_stable', '1.0.0');
-      builder.serve('multiple_newer_stable', '1.0.1');
-      builder.serve('multiple_newer_stable', '1.0.2');
-      builder.serve('multiple_newer_unstable', '1.0.0');
-      builder.serve('multiple_newer_unstable', '1.0.1-unstable.1');
-      builder.serve('multiple_newer_unstable', '1.0.1-unstable.2');
-      builder.serve('no_newer', '1.0.0');
-      builder.serve('one_newer_unstable', '1.0.0');
-      builder.serve('one_newer_unstable', '1.0.1-unstable.1');
-      builder.serve('one_newer_stable', '1.0.0');
-      builder.serve('one_newer_stable', '1.0.1');
-    });
+    await servePackages()
+      ..serve('multiple_newer', '1.0.0')
+      ..serve('multiple_newer', '1.0.1-unstable.1')
+      ..serve('multiple_newer', '1.0.1')
+      ..serve('multiple_newer', '1.0.2-unstable.1')
+      ..serve('multiple_newer', '1.0.2-unstable.2')
+      ..serve('multiple_newer_stable', '1.0.0')
+      ..serve('multiple_newer_stable', '1.0.1')
+      ..serve('multiple_newer_stable', '1.0.2')
+      ..serve('multiple_newer_unstable', '1.0.0')
+      ..serve('multiple_newer_unstable', '1.0.1-unstable.1')
+      ..serve('multiple_newer_unstable', '1.0.1-unstable.2')
+      ..serve('no_newer', '1.0.0')
+      ..serve('one_newer_unstable', '1.0.0')
+      ..serve('one_newer_unstable', '1.0.1-unstable.1')
+      ..serve('one_newer_stable', '1.0.0')
+      ..serve('one_newer_stable', '1.0.1');
 
     // Constraint everything to the first version.
     await d.appDir({
diff --git a/test/upgrade/upgrade_major_versions_test.dart b/test/upgrade/upgrade_major_versions_test.dart
index 7ab389b..8c3f40a 100644
--- a/test/upgrade/upgrade_major_versions_test.dart
+++ b/test/upgrade/upgrade_major_versions_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -12,14 +10,13 @@
 void main() {
   group('pub upgrade --major-versions', () {
     test('bumps dependency constraints and shows summary report', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-        builder.serve('foo', '2.0.0');
-        builder.serve('bar', '0.1.0');
-        builder.serve('bar', '0.2.0');
-        builder.serve('baz', '1.0.0');
-        builder.serve('baz', '1.0.1');
-      });
+      await servePackages()
+        ..serve('foo', '1.0.0')
+        ..serve('foo', '2.0.0')
+        ..serve('bar', '0.1.0')
+        ..serve('bar', '0.2.0')
+        ..serve('baz', '1.0.0')
+        ..serve('baz', '1.0.1');
 
       await d.appDir({
         'foo': '^1.0.0',
@@ -53,14 +50,13 @@
     });
 
     test('bumps dev_dependency constraints and shows summary report', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-        builder.serve('foo', '2.0.0');
-        builder.serve('bar', '0.1.0');
-        builder.serve('bar', '0.2.0');
-        builder.serve('baz', '1.0.0');
-        builder.serve('baz', '1.0.1');
-      });
+      await servePackages()
+        ..serve('foo', '1.0.0')
+        ..serve('foo', '2.0.0')
+        ..serve('bar', '0.1.0')
+        ..serve('bar', '0.2.0')
+        ..serve('baz', '1.0.0')
+        ..serve('baz', '1.0.1');
 
       await d.dir(appPath, [
         d.pubspec({
@@ -104,12 +100,11 @@
     });
 
     test('upgrades only the selected package', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-        builder.serve('foo', '2.0.0');
-        builder.serve('bar', '0.1.0');
-        builder.serve('bar', '0.2.0');
-      });
+      await servePackages()
+        ..serve('foo', '1.0.0')
+        ..serve('foo', '2.0.0')
+        ..serve('bar', '0.1.0')
+        ..serve('bar', '0.2.0');
 
       await d.appDir({
         'foo': '^1.0.0',
@@ -136,11 +131,10 @@
     });
 
     test('chooses the latest version where possible', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-        builder.serve('foo', '2.0.0');
-        builder.serve('foo', '3.0.0');
-      });
+      await servePackages()
+        ..serve('foo', '1.0.0')
+        ..serve('foo', '2.0.0')
+        ..serve('foo', '3.0.0');
 
       await d.appDir({'foo': '^1.0.0'}).create();
 
@@ -168,13 +162,11 @@
     });
 
     test('overridden dependencies - no resolution', () async {
-      await servePackages(
-        (builder) => builder
-          ..serve('foo', '1.0.0', deps: {'bar': '^2.0.0'})
-          ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
-          ..serve('bar', '1.0.0', deps: {'foo': '^1.0.0'})
-          ..serve('bar', '2.0.0', deps: {'foo': '^2.0.0'}),
-      );
+      await servePackages()
+        ..serve('foo', '1.0.0', deps: {'bar': '^2.0.0'})
+        ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
+        ..serve('bar', '1.0.0', deps: {'foo': '^1.0.0'})
+        ..serve('bar', '2.0.0', deps: {'foo': '^2.0.0'});
 
       await d.dir(appPath, [
         d.pubspec({
@@ -225,16 +217,15 @@
       /// The version solver solves the packages with the least number of
       /// versions remaining, so we add more 'bar' packages to force 'foo' to be
       /// resolved first
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-        builder.serve('foo', '2.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0')
+        ..serve('foo', '2.0.0', pubspec: {
           'dependencies': {'bar': '1.0.0'}
-        });
-        builder.serve('bar', '1.0.0');
-        builder.serve('bar', '2.0.0');
-        builder.serve('bar', '3.0.0');
-        builder.serve('bar', '4.0.0');
-      });
+        })
+        ..serve('bar', '1.0.0')
+        ..serve('bar', '2.0.0')
+        ..serve('bar', '3.0.0')
+        ..serve('bar', '4.0.0');
 
       await d.appDir({
         'foo': '^1.0.0',
diff --git a/test/upgrade/upgrade_null_safety_test.dart b/test/upgrade/upgrade_null_safety_test.dart
index 9c7dad0..557c589 100644
--- a/test/upgrade/upgrade_null_safety_test.dart
+++ b/test/upgrade/upgrade_null_safety_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
@@ -11,29 +9,28 @@
 void main() {
   group('pub upgrade --null-safety', () {
     setUp(() async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0', pubspec: {
           'environment': {'sdk': '>=2.10.0<3.0.0'},
-        });
-        builder.serve('foo', '2.0.0', pubspec: {
+        })
+        ..serve('foo', '2.0.0', pubspec: {
           'environment': {'sdk': '>=2.12.0<3.0.0'},
-        });
-        builder.serve('bar', '1.0.0', pubspec: {
+        })
+        ..serve('bar', '1.0.0', pubspec: {
           'environment': {'sdk': '>=2.9.0<3.0.0'},
-        });
-        builder.serve('bar', '2.0.0-nullsafety.0', pubspec: {
+        })
+        ..serve('bar', '2.0.0-nullsafety.0', pubspec: {
           'environment': {'sdk': '>=2.12.0<3.0.0'},
-        });
-        builder.serve('baz', '1.0.0', pubspec: {
+        })
+        ..serve('baz', '1.0.0', pubspec: {
           'environment': {'sdk': '>=2.9.0<3.0.0'},
-        });
-        builder.serve('has_conflict', '1.0.0', pubspec: {
+        })
+        ..serve('has_conflict', '1.0.0', pubspec: {
           'environment': {'sdk': '>=2.9.0<3.0.0'},
-        });
-        builder.serve('has_conflict', '2.0.0', pubspec: {
+        })
+        ..serve('has_conflict', '2.0.0', pubspec: {
           'environment': {'sdk': '>=2.13.0<3.0.0'},
         });
-      });
     });
 
     test('upgrades to null-safety versions', () async {
diff --git a/test/validator/changelog_test.dart b/test/validator/changelog_test.dart
index be166c3..5bef662 100644
--- a/test/validator/changelog_test.dart
+++ b/test/validator/changelog_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/changelog.dart';
diff --git a/test/validator/compiled_dartdoc_test.dart b/test/validator/compiled_dartdoc_test.dart
index a656958..f1d3d6d 100644
--- a/test/validator/compiled_dartdoc_test.dart
+++ b/test/validator/compiled_dartdoc_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/compiled_dartdoc.dart';
diff --git a/test/validator/dependency_override_test.dart b/test/validator/dependency_override_test.dart
index f459119..21a437d 100644
--- a/test/validator/dependency_override_test.dart
+++ b/test/validator/dependency_override_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/dependency_override.dart';
diff --git a/test/validator/dependency_test.dart b/test/validator/dependency_test.dart
index 00ab0c3..db9db15 100644
--- a/test/validator/dependency_test.dart
+++ b/test/validator/dependency_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async';
 import 'dart:convert';
 
@@ -29,7 +27,7 @@
 
 /// Sets up a test package with dependency [dep] and mocks a server with
 /// [hostedVersions] of the package available.
-Future setUpDependency(Map dep, {List<String> hostedVersions}) {
+Future setUpDependency(Map dep, {List<String>? hostedVersions}) {
   useMockClient(MockClient((request) {
     expect(request.method, equals('GET'));
     expect(request.url.path, equals('/api/packages/foo'));
diff --git a/test/validator/deprecated_fields_test.dart b/test/validator/deprecated_fields_test.dart
index a13774b..ee4551d 100644
--- a/test/validator/deprecated_fields_test.dart
+++ b/test/validator/deprecated_fields_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/deprecated_fields.dart';
diff --git a/test/validator/directory_test.dart b/test/validator/directory_test.dart
index 5a5ec99..7cc53b6 100644
--- a/test/validator/directory_test.dart
+++ b/test/validator/directory_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/directory.dart';
diff --git a/test/validator/executable_test.dart b/test/validator/executable_test.dart
index 555f768..d9973e7 100644
--- a/test/validator/executable_test.dart
+++ b/test/validator/executable_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/executable.dart';
diff --git a/test/validator/flutter_constraint_test.dart b/test/validator/flutter_constraint_test.dart
index 685c59d..b7bdf7c 100644
--- a/test/validator/flutter_constraint_test.dart
+++ b/test/validator/flutter_constraint_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -20,7 +18,7 @@
 }
 
 Future<void> setup({
-  String flutterConstraint,
+  String? flutterConstraint,
 }) async {
   final fakeFlutterRoot =
       d.dir('fake_flutter_root', [d.file('version', '1.23.0')]);
diff --git a/test/validator/flutter_plugin_format_test.dart b/test/validator/flutter_plugin_format_test.dart
index cddeaf9..0c24bda 100644
--- a/test/validator/flutter_plugin_format_test.dart
+++ b/test/validator/flutter_plugin_format_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/flutter_plugin_format.dart';
diff --git a/test/validator/gitignore_test.dart b/test/validator/gitignore_test.dart
index 06d3be4..f7b02fe 100644
--- a/test/validator/gitignore_test.dart
+++ b/test/validator/gitignore_test.dart
@@ -2,7 +2,7 @@
 // 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.
 
-// @dart=2.10
+import 'dart:io';
 
 import 'package:path/path.dart' as p;
 import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -14,7 +14,7 @@
 Future<void> expectValidation(
   error,
   int exitCode, {
-  String workingDirectory,
+  String? workingDirectory,
 }) async {
   await runPub(
     error: error,
@@ -84,4 +84,22 @@
         exit_codes.DATA,
         workingDirectory: packageRoot);
   });
+
+  test('Should not follow symlinks', () async {
+    await d.git('myapp', [
+      ...d.validPackage.contents,
+    ]).create();
+    final packageRoot = p.join(d.sandbox, 'myapp');
+    await pubGet(
+        environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'},
+        workingDirectory: packageRoot);
+
+    Link(p.join(packageRoot, '.abc', 'itself')).createSync(
+      packageRoot,
+      recursive: true,
+    );
+
+    await expectValidation(contains('Package has 0 warnings.'), 0,
+        workingDirectory: packageRoot);
+  });
 }
diff --git a/test/validator/language_version_test.dart b/test/validator/language_version_test.dart
index 37431d4..39c9465 100644
--- a/test/validator/language_version_test.dart
+++ b/test/validator/language_version_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/language_version.dart';
@@ -17,7 +15,7 @@
     LanguageVersionValidator(entrypoint);
 
 Future<void> setup(
-    {String sdkConstraint, String libraryLanguageVersion}) async {
+    {required String sdkConstraint, String? libraryLanguageVersion}) async {
   await d.validPackage.create();
   await d.dir(appPath, [
     d.pubspec({
diff --git a/test/validator/leak_detection_test.dart b/test/validator/leak_detection_test.dart
index ee7d5d3..c055e59 100644
--- a/test/validator/leak_detection_test.dart
+++ b/test/validator/leak_detection_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/leak_detection.dart';
diff --git a/test/validator/license_test.dart b/test/validator/license_test.dart
index 77225b5..8717c75 100644
--- a/test/validator/license_test.dart
+++ b/test/validator/license_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/io.dart';
diff --git a/test/validator/name_test.dart b/test/validator/name_test.dart
index 5639c09..7cbb51c 100644
--- a/test/validator/name_test.dart
+++ b/test/validator/name_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/io.dart';
diff --git a/test/validator/null_safety_mixed_mode_test.dart b/test/validator/null_safety_mixed_mode_test.dart
index 6ec4746..d62d051 100644
--- a/test/validator/null_safety_mixed_mode_test.dart
+++ b/test/validator/null_safety_mixed_mode_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -20,7 +18,7 @@
 }
 
 Future<void> setup({
-  String sdkConstraint,
+  required String sdkConstraint,
   Map dependencies = const {},
   Map devDependencies = const {},
   List<d.Descriptor> extraFiles = const [],
@@ -47,14 +45,13 @@
   group('should consider a package valid if it', () {
     test('is not opting in to null-safety, but depends on package that is',
         () async {
-      await servePackages(
-        (server) => server.serve(
-          'foo',
-          '0.0.1',
-          pubspec: {
-            'environment': {'sdk': '>=2.12.0<3.0.0'}
-          },
-        ),
+      final server = await servePackages();
+      server.serve(
+        'foo',
+        '0.0.1',
+        pubspec: {
+          'environment': {'sdk': '>=2.12.0<3.0.0'}
+        },
       );
 
       await setup(
@@ -63,14 +60,13 @@
     });
     test('is opting in to null-safety and depends on package that is',
         () async {
-      await servePackages(
-        (server) => server.serve(
-          'foo',
-          '0.0.1',
-          pubspec: {
-            'environment': {'sdk': '>=2.12.0<3.0.0'}
-          },
-        ),
+      final server = await servePackages();
+      server.serve(
+        'foo',
+        '0.0.1',
+        pubspec: {
+          'environment': {'sdk': '>=2.12.0<3.0.0'}
+        },
       );
 
       await setup(
@@ -80,14 +76,13 @@
 
     test('is opting in to null-safety has dev_dependency that is not',
         () async {
-      await servePackages(
-        (server) => server.serve(
-          'foo',
-          '0.0.1',
-          pubspec: {
-            'environment': {'sdk': '>=2.9.0<3.0.0'}
-          },
-        ),
+      final server = await servePackages();
+      server.serve(
+        'foo',
+        '0.0.1',
+        pubspec: {
+          'environment': {'sdk': '>=2.9.0<3.0.0'}
+        },
       );
 
       await setup(sdkConstraint: '>=2.12.0 <3.0.0', devDependencies: {
@@ -100,14 +95,13 @@
   group('should consider a package invalid if it', () {
     test('is opting in to null-safety, but depends on package that is not',
         () async {
-      await servePackages(
-        (server) => server.serve(
-          'foo',
-          '0.0.1',
-          pubspec: {
-            'environment': {'sdk': '>=2.9.0<3.0.0'}
-          },
-        ),
+      final server = await servePackages();
+      server.serve(
+        'foo',
+        '0.0.1',
+        pubspec: {
+          'environment': {'sdk': '>=2.9.0<3.0.0'}
+        },
       );
 
       await setup(
@@ -136,17 +130,16 @@
     test(
         'is opting in to null-safety, but depends on package has file opting out',
         () async {
-      await servePackages(
-        (server) => server.serve('foo', '0.0.1', pubspec: {
-          'environment': {'sdk': '>=2.12.0<3.0.0'}
-        }, contents: [
-          d.dir('lib', [
-            d.file('foo.dart', '''
+      final server = await servePackages();
+      server.serve('foo', '0.0.1', pubspec: {
+        'environment': {'sdk': '>=2.12.0<3.0.0'}
+      }, contents: [
+        d.dir('lib', [
+          d.file('foo.dart', '''
 // @dart = 2.9
           ''')
-          ])
-        ]),
-      );
+        ])
+      ]);
 
       await setup(
           sdkConstraint: '>=2.12.0 <3.0.0', dependencies: {'foo': '^0.0.1'});
diff --git a/test/validator/pubspec_field_test.dart b/test/validator/pubspec_field_test.dart
index 7d4dbd7..8e6fefc 100644
--- a/test/validator/pubspec_field_test.dart
+++ b/test/validator/pubspec_field_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/pubspec_field.dart';
@@ -57,7 +55,7 @@
 
     test('has executables', () async {
       var pkg = packageMap('test_pkg', '1.0.0');
-      pkg['executables'] = <String, String>{
+      pkg['executables'] = <String, String?>{
         'test_pkg': null,
         'test_pkg_helper': 'helper',
       };
diff --git a/test/validator/pubspec_test.dart b/test/validator/pubspec_test.dart
index 0d964ce..9942220 100644
--- a/test/validator/pubspec_test.dart
+++ b/test/validator/pubspec_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/validator/pubspec.dart';
 import 'package:test/test.dart';
 
diff --git a/test/validator/pubspec_typo_test.dart b/test/validator/pubspec_typo_test.dart
index efc731b..ab2a547 100644
--- a/test/validator/pubspec_typo_test.dart
+++ b/test/validator/pubspec_typo_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/pubspec_typo.dart';
diff --git a/test/validator/readme_test.dart b/test/validator/readme_test.dart
index 132ff6c..6519c6f 100644
--- a/test/validator/readme_test.dart
+++ b/test/validator/readme_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as p;
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/io.dart';
diff --git a/test/validator/relative_version_numbering_test.dart b/test/validator/relative_version_numbering_test.dart
index 0a9a1f7..2f3da5c 100644
--- a/test/validator/relative_version_numbering_test.dart
+++ b/test/validator/relative_version_numbering_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/relative_version_numbering.dart';
@@ -15,10 +13,10 @@
 
 Validator validator(Entrypoint entrypoint) => RelativeVersionNumberingValidator(
       entrypoint,
-      Uri.parse(globalPackageServer.url),
+      Uri.parse(globalServer.url),
     );
 
-Future<void> setup({String sdkConstraint}) async {
+Future<void> setup({required String sdkConstraint}) async {
   await d.validPackage.create();
   await d.dir(appPath, [
     d.pubspec({
@@ -35,14 +33,13 @@
   group('should consider a package valid if it', () {
     test('is not opting in to null-safety with previous non-null-safe version',
         () async {
-      await servePackages(
-        (server) => server.serve(
-          'test_pkg',
-          '0.0.1',
-          pubspec: {
-            'environment': {'sdk': '>=2.9.0<3.0.0'}
-          },
-        ),
+      final server = await servePackages();
+      server.serve(
+        'test_pkg',
+        '0.0.1',
+        pubspec: {
+          'environment': {'sdk': '>=2.9.0<3.0.0'}
+        },
       );
 
       await setup(sdkConstraint: '>=2.9.0 <3.0.0');
@@ -52,23 +49,21 @@
     test(
         'is not opting in to null-safety with previous non-null-safe version. '
         'Even with a later null-safe version', () async {
-      await servePackages(
-        (server) => server
-          ..serve(
-            'test_pkg',
-            '0.0.1',
-            pubspec: {
-              'environment': {'sdk': '>=2.9.0<3.0.0'}
-            },
-          )
-          ..serve(
-            'test_pkg',
-            '2.0.0',
-            pubspec: {
-              'environment': {'sdk': '>=2.12.0<3.0.0'}
-            },
-          ),
-      );
+      await servePackages()
+        ..serve(
+          'test_pkg',
+          '0.0.1',
+          pubspec: {
+            'environment': {'sdk': '>=2.9.0<3.0.0'}
+          },
+        )
+        ..serve(
+          'test_pkg',
+          '2.0.0',
+          pubspec: {
+            'environment': {'sdk': '>=2.12.0<3.0.0'}
+          },
+        );
 
       await setup(sdkConstraint: '>=2.9.0 <3.0.0');
       await expectValidation(validator);
@@ -76,14 +71,13 @@
 
     test('is opting in to null-safety with previous null-safe version',
         () async {
-      await servePackages(
-        (server) => server.serve(
-          'test_pkg',
-          '0.0.1',
-          pubspec: {
-            'environment': {'sdk': '>=2.12.0<3.0.0'}
-          },
-        ),
+      final server = await servePackages();
+      server.serve(
+        'test_pkg',
+        '0.0.1',
+        pubspec: {
+          'environment': {'sdk': '>=2.12.0<3.0.0'}
+        },
       );
 
       await setup(sdkConstraint: '>=2.12.0 <3.0.0');
@@ -93,14 +87,13 @@
     test(
         'is opting in to null-safety using a pre-release of 2.12.0 '
         'with previous null-safe version', () async {
-      await servePackages(
-        (server) => server.serve(
-          'test_pkg',
-          '0.0.1',
-          pubspec: {
-            'environment': {'sdk': '>=2.12.0<3.0.0'}
-          },
-        ),
+      final server = await servePackages();
+      server.serve(
+        'test_pkg',
+        '0.0.1',
+        pubspec: {
+          'environment': {'sdk': '>=2.12.0<3.0.0'}
+        },
       );
 
       await setup(sdkConstraint: '>=2.12.0-dev <3.0.0');
@@ -110,23 +103,21 @@
     test(
         'is opting in to null-safety with previous null-safe version. '
         'Even with a later non-null-safe version', () async {
-      await servePackages(
-        (server) => server
-          ..serve(
-            'test_pkg',
-            '0.0.1',
-            pubspec: {
-              'environment': {'sdk': '>=2.12.0<3.0.0'}
-            },
-          )
-          ..serve(
-            'test_pkg',
-            '2.0.1',
-            pubspec: {
-              'environment': {'sdk': '>=2.9.0<3.0.0'}
-            },
-          ),
-      );
+      await servePackages()
+        ..serve(
+          'test_pkg',
+          '0.0.1',
+          pubspec: {
+            'environment': {'sdk': '>=2.12.0<3.0.0'}
+          },
+        )
+        ..serve(
+          'test_pkg',
+          '2.0.1',
+          pubspec: {
+            'environment': {'sdk': '>=2.9.0<3.0.0'}
+          },
+        );
 
       await setup(sdkConstraint: '>=2.12.0 <3.0.0');
       await expectValidation(validator);
@@ -134,13 +125,13 @@
 
     test('is opting in to null-safety with no existing versions', () async {
       await setup(sdkConstraint: '>=2.12.0 <3.0.0');
-      await servePackages((x) => x);
+      await servePackages();
       await expectValidation(validator);
     });
 
     test('is not opting in to null-safety with no existing versions', () async {
       await setup(sdkConstraint: '>=2.9.0 <3.0.0');
-      await servePackages((x) => x);
+      await servePackages();
 
       await expectValidation(validator);
     });
@@ -148,23 +139,21 @@
     test(
         'is not opting in to null-safety with previous null-safe stable version. '
         'With an in-between not null-safe prerelease', () async {
-      await servePackages(
-        (server) => server
-          ..serve(
-            'test_pkg',
-            '0.0.1',
-            pubspec: {
-              'environment': {'sdk': '>=2.12.0<3.0.0'}
-            },
-          )
-          ..serve(
-            'test_pkg',
-            '0.0.2-dev',
-            pubspec: {
-              'environment': {'sdk': '>=2.9.0<3.0.0'}
-            },
-          ),
-      );
+      await servePackages()
+        ..serve(
+          'test_pkg',
+          '0.0.1',
+          pubspec: {
+            'environment': {'sdk': '>=2.12.0<3.0.0'}
+          },
+        )
+        ..serve(
+          'test_pkg',
+          '0.0.2-dev',
+          pubspec: {
+            'environment': {'sdk': '>=2.9.0<3.0.0'}
+          },
+        );
 
       await setup(sdkConstraint: '>=2.9.0 <3.0.0');
       await expectValidation(validator);
@@ -173,23 +162,21 @@
     test(
         'opts in to null-safety, with previous stable version not-null-safe. '
         'With an in-between non-null-safe prerelease', () async {
-      await servePackages(
-        (server) => server
-          ..serve(
-            'test_pkg',
-            '0.0.1',
-            pubspec: {
-              'environment': {'sdk': '>=2.9.0<3.0.0'}
-            },
-          )
-          ..serve(
-            'test_pkg',
-            '0.0.2-dev',
-            pubspec: {
-              'environment': {'sdk': '>=2.12.0<3.0.0'}
-            },
-          ),
-      );
+      await servePackages()
+        ..serve(
+          'test_pkg',
+          '0.0.1',
+          pubspec: {
+            'environment': {'sdk': '>=2.9.0<3.0.0'}
+          },
+        )
+        ..serve(
+          'test_pkg',
+          '0.0.2-dev',
+          pubspec: {
+            'environment': {'sdk': '>=2.12.0<3.0.0'}
+          },
+        );
 
       await setup(sdkConstraint: '>=2.12.0 <3.0.0');
       await expectValidation(validator);
@@ -199,14 +186,13 @@
   group('should warn if ', () {
     test('opts in to null-safety, with previous version not-null-safe',
         () async {
-      await servePackages(
-        (server) => server.serve(
-          'test_pkg',
-          '0.0.1',
-          pubspec: {
-            'environment': {'sdk': '>=2.9.0<3.0.0'}
-          },
-        ),
+      final server = await servePackages();
+      server.serve(
+        'test_pkg',
+        '0.0.1',
+        pubspec: {
+          'environment': {'sdk': '>=2.9.0<3.0.0'}
+        },
       );
 
       await setup(sdkConstraint: '>=2.12.0 <3.0.0');
@@ -217,14 +203,13 @@
         'is not opting in to null-safety with no existing stable versions. '
         'With a previous in-between null-safe prerelease', () async {
       await setup(sdkConstraint: '>=2.9.0 <3.0.0');
-      await servePackages(
-        (server) => server.serve(
-          'test_pkg',
-          '0.0.2-dev',
-          pubspec: {
-            'environment': {'sdk': '>=2.12.0<3.0.0'}
-          },
-        ),
+      final server = await servePackages();
+      server.serve(
+        'test_pkg',
+        '0.0.2-dev',
+        pubspec: {
+          'environment': {'sdk': '>=2.12.0<3.0.0'}
+        },
       );
 
       await expectValidation(validator, hints: isNotEmpty);
@@ -232,23 +217,21 @@
     test(
         'is not opting in to null-safety with previous non-null-safe stable version. '
         'With an in-between null-safe prerelease', () async {
-      await servePackages(
-        (server) => server
-          ..serve(
-            'test_pkg',
-            '0.0.1',
-            pubspec: {
-              'environment': {'sdk': '>=2.9.0<3.0.0'}
-            },
-          )
-          ..serve(
-            'test_pkg',
-            '0.0.2-dev',
-            pubspec: {
-              'environment': {'sdk': '>=2.12.0<3.0.0'}
-            },
-          ),
-      );
+      await servePackages()
+        ..serve(
+          'test_pkg',
+          '0.0.1',
+          pubspec: {
+            'environment': {'sdk': '>=2.9.0<3.0.0'}
+          },
+        )
+        ..serve(
+          'test_pkg',
+          '0.0.2-dev',
+          pubspec: {
+            'environment': {'sdk': '>=2.12.0<3.0.0'}
+          },
+        );
 
       await setup(sdkConstraint: '>=2.9.0 <3.0.0');
       await expectValidation(validator, hints: isNotEmpty);
@@ -257,23 +240,21 @@
     test(
         'opts in to null-safety, with previous version not-null-safe. '
         'Even with a later null-safe version', () async {
-      await servePackages(
-        (server) => server
-          ..serve(
-            'test_pkg',
-            '0.0.1',
-            pubspec: {
-              'environment': {'sdk': '>=2.9.0<3.0.0'}
-            },
-          )
-          ..serve(
-            'test_pkg',
-            '2.0.0',
-            pubspec: {
-              'environment': {'sdk': '>=2.12.0<3.0.0'}
-            },
-          ),
-      );
+      await servePackages()
+        ..serve(
+          'test_pkg',
+          '0.0.1',
+          pubspec: {
+            'environment': {'sdk': '>=2.9.0<3.0.0'}
+          },
+        )
+        ..serve(
+          'test_pkg',
+          '2.0.0',
+          pubspec: {
+            'environment': {'sdk': '>=2.12.0<3.0.0'}
+          },
+        );
 
       await setup(sdkConstraint: '>=2.12.0 <3.0.0');
       await expectValidation(validator, hints: isNotEmpty);
@@ -281,14 +262,13 @@
 
     test('is not opting in to null-safety with previous null-safe version',
         () async {
-      await servePackages(
-        (server) => server.serve(
-          'test_pkg',
-          '0.0.1',
-          pubspec: {
-            'environment': {'sdk': '>=2.12.0<3.0.0'}
-          },
-        ),
+      final server = await servePackages();
+      server.serve(
+        'test_pkg',
+        '0.0.1',
+        pubspec: {
+          'environment': {'sdk': '>=2.12.0<3.0.0'}
+        },
       );
 
       await setup(sdkConstraint: '>=2.9.0 <3.0.0');
@@ -298,23 +278,21 @@
     test(
         'is not opting in to null-safety with previous null-safe version. '
         'Even with a later non-null-safe version', () async {
-      await servePackages(
-        (server) => server
-          ..serve(
-            'test_pkg',
-            '0.0.1',
-            pubspec: {
-              'environment': {'sdk': '>=2.12.0<3.0.0'}
-            },
-          )
-          ..serve(
-            'test_pkg',
-            '2.0.0',
-            pubspec: {
-              'environment': {'sdk': '>=2.9.0<3.0.0'}
-            },
-          ),
-      );
+      await servePackages()
+        ..serve(
+          'test_pkg',
+          '0.0.1',
+          pubspec: {
+            'environment': {'sdk': '>=2.12.0<3.0.0'}
+          },
+        )
+        ..serve(
+          'test_pkg',
+          '2.0.0',
+          pubspec: {
+            'environment': {'sdk': '>=2.9.0<3.0.0'}
+          },
+        );
 
       await setup(sdkConstraint: '>=2.9.0 <3.0.0');
       await expectValidation(validator, hints: isNotEmpty);
@@ -323,23 +301,21 @@
     test(
         'is opting in to null-safety with previous null-safe stable version. '
         'with an in-between non-null-safe prerelease', () async {
-      await servePackages(
-        (server) => server
-          ..serve(
-            'test_pkg',
-            '0.0.1',
-            pubspec: {
-              'environment': {'sdk': '>=2.12.0<3.0.0'}
-            },
-          )
-          ..serve(
-            'test_pkg',
-            '0.0.2-dev',
-            pubspec: {
-              'environment': {'sdk': '>=2.9.0<3.0.0'}
-            },
-          ),
-      );
+      await servePackages()
+        ..serve(
+          'test_pkg',
+          '0.0.1',
+          pubspec: {
+            'environment': {'sdk': '>=2.12.0<3.0.0'}
+          },
+        )
+        ..serve(
+          'test_pkg',
+          '0.0.2-dev',
+          pubspec: {
+            'environment': {'sdk': '>=2.9.0<3.0.0'}
+          },
+        );
 
       await setup(sdkConstraint: '>=2.12.0 <3.0.0');
       await expectValidation(validator, hints: isNotEmpty);
@@ -349,14 +325,13 @@
         'is opting in to null-safety with no existing stable versions. '
         'With a previous non-null-safe prerelease', () async {
       await setup(sdkConstraint: '>=2.12.0 <3.0.0');
-      await servePackages(
-        (server) => server.serve(
-          'test_pkg',
-          '0.0.2-dev',
-          pubspec: {
-            'environment': {'sdk': '>=2.9.0<3.0.0'}
-          },
-        ),
+      final server = await servePackages();
+      server.serve(
+        'test_pkg',
+        '0.0.2-dev',
+        pubspec: {
+          'environment': {'sdk': '>=2.9.0<3.0.0'}
+        },
       );
       await expectValidation(validator, hints: isNotEmpty);
     });
diff --git a/test/validator/sdk_constraint_test.dart b/test/validator/sdk_constraint_test.dart
index 1310d17..c24adf2 100644
--- a/test/validator/sdk_constraint_test.dart
+++ b/test/validator/sdk_constraint_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
 import 'package:pub/src/validator/sdk_constraint.dart';
diff --git a/test/validator/size_test.dart b/test/validator/size_test.dart
index 37a746d..3a22e60 100644
--- a/test/validator/size_test.dart
+++ b/test/validator/size_test.dart
@@ -2,10 +2,7 @@
 // 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.
 
-// @dart=2.10
-
 import 'dart:async';
-import 'dart:math' as math;
 
 import 'package:pub/src/validator/size.dart';
 import 'package:test/test.dart';
@@ -20,7 +17,7 @@
 
 Future<void> expectSizeValidationError(Matcher matcher) async {
   await expectValidation(
-    size(100 * math.pow(2, 20) + 1),
+    size(100 * 1048577 /*2^20 +1*/),
     errors: contains(matcher),
   );
 }
@@ -30,7 +27,7 @@
     await d.validPackage.create();
 
     await expectValidation(size(100));
-    await expectValidation(size(100 * math.pow(2, 20)));
+    await expectValidation(size(100 * 1048576 /*2^20*/));
   });
 
   group('considers a package invalid if it is more than 100 MB', () {
diff --git a/test/validator/strict_dependencies_test.dart b/test/validator/strict_dependencies_test.dart
index 0456413..7b7962a 100644
--- a/test/validator/strict_dependencies_test.dart
+++ b/test/validator/strict_dependencies_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:path/path.dart' as path;
 import 'package:pub/src/entrypoint.dart';
 import 'package:pub/src/validator.dart';
@@ -67,8 +65,8 @@
 
     for (var port in ['import', 'export']) {
       for (var isDev in [false, true]) {
-        Map<String, String> deps;
-        Map<String, String> devDeps;
+        Map<String, String>? deps;
+        Map<String, String>? devDeps;
 
         if (isDev) {
           devDeps = {'silly_monkey': '^1.2.3'};
diff --git a/test/validator/utils.dart b/test/validator/utils.dart
index 7eda0fd..5123683 100644
--- a/test/validator/utils.dart
+++ b/test/validator/utils.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'package:test/test.dart';
 
 import '../test_pub.dart';
diff --git a/test/version_solver_test.dart b/test/version_solver_test.dart
index cf6f65f..d36a16f 100644
--- a/test/version_solver_test.dart
+++ b/test/version_solver_test.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 import 'dart:async';
 import 'dart:io';
 
@@ -42,14 +40,13 @@
   });
 
   test('simple dependency tree', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {'aa': '1.0.0', 'ab': '1.0.0'});
-      builder.serve('aa', '1.0.0');
-      builder.serve('ab', '1.0.0');
-      builder.serve('b', '1.0.0', deps: {'ba': '1.0.0', 'bb': '1.0.0'});
-      builder.serve('ba', '1.0.0');
-      builder.serve('bb', '1.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {'aa': '1.0.0', 'ab': '1.0.0'})
+      ..serve('aa', '1.0.0')
+      ..serve('ab', '1.0.0')
+      ..serve('b', '1.0.0', deps: {'ba': '1.0.0', 'bb': '1.0.0'})
+      ..serve('ba', '1.0.0')
+      ..serve('bb', '1.0.0');
 
     await d.appDir({'a': '1.0.0', 'b': '1.0.0'}).create();
     await expectResolves(result: {
@@ -63,15 +60,14 @@
   });
 
   test('shared dependency with overlapping constraints', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {'shared': '>=2.0.0 <4.0.0'});
-      builder.serve('b', '1.0.0', deps: {'shared': '>=3.0.0 <5.0.0'});
-      builder.serve('shared', '2.0.0');
-      builder.serve('shared', '3.0.0');
-      builder.serve('shared', '3.6.9');
-      builder.serve('shared', '4.0.0');
-      builder.serve('shared', '5.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {'shared': '>=2.0.0 <4.0.0'})
+      ..serve('b', '1.0.0', deps: {'shared': '>=3.0.0 <5.0.0'})
+      ..serve('shared', '2.0.0')
+      ..serve('shared', '3.0.0')
+      ..serve('shared', '3.6.9')
+      ..serve('shared', '4.0.0')
+      ..serve('shared', '5.0.0');
 
     await d.appDir({'a': '1.0.0', 'b': '1.0.0'}).create();
     await expectResolves(
@@ -81,16 +77,15 @@
   test(
       'shared dependency where dependent version in turn affects other '
       'dependencies', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '1.0.1', deps: {'bang': '1.0.0'});
-      builder.serve('foo', '1.0.2', deps: {'whoop': '1.0.0'});
-      builder.serve('foo', '1.0.3', deps: {'zoop': '1.0.0'});
-      builder.serve('bar', '1.0.0', deps: {'foo': '<=1.0.1'});
-      builder.serve('bang', '1.0.0');
-      builder.serve('whoop', '1.0.0');
-      builder.serve('zoop', '1.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '1.0.1', deps: {'bang': '1.0.0'})
+      ..serve('foo', '1.0.2', deps: {'whoop': '1.0.0'})
+      ..serve('foo', '1.0.3', deps: {'zoop': '1.0.0'})
+      ..serve('bar', '1.0.0', deps: {'foo': '<=1.0.1'})
+      ..serve('bang', '1.0.0')
+      ..serve('whoop', '1.0.0')
+      ..serve('zoop', '1.0.0');
 
     await d.appDir({'foo': '<=1.0.2', 'bar': '1.0.0'}).create();
     await expectResolves(
@@ -98,23 +93,21 @@
   });
 
   test('circular dependency', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
-      builder.serve('bar', '1.0.0', deps: {'foo': '1.0.0'});
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+      ..serve('bar', '1.0.0', deps: {'foo': '1.0.0'});
 
     await d.appDir({'foo': '1.0.0'}).create();
     await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'});
   });
 
   test('removed dependency', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '2.0.0');
-      builder.serve('bar', '1.0.0');
-      builder.serve('bar', '2.0.0', deps: {'baz': '1.0.0'});
-      builder.serve('baz', '1.0.0', deps: {'foo': '2.0.0'});
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '2.0.0')
+      ..serve('bar', '1.0.0')
+      ..serve('bar', '2.0.0', deps: {'baz': '1.0.0'})
+      ..serve('baz', '1.0.0', deps: {'foo': '2.0.0'});
 
     await d.appDir({'foo': '1.0.0', 'bar': 'any'}).create();
     await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'}, tries: 2);
@@ -123,14 +116,13 @@
 
 void withLockFile() {
   test('with compatible locked dependency', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
-      builder.serve('foo', '1.0.1', deps: {'bar': '1.0.1'});
-      builder.serve('foo', '1.0.2', deps: {'bar': '1.0.2'});
-      builder.serve('bar', '1.0.0');
-      builder.serve('bar', '1.0.1');
-      builder.serve('bar', '1.0.2');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+      ..serve('foo', '1.0.1', deps: {'bar': '1.0.1'})
+      ..serve('foo', '1.0.2', deps: {'bar': '1.0.2'})
+      ..serve('bar', '1.0.0')
+      ..serve('bar', '1.0.1')
+      ..serve('bar', '1.0.2');
 
     await d.appDir({'foo': '1.0.1'}).create();
     await expectResolves(result: {'foo': '1.0.1', 'bar': '1.0.1'});
@@ -140,14 +132,13 @@
   });
 
   test('with incompatible locked dependency', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
-      builder.serve('foo', '1.0.1', deps: {'bar': '1.0.1'});
-      builder.serve('foo', '1.0.2', deps: {'bar': '1.0.2'});
-      builder.serve('bar', '1.0.0');
-      builder.serve('bar', '1.0.1');
-      builder.serve('bar', '1.0.2');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+      ..serve('foo', '1.0.1', deps: {'bar': '1.0.1'})
+      ..serve('foo', '1.0.2', deps: {'bar': '1.0.2'})
+      ..serve('bar', '1.0.0')
+      ..serve('bar', '1.0.1')
+      ..serve('bar', '1.0.2');
 
     await d.appDir({'foo': '1.0.1'}).create();
     await expectResolves(result: {'foo': '1.0.1', 'bar': '1.0.1'});
@@ -157,15 +148,14 @@
   });
 
   test('with unrelated locked dependency', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
-      builder.serve('foo', '1.0.1', deps: {'bar': '1.0.1'});
-      builder.serve('foo', '1.0.2', deps: {'bar': '1.0.2'});
-      builder.serve('bar', '1.0.0');
-      builder.serve('bar', '1.0.1');
-      builder.serve('bar', '1.0.2');
-      builder.serve('baz', '1.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+      ..serve('foo', '1.0.1', deps: {'bar': '1.0.1'})
+      ..serve('foo', '1.0.2', deps: {'bar': '1.0.2'})
+      ..serve('bar', '1.0.0')
+      ..serve('bar', '1.0.1')
+      ..serve('bar', '1.0.2')
+      ..serve('baz', '1.0.0');
 
     await d.appDir({'baz': '1.0.0'}).create();
     await expectResolves(result: {'baz': '1.0.0'});
@@ -177,17 +167,16 @@
   test(
       'unlocks dependencies if necessary to ensure that a new '
       'dependency is satisfied', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
-      builder.serve('bar', '1.0.0', deps: {'baz': '<2.0.0'});
-      builder.serve('baz', '1.0.0', deps: {'qux': '<2.0.0'});
-      builder.serve('qux', '1.0.0');
-      builder.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
-      builder.serve('bar', '2.0.0', deps: {'baz': '<3.0.0'});
-      builder.serve('baz', '2.0.0', deps: {'qux': '<3.0.0'});
-      builder.serve('qux', '2.0.0');
-      builder.serve('newdep', '2.0.0', deps: {'baz': '>=1.5.0'});
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '<2.0.0'})
+      ..serve('bar', '1.0.0', deps: {'baz': '<2.0.0'})
+      ..serve('baz', '1.0.0', deps: {'qux': '<2.0.0'})
+      ..serve('qux', '1.0.0')
+      ..serve('foo', '2.0.0', deps: {'bar': '<3.0.0'})
+      ..serve('bar', '2.0.0', deps: {'baz': '<3.0.0'})
+      ..serve('baz', '2.0.0', deps: {'qux': '<3.0.0'})
+      ..serve('qux', '2.0.0')
+      ..serve('newdep', '2.0.0', deps: {'baz': '>=1.5.0'});
 
     await d.appDir({'foo': '1.0.0'}).create();
     await expectResolves(result: {
@@ -211,11 +200,10 @@
   test(
       "produces a nice message for a locked dependency that's the only "
       'version of its package', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '>=2.0.0'});
-      builder.serve('bar', '1.0.0');
-      builder.serve('bar', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '>=2.0.0'})
+      ..serve('bar', '1.0.0')
+      ..serve('bar', '2.0.0');
 
     await d.appDir({'foo': 'any'}).create();
     await expectResolves(result: {'foo': '1.0.0', 'bar': '2.0.0'});
@@ -231,30 +219,27 @@
 
 void rootDependency() {
   test('with root source', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'myapp': 'any'});
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', deps: {'myapp': 'any'});
 
     await d.appDir({'foo': '1.0.0'}).create();
     await expectResolves(result: {'foo': '1.0.0'});
   });
 
   test('with mismatched sources', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'myapp': 'any'});
-      builder.serve('bar', '1.0.0', deps: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'myapp': 'any'})
+      ..serve('bar', '1.0.0', deps: {
         'myapp': {'git': 'http://nowhere.com/'}
       });
-    });
 
     await d.appDir({'foo': '1.0.0', 'bar': '1.0.0'}).create();
     await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'});
   });
 
   test('with wrong version', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'myapp': '>0.0.0'});
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', deps: {'myapp': '>0.0.0'});
 
     await d.appDir({'foo': '1.0.0'}).create();
     await expectResolves(error: equalsIgnoringWhitespace('''
@@ -267,10 +252,9 @@
 
 void devDependency() {
   test("includes root package's dev dependencies", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('bar', '1.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('bar', '1.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -283,10 +267,9 @@
   });
 
   test("includes dev dependency's transitive dependencies", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
-      builder.serve('bar', '1.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+      ..serve('bar', '1.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -299,10 +282,9 @@
   });
 
   test("ignores transitive dependency's dev dependencies", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'dev_dependencies': {'bar': '1.0.0'}
-      });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'dev_dependencies': {'bar': '1.0.0'}
     });
 
     await d.appDir({'foo': '1.0.0'}).create();
@@ -311,11 +293,10 @@
 
   group('with both a dev and regular dependency', () {
     test('succeeds when both are satisfied', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-        builder.serve('foo', '2.0.0');
-        builder.serve('foo', '3.0.0');
-      });
+      await servePackages()
+        ..serve('foo', '1.0.0')
+        ..serve('foo', '2.0.0')
+        ..serve('foo', '3.0.0');
 
       await d.dir(appPath, [
         d.pubspec({
@@ -329,9 +310,8 @@
     });
 
     test("fails when main dependency isn't satisfied", () async {
-      await servePackages((builder) {
-        builder.serve('foo', '3.0.0');
-      });
+      final server = await servePackages();
+      server.serve('foo', '3.0.0');
 
       await d.dir(appPath, [
         d.pubspec({
@@ -349,9 +329,8 @@
     });
 
     test("fails when dev dependency isn't satisfied", () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-      });
+      final server = await servePackages();
+      server.serve('foo', '1.0.0');
 
       await d.dir(appPath, [
         d.pubspec({
@@ -369,9 +348,8 @@
     });
 
     test('fails when dev and main constraints are incompatible', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-      });
+      final server = await servePackages();
+      server.serve('foo', '1.0.0');
 
       await d.dir(appPath, [
         d.pubspec({
@@ -388,9 +366,8 @@
     });
 
     test('fails when dev and main sources are incompatible', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-      });
+      final server = await servePackages();
+      server.serve('foo', '1.0.0');
 
       await d.dir(appPath, [
         d.pubspec({
@@ -409,9 +386,8 @@
     });
 
     test('fails when dev and main descriptions are incompatible', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-      });
+      final server = await servePackages();
+      server.serve('foo', '1.0.0');
 
       await d.dir(appPath, [
         d.pubspec({
@@ -435,10 +411,9 @@
 
 void unsolvable() {
   test('no version that matches constraint', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '2.0.0');
-      builder.serve('foo', '2.1.3');
-    });
+    await servePackages()
+      ..serve('foo', '2.0.0')
+      ..serve('foo', '2.1.3');
 
     await d.appDir({'foo': '>=1.0.0 <2.0.0'}).create();
     await expectResolves(error: equalsIgnoringWhitespace("""
@@ -448,12 +423,11 @@
   });
 
   test('no version that matches combined constraint', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'shared': '>=2.0.0 <3.0.0'});
-      builder.serve('bar', '1.0.0', deps: {'shared': '>=2.9.0 <4.0.0'});
-      builder.serve('shared', '2.5.0');
-      builder.serve('shared', '3.5.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'shared': '>=2.0.0 <3.0.0'})
+      ..serve('bar', '1.0.0', deps: {'shared': '>=2.9.0 <4.0.0'})
+      ..serve('shared', '2.5.0')
+      ..serve('shared', '3.5.0');
 
     await d.appDir({'foo': '1.0.0', 'bar': '1.0.0'}).create();
     await expectResolves(error: equalsIgnoringWhitespace('''
@@ -468,12 +442,11 @@
   });
 
   test('disjoint constraints', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'shared': '<=2.0.0'});
-      builder.serve('bar', '1.0.0', deps: {'shared': '>3.0.0'});
-      builder.serve('shared', '2.0.0');
-      builder.serve('shared', '4.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'shared': '<=2.0.0'})
+      ..serve('bar', '1.0.0', deps: {'shared': '>3.0.0'})
+      ..serve('shared', '2.0.0')
+      ..serve('shared', '4.0.0');
 
     await d.appDir({'foo': '1.0.0', 'bar': '1.0.0'}).create();
     await expectResolves(error: equalsIgnoringWhitespace('''
@@ -485,20 +458,18 @@
   });
 
   test('mismatched descriptions', () async {
-    var otherServer = await PackageServer.start((builder) {
-      builder.serve('shared', '1.0.0');
-    });
+    var otherServer = await startPackageServer();
+    otherServer.serve('shared', '1.0.0');
 
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'shared': '1.0.0'});
-      builder.serve('bar', '1.0.0', deps: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'shared': '1.0.0'})
+      ..serve('bar', '1.0.0', deps: {
         'shared': {
           'hosted': {'name': 'shared', 'url': otherServer.url},
           'version': '1.0.0'
         }
-      });
-      builder.serve('shared', '1.0.0');
-    });
+      })
+      ..serve('shared', '1.0.0');
 
     await d.appDir({'foo': '1.0.0', 'bar': '1.0.0'}).create();
 
@@ -517,13 +488,12 @@
   test('mismatched sources', () async {
     await d.dir('shared', [d.libPubspec('shared', '1.0.0')]).create();
 
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'shared': '1.0.0'});
-      builder.serve('bar', '1.0.0', deps: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'shared': '1.0.0'})
+      ..serve('bar', '1.0.0', deps: {
         'shared': {'path': p.join(d.sandbox, 'shared')}
-      });
-      builder.serve('shared', '1.0.0');
-    });
+      })
+      ..serve('shared', '1.0.0');
 
     await d.appDir({'foo': '1.0.0', 'bar': '1.0.0'}).create();
     await expectResolves(error: equalsIgnoringWhitespace('''
@@ -536,12 +506,11 @@
   });
 
   test('no valid solution', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {'b': '1.0.0'});
-      builder.serve('a', '2.0.0', deps: {'b': '2.0.0'});
-      builder.serve('b', '1.0.0', deps: {'a': '2.0.0'});
-      builder.serve('b', '2.0.0', deps: {'a': '1.0.0'});
-    });
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {'b': '1.0.0'})
+      ..serve('a', '2.0.0', deps: {'b': '2.0.0'})
+      ..serve('b', '1.0.0', deps: {'a': '2.0.0'})
+      ..serve('b', '2.0.0', deps: {'a': '1.0.0'});
 
     await d.appDir({'a': 'any', 'b': 'any'}).create();
     await expectResolves(error: equalsIgnoringWhitespace('''
@@ -556,10 +525,9 @@
 
   // This is a regression test for #15550.
   test('no version that matches while backtracking', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('b', '1.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('b', '1.0.0');
 
     await d.appDir({'a': 'any', 'b': '>1.0.0'}).create();
     await expectResolves(error: equalsIgnoringWhitespace("""
@@ -570,19 +538,18 @@
 
   // This is a regression test for #18300.
   test('issue 18300', () async {
-    await servePackages((builder) {
-      builder.serve('analyzer', '0.12.2');
-      builder.serve('angular', '0.10.0',
-          deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'});
-      builder.serve('angular', '0.9.11',
-          deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'});
-      builder.serve('angular', '0.9.10',
-          deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'});
-      builder.serve('collection', '0.9.0');
-      builder.serve('collection', '0.9.1');
-      builder.serve('di', '0.0.37', deps: {'analyzer': '>=0.13.0 <0.14.0'});
-      builder.serve('di', '0.0.36', deps: {'analyzer': '>=0.13.0 <0.14.0'});
-    });
+    await servePackages()
+      ..serve('analyzer', '0.12.2')
+      ..serve('angular', '0.10.0',
+          deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'})
+      ..serve('angular', '0.9.11',
+          deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'})
+      ..serve('angular', '0.9.10',
+          deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'})
+      ..serve('collection', '0.9.0')
+      ..serve('collection', '0.9.1')
+      ..serve('di', '0.0.37', deps: {'analyzer': '>=0.13.0 <0.14.0'})
+      ..serve('di', '0.0.36', deps: {'analyzer': '>=0.13.0 <0.14.0'});
 
     await d.appDir({'angular': 'any', 'collection': 'any'}).create();
     await expectResolves(error: equalsIgnoringWhitespace('''
@@ -622,17 +589,16 @@
   });
 
   test('fail if all versions have bad source in dep', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {
         'bar': {'bad': 'any'}
-      });
-      builder.serve('foo', '1.0.1', deps: {
+      })
+      ..serve('foo', '1.0.1', deps: {
         'baz': {'bad': 'any'}
-      });
-      builder.serve('foo', '1.0.2', deps: {
+      })
+      ..serve('foo', '1.0.2', deps: {
         'bang': {'bad': 'any'}
       });
-    });
 
     await d.appDir({'foo': 'any'}).create();
     await expectResolves(error: equalsIgnoringWhitespace('''
@@ -648,16 +614,15 @@
   });
 
   test('ignore versions with bad source in dep', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
-      builder.serve('foo', '1.0.1', deps: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': 'any'})
+      ..serve('foo', '1.0.1', deps: {
         'bar': {'bad': 'any'}
-      });
-      builder.serve('foo', '1.0.2', deps: {
+      })
+      ..serve('foo', '1.0.2', deps: {
         'bar': {'bad': 'any'}
-      });
-      builder.serve('bar', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0');
 
     await d.appDir({'foo': 'any'}).create();
     await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'}, tries: 2);
@@ -665,11 +630,10 @@
 
   // Issue 1853
   test('reports a nice error across a collapsed cause', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
-      builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
-      builder.serve('baz', '1.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': 'any'})
+      ..serve('bar', '1.0.0', deps: {'baz': 'any'})
+      ..serve('baz', '1.0.0');
     await d.dir('baz', [d.libPubspec('baz', '1.0.0')]).create();
 
     await d.appDir({
@@ -687,28 +651,24 @@
 
 void backtracking() {
   test('circular dependency on older version', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('a', '2.0.0', deps: {'b': '1.0.0'});
-      builder.serve('b', '1.0.0', deps: {'a': '1.0.0'});
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('a', '2.0.0', deps: {'b': '1.0.0'})
+      ..serve('b', '1.0.0', deps: {'a': '1.0.0'});
 
     await d.appDir({'a': '>=1.0.0'}).create();
     await expectResolves(result: {'a': '1.0.0'}, tries: 2);
   });
 
   test('diamond dependency graph', () async {
-    await servePackages((builder) {
-      builder.serve('a', '2.0.0', deps: {'c': '^1.0.0'});
-      builder.serve('a', '1.0.0');
-
-      builder.serve('b', '2.0.0', deps: {'c': '^3.0.0'});
-      builder.serve('b', '1.0.0', deps: {'c': '^2.0.0'});
-
-      builder.serve('c', '3.0.0');
-      builder.serve('c', '2.0.0');
-      builder.serve('c', '1.0.0');
-    });
+    await servePackages()
+      ..serve('a', '2.0.0', deps: {'c': '^1.0.0'})
+      ..serve('a', '1.0.0')
+      ..serve('b', '2.0.0', deps: {'c': '^3.0.0'})
+      ..serve('b', '1.0.0', deps: {'c': '^2.0.0'})
+      ..serve('c', '3.0.0')
+      ..serve('c', '2.0.0')
+      ..serve('c', '1.0.0');
 
     await d.appDir({'a': 'any', 'b': 'any'}).create();
     await expectResolves(result: {'a': '1.0.0', 'b': '2.0.0', 'c': '3.0.0'});
@@ -718,20 +678,16 @@
   // requirement only exists because of both a and b. The solver should be able
   // to deduce c 2.0.0's incompatibility and select c 1.0.0 instead.
   test('backjumps after a partial satisfier', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {'x': '>=1.0.0'});
-      builder.serve('b', '1.0.0', deps: {'x': '<2.0.0'});
-
-      builder.serve('c', '1.0.0');
-      builder.serve('c', '2.0.0', deps: {'a': 'any', 'b': 'any'});
-
-      builder.serve('x', '0.0.0');
-      builder.serve('x', '1.0.0', deps: {'y': '1.0.0'});
-      builder.serve('x', '2.0.0');
-
-      builder.serve('y', '1.0.0');
-      builder.serve('y', '2.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {'x': '>=1.0.0'})
+      ..serve('b', '1.0.0', deps: {'x': '<2.0.0'})
+      ..serve('c', '1.0.0')
+      ..serve('c', '2.0.0', deps: {'a': 'any', 'b': 'any'})
+      ..serve('x', '0.0.0')
+      ..serve('x', '1.0.0', deps: {'y': '1.0.0'})
+      ..serve('x', '2.0.0')
+      ..serve('y', '1.0.0')
+      ..serve('y', '2.0.0');
 
     await d.appDir({'c': 'any', 'y': '^2.0.0'}).create();
     await expectResolves(result: {'c': '1.0.0', 'y': '2.0.0'}, tries: 2);
@@ -740,16 +696,15 @@
   // This matches the Branching Error Reporting example in the version solver
   // documentation, and tests that we display line numbers correctly.
   test('branching error reporting', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'a': '^1.0.0', 'b': '^1.0.0'});
-      builder.serve('foo', '1.1.0', deps: {'x': '^1.0.0', 'y': '^1.0.0'});
-      builder.serve('a', '1.0.0', deps: {'b': '^2.0.0'});
-      builder.serve('b', '1.0.0');
-      builder.serve('b', '2.0.0');
-      builder.serve('x', '1.0.0', deps: {'y': '^2.0.0'});
-      builder.serve('y', '1.0.0');
-      builder.serve('y', '2.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'a': '^1.0.0', 'b': '^1.0.0'})
+      ..serve('foo', '1.1.0', deps: {'x': '^1.0.0', 'y': '^1.0.0'})
+      ..serve('a', '1.0.0', deps: {'b': '^2.0.0'})
+      ..serve('b', '1.0.0')
+      ..serve('b', '2.0.0')
+      ..serve('x', '1.0.0', deps: {'y': '^2.0.0'})
+      ..serve('y', '1.0.0')
+      ..serve('y', '2.0.0');
 
     await d.appDir({'foo': '^1.0.0'}).create();
     await expectResolves(
@@ -774,14 +729,13 @@
   // will resolve the problem. This test validates that b, which is farther
   // in the dependency graph from myapp is downgraded first.
   test('rolls back leaf versions first', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {'b': 'any'});
-      builder.serve('a', '2.0.0', deps: {'b': 'any', 'c': '2.0.0'});
-      builder.serve('b', '1.0.0');
-      builder.serve('b', '2.0.0', deps: {'c': '1.0.0'});
-      builder.serve('c', '1.0.0');
-      builder.serve('c', '2.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {'b': 'any'})
+      ..serve('a', '2.0.0', deps: {'b': 'any', 'c': '2.0.0'})
+      ..serve('b', '1.0.0')
+      ..serve('b', '2.0.0', deps: {'c': '1.0.0'})
+      ..serve('c', '1.0.0')
+      ..serve('c', '2.0.0');
 
     await d.appDir({'a': 'any'}).create();
     await expectResolves(result: {'a': '2.0.0', 'b': '1.0.0', 'c': '2.0.0'});
@@ -790,15 +744,14 @@
   // Only one version of baz, so foo and bar will have to downgrade until they
   // reach it.
   test('simple transitive', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
-      builder.serve('foo', '2.0.0', deps: {'bar': '2.0.0'});
-      builder.serve('foo', '3.0.0', deps: {'bar': '3.0.0'});
-      builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
-      builder.serve('bar', '2.0.0', deps: {'baz': '2.0.0'});
-      builder.serve('bar', '3.0.0', deps: {'baz': '3.0.0'});
-      builder.serve('baz', '1.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+      ..serve('foo', '2.0.0', deps: {'bar': '2.0.0'})
+      ..serve('foo', '3.0.0', deps: {'bar': '3.0.0'})
+      ..serve('bar', '1.0.0', deps: {'baz': 'any'})
+      ..serve('bar', '2.0.0', deps: {'baz': '2.0.0'})
+      ..serve('bar', '3.0.0', deps: {'baz': '3.0.0'})
+      ..serve('baz', '1.0.0');
 
     await d.appDir({'foo': 'any'}).create();
     await expectResolves(
@@ -810,14 +763,13 @@
   // make sure b has more versions than a so that the solver tries a first
   // since it sorts sibling dependencies by number of versions.
   test('backjump to nearer unsatisfied package', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {'c': '1.0.0'});
-      builder.serve('a', '2.0.0', deps: {'c': '2.0.0-nonexistent'});
-      builder.serve('b', '1.0.0');
-      builder.serve('b', '2.0.0');
-      builder.serve('b', '3.0.0');
-      builder.serve('c', '1.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {'c': '1.0.0'})
+      ..serve('a', '2.0.0', deps: {'c': '2.0.0-nonexistent'})
+      ..serve('b', '1.0.0')
+      ..serve('b', '2.0.0')
+      ..serve('b', '3.0.0')
+      ..serve('c', '1.0.0');
 
     await d.appDir({'a': 'any', 'b': 'any'}).create();
     await expectResolves(
@@ -841,18 +793,17 @@
   test('successful backjump to conflicting source', () async {
     await d.dir('a', [d.libPubspec('a', '1.0.0')]).create();
 
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('b', '1.0.0', deps: {'a': 'any'});
-      builder.serve('b', '2.0.0', deps: {
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('b', '1.0.0', deps: {'a': 'any'})
+      ..serve('b', '2.0.0', deps: {
         'a': {'path': p.join(d.sandbox, 'a')}
-      });
-      builder.serve('c', '1.0.0');
-      builder.serve('c', '2.0.0');
-      builder.serve('c', '3.0.0');
-      builder.serve('c', '4.0.0');
-      builder.serve('c', '5.0.0');
-    });
+      })
+      ..serve('c', '1.0.0')
+      ..serve('c', '2.0.0')
+      ..serve('c', '3.0.0')
+      ..serve('c', '4.0.0')
+      ..serve('c', '5.0.0');
 
     await d.appDir({'a': 'any', 'b': 'any', 'c': 'any'}).create();
     await expectResolves(result: {'a': '1.0.0', 'b': '1.0.0', 'c': '5.0.0'});
@@ -860,24 +811,22 @@
 
   // Like the above test, but for a conflicting description.
   test('successful backjump to conflicting description', () async {
-    var otherServer = await PackageServer.start((builder) {
-      builder.serve('a', '1.0.0');
-    });
+    var otherServer = await startPackageServer();
+    otherServer.serve('a', '1.0.0');
 
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('b', '1.0.0', deps: {'a': 'any'});
-      builder.serve('b', '2.0.0', deps: {
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('b', '1.0.0', deps: {'a': 'any'})
+      ..serve('b', '2.0.0', deps: {
         'a': {
           'hosted': {'name': 'a', 'url': otherServer.url}
         }
-      });
-      builder.serve('c', '1.0.0');
-      builder.serve('c', '2.0.0');
-      builder.serve('c', '3.0.0');
-      builder.serve('c', '4.0.0');
-      builder.serve('c', '5.0.0');
-    });
+      })
+      ..serve('c', '1.0.0')
+      ..serve('c', '2.0.0')
+      ..serve('c', '3.0.0')
+      ..serve('c', '4.0.0')
+      ..serve('c', '5.0.0');
 
     await d.appDir({'a': 'any', 'b': 'any', 'c': 'any'}).create();
     await expectResolves(result: {'a': '1.0.0', 'b': '1.0.0', 'c': '5.0.0'});
@@ -888,17 +837,16 @@
   test('failing backjump to conflicting source', () async {
     await d.dir('a', [d.libPubspec('a', '1.0.0')]).create();
 
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('b', '1.0.0', deps: {
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('b', '1.0.0', deps: {
         'a': {'path': p.join(d.sandbox, 'shared')}
-      });
-      builder.serve('c', '1.0.0');
-      builder.serve('c', '2.0.0');
-      builder.serve('c', '3.0.0');
-      builder.serve('c', '4.0.0');
-      builder.serve('c', '5.0.0');
-    });
+      })
+      ..serve('c', '1.0.0')
+      ..serve('c', '2.0.0')
+      ..serve('c', '3.0.0')
+      ..serve('c', '4.0.0')
+      ..serve('c', '5.0.0');
 
     await d.appDir({'a': 'any', 'b': 'any', 'c': 'any'}).create();
     await expectResolves(error: equalsIgnoringWhitespace('''
@@ -909,23 +857,21 @@
   });
 
   test('failing backjump to conflicting description', () async {
-    var otherServer = await PackageServer.start((builder) {
-      builder.serve('a', '1.0.0');
-    });
+    var otherServer = await startPackageServer();
+    otherServer.serve('a', '1.0.0');
 
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('b', '1.0.0', deps: {
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('b', '1.0.0', deps: {
         'a': {
           'hosted': {'name': 'a', 'url': otherServer.url}
         }
-      });
-      builder.serve('c', '1.0.0');
-      builder.serve('c', '2.0.0');
-      builder.serve('c', '3.0.0');
-      builder.serve('c', '4.0.0');
-      builder.serve('c', '5.0.0');
-    });
+      })
+      ..serve('c', '1.0.0')
+      ..serve('c', '2.0.0')
+      ..serve('c', '3.0.0')
+      ..serve('c', '4.0.0')
+      ..serve('c', '5.0.0');
 
     await d.appDir({'a': 'any', 'b': 'any', 'c': 'any'}).create();
     await expectResolves(
@@ -944,39 +890,37 @@
   // Since b has fewer versions, it will be traversed first, which means a will
   // come later. Since later selections are revised first, a gets downgraded.
   test('traverse into package with fewer versions first', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {'c': 'any'});
-      builder.serve('a', '2.0.0', deps: {'c': 'any'});
-      builder.serve('a', '3.0.0', deps: {'c': 'any'});
-      builder.serve('a', '4.0.0', deps: {'c': 'any'});
-      builder.serve('a', '5.0.0', deps: {'c': '1.0.0'});
-      builder.serve('b', '1.0.0', deps: {'c': 'any'});
-      builder.serve('b', '2.0.0', deps: {'c': 'any'});
-      builder.serve('b', '3.0.0', deps: {'c': 'any'});
-      builder.serve('b', '4.0.0', deps: {'c': '2.0.0'});
-      builder.serve('c', '1.0.0');
-      builder.serve('c', '2.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {'c': 'any'})
+      ..serve('a', '2.0.0', deps: {'c': 'any'})
+      ..serve('a', '3.0.0', deps: {'c': 'any'})
+      ..serve('a', '4.0.0', deps: {'c': 'any'})
+      ..serve('a', '5.0.0', deps: {'c': '1.0.0'})
+      ..serve('b', '1.0.0', deps: {'c': 'any'})
+      ..serve('b', '2.0.0', deps: {'c': 'any'})
+      ..serve('b', '3.0.0', deps: {'c': 'any'})
+      ..serve('b', '4.0.0', deps: {'c': '2.0.0'})
+      ..serve('c', '1.0.0')
+      ..serve('c', '2.0.0');
 
     await d.appDir({'a': 'any', 'b': 'any'}).create();
     await expectResolves(result: {'a': '4.0.0', 'b': '4.0.0', 'c': '2.0.0'});
   });
 
   test('complex backtrack', () async {
-    await servePackages((builder) {
-      // This sets up a hundred versions of foo and bar, 0.0.0 through 9.9.0. Each
-      // version of foo depends on a baz with the same major version. Each version
-      // of bar depends on a baz with the same minor version. There is only one
-      // version of baz, 0.0.0, so only older versions of foo and bar will
-      // satisfy it.
-      builder.serve('baz', '0.0.0');
-      for (var i = 0; i < 10; i++) {
-        for (var j = 0; j < 10; j++) {
-          builder.serve('foo', '$i.$j.0', deps: {'baz': '$i.0.0'});
-          builder.serve('bar', '$i.$j.0', deps: {'baz': '0.$j.0'});
-        }
+    final server = await servePackages();
+    // This sets up a hundred versions of foo and bar, 0.0.0 through 9.9.0. Each
+    // version of foo depends on a baz with the same major version. Each version
+    // of bar depends on a baz with the same minor version. There is only one
+    // version of baz, 0.0.0, so only older versions of foo and bar will
+    // satisfy it.
+    server.serve('baz', '0.0.0');
+    for (var i = 0; i < 10; i++) {
+      for (var j = 0; j < 10; j++) {
+        server.serve('foo', '$i.$j.0', deps: {'baz': '$i.0.0'});
+        server.serve('bar', '$i.$j.0', deps: {'baz': '0.$j.0'});
       }
-    });
+    }
 
     await d.appDir({'foo': 'any', 'bar': 'any'}).create();
     await expectResolves(
@@ -987,19 +931,18 @@
   // versions of it is a waste of time: no possible versions can match. We need
   // to jump past it to the most recent package that affected the constraint.
   test('backjump past failed package on disjoint constraint', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {
         'foo': 'any' // ok
-      });
-      builder.serve('a', '2.0.0', deps: {
+      })
+      ..serve('a', '2.0.0', deps: {
         'foo': '<1.0.0' // disjoint with myapp's constraint on foo
-      });
-      builder.serve('foo', '2.0.0');
-      builder.serve('foo', '2.0.1');
-      builder.serve('foo', '2.0.2');
-      builder.serve('foo', '2.0.3');
-      builder.serve('foo', '2.0.4');
-    });
+      })
+      ..serve('foo', '2.0.0')
+      ..serve('foo', '2.0.1')
+      ..serve('foo', '2.0.2')
+      ..serve('foo', '2.0.3')
+      ..serve('foo', '2.0.4');
 
     await d.appDir({'a': 'any', 'foo': '>2.0.0'}).create();
     await expectResolves(result: {'a': '1.0.0', 'foo': '2.0.4'});
@@ -1010,14 +953,13 @@
   // would backtrack over the failed package instead of trying different
   // versions of it.
   test('finds solution with less strict constraint', () async {
-    await servePackages((builder) {
-      builder.serve('a', '2.0.0');
-      builder.serve('a', '1.0.0');
-      builder.serve('b', '1.0.0', deps: {'a': '1.0.0'});
-      builder.serve('c', '1.0.0', deps: {'b': 'any'});
-      builder.serve('d', '2.0.0', deps: {'myapp': 'any'});
-      builder.serve('d', '1.0.0', deps: {'myapp': '<1.0.0'});
-    });
+    await servePackages()
+      ..serve('a', '2.0.0')
+      ..serve('a', '1.0.0')
+      ..serve('b', '1.0.0', deps: {'a': '1.0.0'})
+      ..serve('c', '1.0.0', deps: {'b': 'any'})
+      ..serve('d', '2.0.0', deps: {'myapp': 'any'})
+      ..serve('d', '1.0.0', deps: {'myapp': '<1.0.0'});
 
     await d.appDir({'a': 'any', 'c': 'any', 'd': 'any'}).create();
     await expectResolves(
@@ -1053,10 +995,9 @@
   });
 
   test('dependency does not match SDK', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
-        'environment': {'sdk': '0.0.0'}
-      });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0', pubspec: {
+      'environment': {'sdk': '0.0.0'}
     });
 
     await d.appDir({'foo': 'any'}).create();
@@ -1069,12 +1010,11 @@
   });
 
   test('transitive dependency does not match SDK', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
-      builder.serve('bar', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': 'any'})
+      ..serve('bar', '1.0.0', pubspec: {
         'environment': {'sdk': '0.0.0'}
       });
-    });
 
     await d.appDir({'foo': 'any'}).create();
     await expectResolves(error: equalsIgnoringWhitespace('''
@@ -1087,41 +1027,39 @@
   });
 
   test('selects a dependency version that allows the SDK', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'environment': {'sdk': '0.1.2+3'}
-      });
-      builder.serve('foo', '2.0.0', pubspec: {
+      })
+      ..serve('foo', '2.0.0', pubspec: {
         'environment': {'sdk': '0.1.2+3'}
-      });
-      builder.serve('foo', '3.0.0', pubspec: {
+      })
+      ..serve('foo', '3.0.0', pubspec: {
+        'environment': {'sdk': '0.0.0'}
+      })
+      ..serve('foo', '4.0.0', pubspec: {
         'environment': {'sdk': '0.0.0'}
       });
-      builder.serve('foo', '4.0.0', pubspec: {
-        'environment': {'sdk': '0.0.0'}
-      });
-    });
 
     await d.appDir({'foo': 'any'}).create();
     await expectResolves(result: {'foo': '2.0.0'});
   });
 
   test('selects a transitive dependency version that allows the SDK', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
-      builder.serve('bar', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': 'any'})
+      ..serve('bar', '1.0.0', pubspec: {
         'environment': {'sdk': '0.1.2+3'}
-      });
-      builder.serve('bar', '2.0.0', pubspec: {
+      })
+      ..serve('bar', '2.0.0', pubspec: {
         'environment': {'sdk': '0.1.2+3'}
-      });
-      builder.serve('bar', '3.0.0', pubspec: {
+      })
+      ..serve('bar', '3.0.0', pubspec: {
+        'environment': {'sdk': '0.0.0'}
+      })
+      ..serve('bar', '4.0.0', pubspec: {
         'environment': {'sdk': '0.0.0'}
       });
-      builder.serve('bar', '4.0.0', pubspec: {
-        'environment': {'sdk': '0.0.0'}
-      });
-    });
 
     await d.appDir({'foo': 'any'}).create();
     await expectResolves(result: {'foo': '1.0.0', 'bar': '2.0.0'});
@@ -1130,24 +1068,23 @@
   test(
       'selects a dependency version that allows a transitive '
       'dependency that allows the SDK', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
-      builder.serve('foo', '2.0.0', deps: {'bar': '2.0.0'});
-      builder.serve('foo', '3.0.0', deps: {'bar': '3.0.0'});
-      builder.serve('foo', '4.0.0', deps: {'bar': '4.0.0'});
-      builder.serve('bar', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+      ..serve('foo', '2.0.0', deps: {'bar': '2.0.0'})
+      ..serve('foo', '3.0.0', deps: {'bar': '3.0.0'})
+      ..serve('foo', '4.0.0', deps: {'bar': '4.0.0'})
+      ..serve('bar', '1.0.0', pubspec: {
         'environment': {'sdk': '0.1.2+3'}
-      });
-      builder.serve('bar', '2.0.0', pubspec: {
+      })
+      ..serve('bar', '2.0.0', pubspec: {
         'environment': {'sdk': '0.1.2+3'}
-      });
-      builder.serve('bar', '3.0.0', pubspec: {
+      })
+      ..serve('bar', '3.0.0', pubspec: {
+        'environment': {'sdk': '0.0.0'}
+      })
+      ..serve('bar', '4.0.0', pubspec: {
         'environment': {'sdk': '0.0.0'}
       });
-      builder.serve('bar', '4.0.0', pubspec: {
-        'environment': {'sdk': '0.0.0'}
-      });
-    });
 
     await d.appDir({'foo': 'any'}).create();
     await expectResolves(result: {'foo': '2.0.0', 'bar': '2.0.0'}, tries: 2);
@@ -1465,10 +1402,9 @@
     });
 
     test('fails for a dependency', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
-          'environment': {'flutter': '0.0.0'}
-        });
+      final server = await servePackages();
+      server.serve('foo', '1.0.0', pubspec: {
+        'environment': {'flutter': '0.0.0'}
       });
 
       await d.appDir({'foo': 'any'}).create();
@@ -1481,13 +1417,12 @@
     });
 
     test("chooses a version that doesn't need Flutter", () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-        builder.serve('foo', '2.0.0');
-        builder.serve('foo', '3.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0')
+        ..serve('foo', '2.0.0')
+        ..serve('foo', '3.0.0', pubspec: {
           'environment': {'flutter': '0.0.0'}
         });
-      });
 
       await d.appDir({'foo': 'any'}).create();
       await expectResolves(result: {'foo': '2.0.0'});
@@ -1614,17 +1549,16 @@
     });
 
     test('selects the latest dependency with a matching constraint', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0', pubspec: {
           'environment': {'flutter': '^0.0.0'}
-        });
-        builder.serve('foo', '2.0.0', pubspec: {
+        })
+        ..serve('foo', '2.0.0', pubspec: {
           'environment': {'flutter': '^1.0.0'}
-        });
-        builder.serve('foo', '3.0.0', pubspec: {
+        })
+        ..serve('foo', '3.0.0', pubspec: {
           'environment': {'flutter': '^2.0.0'}
         });
-      });
 
       await d.appDir({'foo': 'any'}).create();
       await expectResolves(
@@ -1636,36 +1570,33 @@
 
 void prerelease() {
   test('prefer stable versions over unstable', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('a', '1.1.0-dev');
-      builder.serve('a', '2.0.0-dev');
-      builder.serve('a', '3.0.0-dev');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('a', '1.1.0-dev')
+      ..serve('a', '2.0.0-dev')
+      ..serve('a', '3.0.0-dev');
 
     await d.appDir({'a': 'any'}).create();
     await expectResolves(result: {'a': '1.0.0'});
   });
 
   test('use latest allowed prerelease if no stable versions match', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0-dev');
-      builder.serve('a', '1.1.0-dev');
-      builder.serve('a', '1.9.0-dev');
-      builder.serve('a', '3.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0-dev')
+      ..serve('a', '1.1.0-dev')
+      ..serve('a', '1.9.0-dev')
+      ..serve('a', '3.0.0');
 
     await d.appDir({'a': '<2.0.0'}).create();
     await expectResolves(result: {'a': '1.9.0-dev'});
   });
 
   test('use an earlier stable version on a < constraint', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('a', '1.1.0');
-      builder.serve('a', '2.0.0-dev');
-      builder.serve('a', '2.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('a', '1.1.0')
+      ..serve('a', '2.0.0-dev')
+      ..serve('a', '2.0.0');
 
     await d.appDir({'a': '<2.0.0'}).create();
     await expectResolves(result: {'a': '1.1.0'});
@@ -1673,33 +1604,30 @@
 
   test('prefer a stable version even if constraint mentions unstable',
       () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('a', '1.1.0');
-      builder.serve('a', '2.0.0-dev');
-      builder.serve('a', '2.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('a', '1.1.0')
+      ..serve('a', '2.0.0-dev')
+      ..serve('a', '2.0.0');
 
     await d.appDir({'a': '<=2.0.0-dev'}).create();
     await expectResolves(result: {'a': '1.1.0'});
   });
 
   test('use pre-release when desired', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('a', '1.1.0-dev');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('a', '1.1.0-dev');
 
     await d.appDir({'a': '^1.1.0-dev'}).create();
     await expectResolves(result: {'a': '1.1.0-dev'});
   });
 
   test('can upgrade from pre-release', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('a', '1.1.0-dev');
-      builder.serve('a', '1.1.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('a', '1.1.0-dev')
+      ..serve('a', '1.1.0');
 
     await d.appDir({'a': '^1.1.0-dev'}).create();
     await expectResolves(result: {'a': '1.1.0'});
@@ -1708,12 +1636,11 @@
   test('will use pre-release if depended on in stable release', () async {
     // This behavior is desired because a stable package has dependency on a
     // pre-release.
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {'b': '^1.0.0'});
-      builder.serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'});
-      builder.serve('b', '1.0.0');
-      builder.serve('b', '1.1.0-dev');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {'b': '^1.0.0'})
+      ..serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'})
+      ..serve('b', '1.0.0')
+      ..serve('b', '1.1.0-dev');
 
     await d.appDir({'a': '^1.0.0'}).create();
     await expectResolves(result: {
@@ -1723,12 +1650,11 @@
   });
 
   test('backtracks pre-release choice with direct dependency', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {'b': '^1.0.0'});
-      builder.serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'});
-      builder.serve('b', '1.0.0');
-      builder.serve('b', '1.1.0-dev');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {'b': '^1.0.0'})
+      ..serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'})
+      ..serve('b', '1.0.0')
+      ..serve('b', '1.1.0-dev');
 
     await d.appDir({
       'a': '^1.0.0',
@@ -1743,13 +1669,12 @@
   test('backtracking pre-release fails with indirect dependency', () async {
     // NOTE: This behavior is not necessarily desired.
     //       If feasible it might worth changing this behavior in the future.
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {'b': '^1.0.0'});
-      builder.serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'});
-      builder.serve('b', '1.0.0');
-      builder.serve('b', '1.1.0-dev');
-      builder.serve('c', '1.0.0', deps: {'b': '^1.0.0'});
-    });
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {'b': '^1.0.0'})
+      ..serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'})
+      ..serve('b', '1.0.0')
+      ..serve('b', '1.1.0-dev')
+      ..serve('c', '1.0.0', deps: {'b': '^1.0.0'});
 
     await d.appDir({
       'a': '^1.0.0',
@@ -1764,14 +1689,13 @@
 
   test('https://github.com/dart-lang/pub/issues/3057 regression', () async {
     // This used to cause an infinite loop.
-    await servePackages((builder) {
-      builder.serve('a', '0.12.0', deps: {});
-      builder.serve('b', '0.1.0', deps: {'c': '2.0.0'});
-      builder.serve('b', '0.9.0-1', deps: {'c': '^1.6.0'});
-      builder.serve('b', '0.10.0', deps: {'a': '1.0.0'});
-      builder.serve('b', '0.17.0', deps: {'a': '1.0.0'});
-      builder.serve('c', '2.0.1', deps: {});
-    });
+    await servePackages()
+      ..serve('a', '0.12.0', deps: {})
+      ..serve('b', '0.1.0', deps: {'c': '2.0.0'})
+      ..serve('b', '0.9.0-1', deps: {'c': '^1.6.0'})
+      ..serve('b', '0.10.0', deps: {'a': '1.0.0'})
+      ..serve('b', '0.17.0', deps: {'a': '1.0.0'})
+      ..serve('c', '2.0.1', deps: {});
 
     await d.appDir(
       {
@@ -1786,13 +1710,12 @@
   });
 
   test('https://github.com/dart-lang/pub/pull/3038 regression', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.1.0', deps: {'b': '^1.0.0'});
-      builder.serve('b', '1.0.0', deps: {'c': '^1.0.0'});
-      builder.serve('c', '0.9.0');
-      builder.serve('b', '1.1.0-alpha');
-      builder.serve('a', '1.0.0', deps: {'b': '^1.1.0-alpha'});
-    });
+    await servePackages()
+      ..serve('a', '1.1.0', deps: {'b': '^1.0.0'})
+      ..serve('b', '1.0.0', deps: {'c': '^1.0.0'})
+      ..serve('c', '0.9.0')
+      ..serve('b', '1.1.0-alpha')
+      ..serve('a', '1.0.0', deps: {'b': '^1.1.0-alpha'});
 
     await d.appDir({
       'a': '^1.0.0',
@@ -1803,11 +1726,10 @@
 
 void override() {
   test('chooses best version matching override constraint', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('a', '2.0.0');
-      builder.serve('a', '3.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('a', '2.0.0')
+      ..serve('a', '3.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -1821,11 +1743,10 @@
   });
 
   test('uses override as dependency', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('a', '2.0.0');
-      builder.serve('a', '3.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('a', '2.0.0')
+      ..serve('a', '3.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -1838,13 +1759,12 @@
   });
 
   test('ignores other constraints on overridden package', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('a', '2.0.0');
-      builder.serve('a', '3.0.0');
-      builder.serve('b', '1.0.0', deps: {'a': '1.0.0'});
-      builder.serve('c', '1.0.0', deps: {'a': '3.0.0'});
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('a', '2.0.0')
+      ..serve('a', '3.0.0')
+      ..serve('b', '1.0.0', deps: {'a': '1.0.0'})
+      ..serve('c', '1.0.0', deps: {'a': '3.0.0'});
 
     await d.dir(appPath, [
       d.pubspec({
@@ -1858,12 +1778,11 @@
   });
 
   test('backtracks on overidden package for its constraints', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0', deps: {'shared': 'any'});
-      builder.serve('a', '2.0.0', deps: {'shared': '1.0.0'});
-      builder.serve('shared', '1.0.0');
-      builder.serve('shared', '2.0.0');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0', deps: {'shared': 'any'})
+      ..serve('a', '2.0.0', deps: {'shared': '1.0.0'})
+      ..serve('shared', '1.0.0')
+      ..serve('shared', '2.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -1877,14 +1796,13 @@
   });
 
   test('override compatible with locked dependency', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
-      builder.serve('foo', '1.0.1', deps: {'bar': '1.0.1'});
-      builder.serve('foo', '1.0.2', deps: {'bar': '1.0.2'});
-      builder.serve('bar', '1.0.0');
-      builder.serve('bar', '1.0.1');
-      builder.serve('bar', '1.0.2');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+      ..serve('foo', '1.0.1', deps: {'bar': '1.0.1'})
+      ..serve('foo', '1.0.2', deps: {'bar': '1.0.2'})
+      ..serve('bar', '1.0.0')
+      ..serve('bar', '1.0.1')
+      ..serve('bar', '1.0.2');
 
     await d.appDir({'foo': '1.0.1'}).create();
     await expectResolves(result: {'foo': '1.0.1', 'bar': '1.0.1'});
@@ -1900,14 +1818,13 @@
   });
 
   test('override incompatible with locked dependency', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
-      builder.serve('foo', '1.0.1', deps: {'bar': '1.0.1'});
-      builder.serve('foo', '1.0.2', deps: {'bar': '1.0.2'});
-      builder.serve('bar', '1.0.0');
-      builder.serve('bar', '1.0.1');
-      builder.serve('bar', '1.0.2');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+      ..serve('foo', '1.0.1', deps: {'bar': '1.0.1'})
+      ..serve('foo', '1.0.2', deps: {'bar': '1.0.2'})
+      ..serve('bar', '1.0.0')
+      ..serve('bar', '1.0.1')
+      ..serve('bar', '1.0.2');
 
     await d.appDir({'foo': '1.0.1'}).create();
     await expectResolves(result: {'foo': '1.0.1', 'bar': '1.0.1'});
@@ -1923,10 +1840,9 @@
   });
 
   test('no version that matches override', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '2.0.0');
-      builder.serve('foo', '2.1.3');
-    });
+    await servePackages()
+      ..serve('foo', '2.0.0')
+      ..serve('foo', '2.1.3');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -1942,9 +1858,8 @@
   });
 
   test('overrides a bad source without error', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '0.0.0');
-    });
+    final server = await servePackages();
+    server.serve('foo', '0.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -1960,10 +1875,9 @@
   });
 
   test('overrides an unmatched SDK constraint', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '0.0.0', pubspec: {
-        'environment': {'sdk': '0.0.0'}
-      });
+    final server = await servePackages();
+    server.serve('foo', '0.0.0', pubspec: {
+      'environment': {'sdk': '0.0.0'}
     });
 
     await d.dir(appPath, [
@@ -1977,9 +1891,8 @@
   });
 
   test('overrides an unmatched root dependency', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '0.0.0', deps: {'myapp': '1.0.0'});
-    });
+    final server = await servePackages();
+    server.serve('foo', '0.0.0', deps: {'myapp': '1.0.0'});
 
     await d.dir(appPath, [
       d.pubspec({
@@ -1994,11 +1907,10 @@
 
   // Regression test for #1853
   test("overrides a locked package's dependency", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.2.3', deps: {'bar': '1.2.3'});
-      builder.serve('bar', '1.2.3');
-      builder.serve('bar', '0.0.1');
-    });
+    await servePackages()
+      ..serve('foo', '1.2.3', deps: {'bar': '1.2.3'})
+      ..serve('bar', '1.2.3')
+      ..serve('bar', '0.0.1');
 
     await d.appDir({'foo': 'any'}).create();
 
@@ -2018,12 +1930,11 @@
 
 void downgrade() {
   test('downgrades a dependency to the lowest matching version', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('foo', '2.0.0-dev');
-      builder.serve('foo', '2.0.0');
-      builder.serve('foo', '2.1.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('foo', '2.0.0-dev')
+      ..serve('foo', '2.0.0')
+      ..serve('foo', '2.1.0');
 
     await d.appDir({'foo': '2.1.0'}).create();
     await expectResolves(result: {'foo': '2.1.0'});
@@ -2035,12 +1946,11 @@
   test(
       'use earliest allowed prerelease if no stable versions match '
       'while downgrading', () async {
-    await servePackages((builder) {
-      builder.serve('a', '1.0.0');
-      builder.serve('a', '2.0.0-dev.1');
-      builder.serve('a', '2.0.0-dev.2');
-      builder.serve('a', '2.0.0-dev.3');
-    });
+    await servePackages()
+      ..serve('a', '1.0.0')
+      ..serve('a', '2.0.0-dev.1')
+      ..serve('a', '2.0.0-dev.2')
+      ..serve('a', '2.0.0-dev.3');
 
     await d.appDir({'a': '>=2.0.0-dev.1 <3.0.0'}).create();
     await expectResolves(result: {'a': '2.0.0-dev.1'}, downgrade: true);
@@ -2049,67 +1959,63 @@
 
 void features() {
   test("doesn't enable an opt-in feature by default", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'default': false,
             'dependencies': {'bar': '1.0.0'}
           }
         }
-      });
-      builder.serve('bar', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0');
 
     await d.appDir({'foo': '1.0.0'}).create();
     await expectResolves(result: {'foo': '1.0.0'});
   });
 
   test('enables an opt-out feature by default', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'default': true,
             'dependencies': {'bar': '1.0.0'}
           }
         }
-      });
-      builder.serve('bar', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0');
 
     await d.appDir({'foo': '1.0.0'}).create();
     await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'});
   });
 
   test('features are opt-out by default', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'dependencies': {'bar': '1.0.0'}
           }
         }
-      });
-      builder.serve('bar', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0');
 
     await d.appDir({'foo': '1.0.0'}).create();
     await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'});
   });
 
   test("enables an opt-in feature if it's required", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'default': false,
             'dependencies': {'bar': '1.0.0'}
           }
         }
-      });
-      builder.serve('bar', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0');
 
     await d.appDir({
       'foo': {
@@ -2121,16 +2027,15 @@
   });
 
   test("doesn't enable an opt-out feature if it's disabled", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'dependencies': {'bar': '1.0.0'}
           }
         }
-      });
-      builder.serve('bar', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0');
 
     await d.appDir({
       'foo': {
@@ -2142,22 +2047,21 @@
   });
 
   test('opting in takes precedence over opting out', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'dependencies': {'bar': '1.0.0'}
           }
         }
-      });
-      builder.serve('bar', '1.0.0');
-      builder.serve('baz', '1.0.0', deps: {
+      })
+      ..serve('bar', '1.0.0')
+      ..serve('baz', '1.0.0', deps: {
         'foo': {
           'version': '1.0.0',
           'features': {'stuff': true}
         }
       });
-    });
 
     await d.appDir({
       'foo': {
@@ -2171,21 +2075,20 @@
   });
 
   test('implicitly opting in takes precedence over opting out', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'dependencies': {'bar': '1.0.0'}
           }
         }
-      });
-      builder.serve('bar', '1.0.0');
-      builder.serve('baz', '1.0.0', deps: {
+      })
+      ..serve('bar', '1.0.0')
+      ..serve('baz', '1.0.0', deps: {
         'foo': {
           'version': '1.0.0',
         }
       });
-    });
 
     await d.appDir({
       'foo': {
@@ -2199,18 +2102,17 @@
   });
 
   test("doesn't select a version with an unavailable feature", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'default': false,
             'dependencies': {'bar': '1.0.0'}
           }
         }
-      });
-      builder.serve('foo', '1.1.0');
-      builder.serve('bar', '1.0.0');
-    });
+      })
+      ..serve('foo', '1.1.0')
+      ..serve('bar', '1.0.0');
 
     await d.appDir({
       'foo': {
@@ -2222,26 +2124,25 @@
   });
 
   test("doesn't select a version with an incompatible feature", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'default': false,
             'dependencies': {'bar': '1.0.0'}
           }
         }
-      });
-      builder.serve('foo', '1.1.0', pubspec: {
+      })
+      ..serve('foo', '1.1.0', pubspec: {
         'features': {
           'stuff': {
             'default': false,
             'dependencies': {'bar': '2.0.0'}
           }
         }
-      });
-      builder.serve('bar', '1.0.0');
-      builder.serve('bar', '2.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0')
+      ..serve('bar', '2.0.0');
 
     await d.appDir({
       'foo': {
@@ -2256,8 +2157,8 @@
   test(
       'backtracks if a feature is transitively incompatible with another '
       'feature', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'default': false,
@@ -2269,27 +2170,24 @@
             }
           }
         }
-      });
-      builder.serve('foo', '1.1.0', pubspec: {
+      })
+      ..serve('foo', '1.1.0', pubspec: {
         'features': {
           'stuff': {
             'default': false,
             'dependencies': {'bar': '1.0.0'}
           }
         }
-      });
-
-      builder.serve('bar', '1.0.0', pubspec: {
+      })
+      ..serve('bar', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'dependencies': {'baz': '1.0.0'}
           }
         }
-      });
-
-      builder.serve('baz', '1.0.0');
-      builder.serve('baz', '2.0.0');
-    });
+      })
+      ..serve('baz', '1.0.0')
+      ..serve('baz', '2.0.0');
 
     await d.appDir({
       'foo': {
@@ -2304,30 +2202,27 @@
 
   test("backtracks if a feature's dependencies are transitively incompatible",
       () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', pubspec: {
+    await servePackages()
+      ..serve('foo', '1.0.0', pubspec: {
         'features': {
           'stuff': {
             'default': false,
             'dependencies': {'bar': '1.0.0'}
           }
         }
-      });
-      builder.serve('foo', '1.1.0', pubspec: {
+      })
+      ..serve('foo', '1.1.0', pubspec: {
         'features': {
           'stuff': {
             'default': false,
             'dependencies': {'bar': '2.0.0'}
           }
         }
-      });
-
-      builder.serve('bar', '1.0.0', deps: {'baz': '1.0.0'});
-      builder.serve('bar', '2.0.0', deps: {'baz': '2.0.0'});
-
-      builder.serve('baz', '1.0.0');
-      builder.serve('baz', '2.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0', deps: {'baz': '1.0.0'})
+      ..serve('bar', '2.0.0', deps: {'baz': '2.0.0'})
+      ..serve('baz', '1.0.0')
+      ..serve('baz', '2.0.0');
 
     await d.appDir({
       'foo': {
@@ -2341,9 +2236,9 @@
   });
 
   test('disables a feature when it backtracks', () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {'myapp': '0.0.0'});
-      builder.serve('foo', '1.1.0', deps: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {'myapp': '0.0.0'})
+      ..serve('foo', '1.1.0', deps: {
         // This is a transitively incompatible dependency with myapp, which will
         // force the solver to backtrack and unselect foo 1.1.0.
         'bar': '1.0.0',
@@ -2351,15 +2246,11 @@
           'version': '0.0.0',
           'features': {'stuff': true}
         }
-      });
-
-      builder.serve('bar', '1.0.0', deps: {'baz': '2.0.0'});
-
-      builder.serve('baz', '1.0.0');
-      builder.serve('baz', '2.0.0');
-
-      builder.serve('qux', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0', deps: {'baz': '2.0.0'})
+      ..serve('baz', '1.0.0')
+      ..serve('baz', '2.0.0')
+      ..serve('qux', '1.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -2377,10 +2268,9 @@
   });
 
   test("the root package's features are opt-out by default", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('bar', '1.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('bar', '1.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -2397,10 +2287,9 @@
   });
 
   test("the root package's features can be made opt-in", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-      builder.serve('bar', '1.0.0');
-    });
+    await servePackages()
+      ..serve('foo', '1.0.0')
+      ..serve('bar', '1.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -2423,14 +2312,13 @@
   // increases the total number of dependencies.
   test("the root package's features can't be disabled by dependencies",
       () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {
         'myapp': {
           'features': {'stuff': false}
         }
-      });
-      builder.serve('bar', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -2447,14 +2335,13 @@
   });
 
   test("the root package's features can be enabled by dependencies", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0', deps: {
+    await servePackages()
+      ..serve('foo', '1.0.0', deps: {
         'myapp': {
           'features': {'stuff': true}
         }
-      });
-      builder.serve('bar', '1.0.0');
-    });
+      })
+      ..serve('bar', '1.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -2472,9 +2359,8 @@
   });
 
   test("resolution fails because a feature doesn't exist", () async {
-    await servePackages((builder) {
-      builder.serve('foo', '1.0.0');
-    });
+    final server = await servePackages();
+    server.serve('foo', '1.0.0');
 
     await d.dir(appPath, [
       d.pubspec({
@@ -2494,17 +2380,16 @@
 
   group('an "if available" dependency', () {
     test('enables an opt-in feature', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0', pubspec: {
           'features': {
             'stuff': {
               'default': false,
               'dependencies': {'bar': '1.0.0'}
             }
           }
-        });
-        builder.serve('bar', '1.0.0');
-      });
+        })
+        ..serve('bar', '1.0.0');
 
       await d.appDir({
         'foo': {
@@ -2516,9 +2401,8 @@
     });
 
     test("is compatible with a feature that doesn't exist", () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0');
-      });
+      final server = await servePackages();
+      server.serve('foo', '1.0.0');
 
       await d.appDir({
         'foo': {
@@ -2537,14 +2421,13 @@
 
     group('succeeds when', () {
       test('a Dart SDK constraint is matched', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.0.0', pubspec: {
-            'features': {
-              'stuff': {
-                'environment': {'sdk': '^0.1.0'}
-              }
+        final server = await servePackages();
+        server.serve('foo', '1.0.0', pubspec: {
+          'features': {
+            'stuff': {
+              'environment': {'sdk': '^0.1.0'}
             }
-          });
+          }
         });
 
         await d.dir(appPath, [
@@ -2558,14 +2441,13 @@
       });
 
       test('a Flutter SDK constraint is matched', () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.0.0', pubspec: {
-            'features': {
-              'stuff': {
-                'environment': {'flutter': '^1.0.0'}
-              }
+        final server = await servePackages();
+        server.serve('foo', '1.0.0', pubspec: {
+          'features': {
+            'stuff': {
+              'environment': {'flutter': '^1.0.0'}
             }
-          });
+          }
         });
 
         await d.dir(appPath, [
@@ -2583,16 +2465,15 @@
 
     group("doesn't choose a version because", () {
       test("a Dart SDK constraint isn't matched", () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.0.0');
-          builder.serve('foo', '1.1.0', pubspec: {
+        await servePackages()
+          ..serve('foo', '1.0.0')
+          ..serve('foo', '1.1.0', pubspec: {
             'features': {
               'stuff': {
                 'environment': {'sdk': '0.0.1'}
               }
             }
           });
-        });
 
         await d.dir(appPath, [
           d.pubspec({
@@ -2605,16 +2486,15 @@
       });
 
       test("Flutter isn't available", () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.0.0');
-          builder.serve('foo', '1.1.0', pubspec: {
+        await servePackages()
+          ..serve('foo', '1.0.0')
+          ..serve('foo', '1.1.0', pubspec: {
             'features': {
               'stuff': {
                 'environment': {'flutter': '1.0.0'}
               }
             }
           });
-        });
 
         await d.dir(appPath, [
           d.pubspec({
@@ -2627,16 +2507,15 @@
       });
 
       test("a Flutter SDK constraint isn't matched", () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.0.0');
-          builder.serve('foo', '1.1.0', pubspec: {
+        await servePackages()
+          ..serve('foo', '1.0.0')
+          ..serve('foo', '1.1.0', pubspec: {
             'features': {
               'stuff': {
                 'environment': {'flutter': '^2.0.0'}
               }
             }
           });
-        });
 
         await d.dir(appPath, [
           d.pubspec({
@@ -2653,14 +2532,13 @@
 
     group('resolution fails because', () {
       test("a Dart SDK constraint isn't matched", () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.0.0', pubspec: {
-            'features': {
-              'stuff': {
-                'environment': {'sdk': '0.0.1'}
-              }
+        final server = await servePackages();
+        server.serve('foo', '1.0.0', pubspec: {
+          'features': {
+            'stuff': {
+              'environment': {'sdk': '0.0.1'}
             }
-          });
+          }
         });
 
         await d.dir(appPath, [
@@ -2677,14 +2555,13 @@
       });
 
       test("Flutter isn't available", () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.0.0', pubspec: {
-            'features': {
-              'stuff': {
-                'environment': {'flutter': '1.0.0'}
-              }
+        final server = await servePackages();
+        server.serve('foo', '1.0.0', pubspec: {
+          'features': {
+            'stuff': {
+              'environment': {'flutter': '1.0.0'}
             }
-          });
+          }
         });
 
         await d.dir(appPath, [
@@ -2700,14 +2577,13 @@
       });
 
       test("a Flutter SDK constraint isn't matched", () async {
-        await servePackages((builder) {
-          builder.serve('foo', '1.0.0', pubspec: {
-            'features': {
-              'stuff': {
-                'environment': {'flutter': '^2.0.0'}
-              }
+        final server = await servePackages();
+        server.serve('foo', '1.0.0', pubspec: {
+          'features': {
+            'stuff': {
+              'environment': {'flutter': '^2.0.0'}
             }
-          });
+          }
         });
 
         await d.dir(appPath, [
@@ -2727,8 +2603,8 @@
 
   group('with overlapping dependencies', () {
     test('can enable extra features', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0', pubspec: {
           'dependencies': {'bar': '1.0.0'},
           'features': {
             'stuff': {
@@ -2740,19 +2616,16 @@
               }
             }
           }
-        });
-
-        builder.serve('bar', '1.0.0', pubspec: {
+        })
+        ..serve('bar', '1.0.0', pubspec: {
           'features': {
             'stuff': {
               'default': false,
               'dependencies': {'baz': '1.0.0'}
             }
           }
-        });
-
-        builder.serve('baz', '1.0.0');
-      });
+        })
+        ..serve('baz', '1.0.0');
 
       await d.appDir({
         'foo': {'version': '1.0.0'}
@@ -2770,8 +2643,8 @@
     });
 
     test("can't disable features", () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0', pubspec: {
           'dependencies': {
             'bar': {
               'version': '1.0.0',
@@ -2788,19 +2661,16 @@
               }
             }
           }
-        });
-
-        builder.serve('bar', '1.0.0', pubspec: {
+        })
+        ..serve('bar', '1.0.0', pubspec: {
           'features': {
             'stuff': {
               'default': true,
               'dependencies': {'baz': '1.0.0'}
             }
           }
-        });
-
-        builder.serve('baz', '1.0.0');
-      });
+        })
+        ..serve('baz', '1.0.0');
 
       await d.appDir({
         'foo': {
@@ -2815,8 +2685,8 @@
 
   group('with required features', () {
     test('enables those features', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0', pubspec: {
           'features': {
             'main': {
               'default': false,
@@ -2831,10 +2701,9 @@
               'dependencies': {'baz': '1.0.0'}
             }
           }
-        });
-        builder.serve('bar', '1.0.0');
-        builder.serve('baz', '1.0.0');
-      });
+        })
+        ..serve('bar', '1.0.0')
+        ..serve('baz', '1.0.0');
 
       await d.appDir({
         'foo': {
@@ -2847,8 +2716,8 @@
     });
 
     test('enables those features by default', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0', pubspec: {
           'features': {
             'main': {
               'requires': ['required1', 'required2']
@@ -2862,10 +2731,9 @@
               'dependencies': {'baz': '1.0.0'}
             }
           }
-        });
-        builder.serve('bar', '1.0.0');
-        builder.serve('baz', '1.0.0');
-      });
+        })
+        ..serve('bar', '1.0.0')
+        ..serve('baz', '1.0.0');
 
       await d.appDir({'foo': '1.0.0'}).create();
       await expectResolves(
@@ -2873,8 +2741,8 @@
     });
 
     test("doesn't enable those features if it's disabled", () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0', pubspec: {
           'features': {
             'main': {
               'requires': ['required']
@@ -2884,9 +2752,8 @@
               'dependencies': {'bar': '1.0.0'}
             }
           }
-        });
-        builder.serve('bar', '1.0.0');
-      });
+        })
+        ..serve('bar', '1.0.0');
 
       await d.appDir({
         'foo': {
@@ -2899,8 +2766,8 @@
 
     test("enables those features even if they'd otherwise be disabled",
         () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0', pubspec: {
           'features': {
             'main': {
               'requires': ['required']
@@ -2910,9 +2777,8 @@
               'dependencies': {'bar': '1.0.0'}
             }
           }
-        });
-        builder.serve('bar', '1.0.0');
-      });
+        })
+        ..serve('bar', '1.0.0');
 
       await d.appDir({
         'foo': {
@@ -2924,8 +2790,8 @@
     });
 
     test('enables features transitively', () async {
-      await servePackages((builder) {
-        builder.serve('foo', '1.0.0', pubspec: {
+      await servePackages()
+        ..serve('foo', '1.0.0', pubspec: {
           'features': {
             'main': {
               'requires': ['required1']
@@ -2939,9 +2805,8 @@
               'dependencies': {'bar': '1.0.0'}
             }
           }
-        });
-        builder.serve('bar', '1.0.0');
-      });
+        })
+        ..serve('bar', '1.0.0');
 
       await d.appDir({
         'foo': {
@@ -2974,11 +2839,11 @@
 ///
 /// If [downgrade] is `true`, this runs "pub downgrade" instead of "pub get".
 Future expectResolves(
-    {Map result,
+    {Map? result,
     error,
     output,
-    int tries,
-    Map<String, String> environment,
+    int? tries,
+    Map<String, String>? environment,
     bool downgrade = false}) async {
   await runPub(
       args: [downgrade ? 'downgrade' : 'get'],
@@ -3009,7 +2874,7 @@
       // If the dep uses the default hosted source, grab it from the test
       // package server rather than pub.dartlang.org.
       dep = registry.hosted
-          .refFor(dep.name, url: Uri.parse(globalPackageServer.url))
+          .refFor(dep.name, url: Uri.parse(globalServer.url))
           .withConstraint(dep.constraint);
     }
     expect(dep.allows(id), isTrue, reason: 'Expected $id to match $dep.');
@@ -3020,14 +2885,12 @@
 
 void regressions() {
   test('reformatRanges with a build', () async {
-    await servePackages((b) {
-      b.serve('integration_test', '1.0.1',
-          deps: {'vm_service': '>= 4.2.0 <6.0.0'});
-      b.serve('integration_test', '1.0.2+2',
-          deps: {'vm_service': '>= 4.2.0 <7.0.0'});
-
-      b.serve('vm_service', '7.3.0');
-    });
+    await servePackages()
+      ..serve('integration_test', '1.0.1',
+          deps: {'vm_service': '>= 4.2.0 <6.0.0'})
+      ..serve('integration_test', '1.0.2+2',
+          deps: {'vm_service': '>= 4.2.0 <7.0.0'})
+      ..serve('vm_service', '7.3.0');
     await d.appDir({'integration_test': '^1.0.2'}).create();
     await expectResolves(
       error: contains(
diff --git a/tool/extract_all_pub_dev.dart b/tool/extract_all_pub_dev.dart
index 8d7f049..f96dc5a 100644
--- a/tool/extract_all_pub_dev.dart
+++ b/tool/extract_all_pub_dev.dart
@@ -2,8 +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.
 
-// @dart=2.10
-
 /// This is a manual test that can be run to test the .tar.gz decoding.
 /// It will save progress in [statusFileName] such that it doesn't have to be
 /// finished in a single run.
@@ -33,7 +31,7 @@
 
 Future<void> main() async {
   var alreadyDonePackages = <String>{};
-  var failures = <Map<String, dynamic>>[];
+  var failures = <Map<String, dynamic>?>[];
   if (fileExists(statusFilename)) {
     final json = jsonDecode(readTextFile(statusFilename));
     for (final packageName in json['packages'] ?? []) {
diff --git a/tool/test-bin/pub_command_runner.dart b/tool/test-bin/pub_command_runner.dart
index 52eaf73..2be51e8 100644
--- a/tool/test-bin/pub_command_runner.dart
+++ b/tool/test-bin/pub_command_runner.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// A trivial embedding of the pub command. Used from tests.
-// @dart = 2.11
 import 'dart:convert';
 import 'dart:io';
 
@@ -17,7 +16,7 @@
 final _LoggingAnalytics loggingAnalytics = _LoggingAnalytics();
 
 class Runner extends CommandRunner<int> {
-  ArgResults _options;
+  late ArgResults _options;
 
   Runner() : super('pub_command_runner', 'Tests the embeddable pub command.') {
     final analytics = Platform.environment['_PUB_LOG_ANALYTICS'] == 'true'
@@ -60,7 +59,7 @@
   bool get firstRun => false;
 
   @override
-  Future sendScreenView(String viewName, {Map<String, String> parameters}) {
+  Future sendScreenView(String viewName, {Map<String, String>? parameters}) {
     parameters ??= <String, String>{};
     parameters['viewName'] = viewName;
     return _log('screenView', parameters);
@@ -68,7 +67,7 @@
 
   @override
   Future sendEvent(String category, String action,
-      {String label, int value, Map<String, String> parameters}) {
+      {String? label, int? value, Map<String, String>? parameters}) {
     parameters ??= <String, String>{};
     return _log(
         'event',
@@ -82,7 +81,7 @@
 
   @override
   Future sendTiming(String variableName, int time,
-      {String category, String label}) {
+      {String? category, String? label}) {
     return _log('timing', {
       'variableName': variableName,
       'time': time,