Don't allow non-null-safety constraints in the root pubspec (#3800)

diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index afd6c8a..d18f6e2 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -19,6 +19,7 @@
 import 'exceptions.dart';
 import 'executable.dart';
 import 'io.dart';
+import 'language_version.dart';
 import 'lock_file.dart';
 import 'log.dart' as log;
 import 'package.dart';
@@ -938,21 +939,21 @@
   /// We don't allow unknown sdks.
   void _checkSdkConstraint(Pubspec pubspec) {
     final dartSdkConstraint = pubspec.dartSdkConstraint.effectiveConstraint;
-    if (dartSdkConstraint is! VersionRange || dartSdkConstraint.min == null) {
-      // Suggest an sdk constraint giving the same language version as the
-      // current sdk.
-      var suggestedConstraint = VersionConstraint.compatibleWith(
-        Version(sdk.version.major, sdk.version.minor, 0),
+    // Suggest an sdk constraint giving the same language version as the
+    // current sdk.
+    var suggestedConstraint = VersionConstraint.compatibleWith(
+      Version(sdk.version.major, sdk.version.minor, 0),
+    );
+    // But if somehow that doesn't work, we fallback to safe sanity, mostly
+    // important for tests, or if we jump to 3.x without patching this code.
+    if (!suggestedConstraint.allows(sdk.version)) {
+      suggestedConstraint = VersionRange(
+        min: sdk.version,
+        max: sdk.version.nextBreaking,
+        includeMin: true,
       );
-      // But if somehow that doesn't work, we fallback to safe sanity, mostly
-      // important for tests, or if we jump to 3.x without patching this code.
-      if (!suggestedConstraint.allows(sdk.version)) {
-        suggestedConstraint = VersionRange(
-          min: sdk.version,
-          max: sdk.version.nextBreaking,
-          includeMin: true,
-        );
-      }
+    }
+    if (dartSdkConstraint is! VersionRange || dartSdkConstraint.min == null) {
       throw DataException('''
 $pubspecPath has no lower-bound SDK constraint.
 You should edit $pubspecPath to contain an SDK constraint:
@@ -963,6 +964,24 @@
 See https://dart.dev/go/sdk-constraint
 ''');
     }
+    if (!LanguageVersion.fromSdkConstraint(dartSdkConstraint)
+        .supportsNullSafety) {
+      throw DataException('''
+The lower bound of "sdk: '$dartSdkConstraint'" must be 2.12.0'
+or higher to enable null safety.
+
+The current version of the Dart SDK (${sdk.version}) does not support non-null
+safety code.
+
+Consider using an older, compatible Dart SDK or try the following sdk
+constraint:
+
+environment:
+  sdk: '${suggestedConstraint.asCompatibleWithIfPossible()}'
+
+For details, see https://dart.dev/null-safety
+''');
+    }
     for (final sdk in pubspec.sdkConstraints.keys) {
       if (!sdks.containsKey(sdk)) {
         final environment = pubspec.fields.nodes['environment'] as YamlMap;
diff --git a/lib/src/sdk.dart b/lib/src/sdk.dart
index 7da78c1..bc1c6c9 100644
--- a/lib/src/sdk.dart
+++ b/lib/src/sdk.dart
@@ -31,9 +31,6 @@
   /// The SDK's version number, or `null` if the SDK is unavailable.
   Version? get version;
 
-  /// The version of pub that added support for this SDK.
-  Version get firstPubVersion;
-
   /// A message to indicate to the user how to make this SDK available.
   ///
   /// This is printed after a version solve where the SDK wasn't found. It may
diff --git a/lib/src/sdk/dart.dart b/lib/src/sdk/dart.dart
index 75cf6f9..19af627 100644
--- a/lib/src/sdk/dart.dart
+++ b/lib/src/sdk/dart.dart
@@ -20,8 +20,6 @@
   bool get isAvailable => true;
   @override
   String? get installMessage => null;
-  @override
-  Version get firstPubVersion => Version.none;
 
   static final String _rootDirectory = () {
     if (runningFromDartRepo) return p.join(dartRepoRoot, 'sdk');
diff --git a/lib/src/sdk/flutter.dart b/lib/src/sdk/flutter.dart
index c9f1914..2151e87 100644
--- a/lib/src/sdk/flutter.dart
+++ b/lib/src/sdk/flutter.dart
@@ -15,8 +15,6 @@
   String get name => 'Flutter';
   @override
   bool get isAvailable => _isAvailable;
-  @override
-  Version get firstPubVersion => Version.parse('1.19.0');
 
   // We only consider the Flutter SDK to present if we find a root directory
   // and the root directory contains a valid 'version' file.
diff --git a/lib/src/sdk/fuchsia.dart b/lib/src/sdk/fuchsia.dart
index 3b884a4..e0f551b 100644
--- a/lib/src/sdk/fuchsia.dart
+++ b/lib/src/sdk/fuchsia.dart
@@ -15,8 +15,6 @@
   String get name => 'Fuchsia';
   @override
   bool get isAvailable => _isAvailable;
-  @override
-  Version get firstPubVersion => Version.parse('2.0.0-dev.51.0');
 
   static final bool _isAvailable = _rootDirectory != null;
   static final String? _rootDirectory =
diff --git a/lib/src/validator.dart b/lib/src/validator.dart
index 5a03d7b..6fcab2a 100644
--- a/lib/src/validator.dart
+++ b/lib/src/validator.dart
@@ -23,7 +23,6 @@
 import 'validator/flutter_constraint.dart';
 import 'validator/flutter_plugin_format.dart';
 import 'validator/gitignore.dart';
-import 'validator/language_version.dart';
 import 'validator/leak_detection.dart';
 import 'validator/license.dart';
 import 'validator/name.dart';
@@ -156,7 +155,6 @@
       StrictDependenciesValidator(),
       FlutterConstraintValidator(),
       FlutterPluginFormatValidator(),
-      LanguageVersionValidator(),
       RelativeVersionNumberingValidator(),
       PubspecTypoValidator(),
       LeakDetectionValidator(),
diff --git a/lib/src/validator/dependency.dart b/lib/src/validator/dependency.dart
index 939d9be..ebfa101 100644
--- a/lib/src/validator/dependency.dart
+++ b/lib/src/validator/dependency.dart
@@ -10,18 +10,11 @@
 import '../log.dart' as log;
 import '../package_name.dart';
 import '../sdk.dart';
-import '../source/git.dart';
 import '../source/hosted.dart';
 import '../source/path.dart';
 import '../source/sdk.dart';
 import '../validator.dart';
 
-/// The first Dart SDK version that supported caret constraints.
-final _firstCaretVersion = Version.parse('1.8.0-dev.3.0');
-
-/// The first Dart SDK version that supported Git path dependencies.
-final _firstGitPathVersion = Version.parse('2.0.0-dev.1.0');
-
 /// A validator that validates a package's dependencies.
 class DependencyValidator extends Validator {
   @override
@@ -38,11 +31,6 @@
         errors.add('Unknown SDK "$identifier" for dependency "${dep.name}".');
         return;
       }
-
-      validateSdkConstraint(
-        sdk.firstPubVersion,
-        "Older versions of pub don't support the ${sdk.name} SDK.",
-      );
     }
 
     /// Warn that dependencies should use the hosted source.
@@ -195,14 +183,6 @@
           warnAboutSdkSource(dependency);
         } else if (dependency.source is! HostedSource) {
           await warnAboutSource(dependency);
-
-          final description = dependency.description;
-          if (description is GitDescription && description.path != '.') {
-            validateSdkConstraint(
-              _firstGitPathVersion,
-              "Older versions of pub don't support Git path dependencies.",
-            );
-          }
         } else {
           if (constraint.isAny) {
             warnAboutNoConstraint(dependency);
@@ -224,12 +204,5 @@
     }
 
     await validateDependencies(entrypoint.root.pubspec.dependencies.values);
-
-    if (hasCaretDep) {
-      validateSdkConstraint(
-        _firstCaretVersion,
-        "Older versions of pub don't support ^ version constraints.",
-      );
-    }
   }
 }
diff --git a/lib/src/validator/language_version.dart b/lib/src/validator/language_version.dart
deleted file mode 100644
index ab2d868..0000000
--- a/lib/src/validator/language_version.dart
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2020, 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:async';
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:path/path.dart' as p;
-import 'package:stack_trace/stack_trace.dart';
-
-import '../dart.dart';
-import '../language_version.dart';
-import '../log.dart' as log;
-import '../utils.dart';
-import '../validator.dart';
-
-/// Validates that libraries do not opt into newer language versions than what
-/// they declare in their pubspec.
-class LanguageVersionValidator extends Validator {
-  @override
-  Future validate() async {
-    var packagePath = p.normalize(p.absolute(entrypoint.root.dir));
-    final analysisContextManager = AnalysisContextManager(packagePath);
-
-    final declaredLanguageVersion = entrypoint.root.pubspec.languageVersion;
-
-    for (final path in ['lib', 'bin'].expand((path) {
-      return filesBeneath(path, recursive: true)
-          .where((file) => p.extension(file) == '.dart');
-    })) {
-      CompilationUnit unit;
-      try {
-        unit = analysisContextManager.parse(path);
-      } on AnalyzerErrorGroup catch (e, s) {
-        // Ignore files that do not parse.
-        log.fine(getErrorMessage(e));
-        log.fine(Chain.forTrace(s).terse);
-        continue;
-      }
-
-      final unitLanguageVersionToken = unit.languageVersionToken;
-      if (unitLanguageVersionToken != null) {
-        final unitLanguageVersion =
-            LanguageVersion.fromLanguageVersionToken(unitLanguageVersionToken);
-        if (unitLanguageVersion > declaredLanguageVersion) {
-          final relativePath = p.relative(path);
-          errors.add('$relativePath is declaring language version '
-              '$unitLanguageVersion that is newer than the SDK '
-              'constraint $declaredLanguageVersion declared in '
-              '`pubspec.yaml`.');
-        }
-      }
-    }
-  }
-}
diff --git a/lib/src/validator/sdk_constraint.dart b/lib/src/validator/sdk_constraint.dart
index 729981e..c95cd91 100644
--- a/lib/src/validator/sdk_constraint.dart
+++ b/lib/src/validator/sdk_constraint.dart
@@ -6,7 +6,6 @@
 
 import 'package:pub_semver/pub_semver.dart';
 
-import '../sdk.dart';
 import '../validator.dart';
 
 /// A validator of the SDK constraint.
@@ -62,15 +61,5 @@
 ''');
       }
     }
-
-    for (var sdk in sdks.values) {
-      if (sdk.identifier == 'dart') continue;
-      if (entrypoint.root.pubspec.sdkConstraints.containsKey(sdk.identifier)) {
-        validateSdkConstraint(
-          sdk.firstPubVersion,
-          "Older versions of pub don't support ${sdk.name} SDK constraints.",
-        );
-      }
-    }
   }
 }
diff --git a/test/dart3_sdk_constraint_hack_test.dart b/test/dart3_sdk_constraint_hack_test.dart
index e8e18ab..5771ff6 100644
--- a/test/dart3_sdk_constraint_hack_test.dart
+++ b/test/dart3_sdk_constraint_hack_test.dart
@@ -2,6 +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.
 
+import 'package:pub/src/exit_codes.dart';
 import 'package:test/test.dart';
 
 import 'descriptor.dart' as d;
@@ -18,9 +19,10 @@
 
     await pubGet(
       error: contains(
-        'Because myapp doesn\'t support null safety, version solving failed',
+        'The current version of the Dart SDK (3.5.0) does not support non-null\nsafety code.',
       ),
       environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
+      exitCode: DATA,
     );
   });
   test('The bound of ">=2.12.0 <3.1.0" is not modified', () async {
@@ -49,9 +51,10 @@
 
     await pubGet(
       error: contains(
-        'Because myapp doesn\'t support null safety, version solving failed',
+        'The current version of the Dart SDK (3.5.0) does not support non-null\nsafety code.',
       ),
       environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
+      exitCode: DATA,
     );
   });
 
@@ -65,9 +68,10 @@
 
     await pubGet(
       error: contains(
-        'Because myapp doesn\'t support null safety, version solving failed',
+        'The current version of the Dart SDK (3.5.0) does not support non-null\nsafety code.',
       ),
       environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
+      exitCode: DATA,
     );
   });
 
diff --git a/test/get/sdk_constraint_required_test.dart b/test/get/sdk_constraint_required_test.dart
index 992abcc..50c6420 100644
--- a/test/get/sdk_constraint_required_test.dart
+++ b/test/get/sdk_constraint_required_test.dart
@@ -34,4 +34,43 @@
       d.nothing('.dart_tool/package_config.json'),
     ]).validate();
   });
+
+  test('pub get fails with an non-null-safety SDK constraint', () async {
+    await d.dir(appPath, [
+      d.rawPubspec(
+        {
+          'name': 'myapp',
+          'environment': {'sdk': '>=2.9.0 <4.0.0'}
+        },
+      ),
+    ]).create();
+
+    await pubGet(
+      error: '''
+The lower bound of "sdk: '>=2.9.0 <4.0.0'" must be 2.12.0'
+or higher to enable null safety.
+
+The current version of the Dart SDK (3.1.2+3) does not support non-null
+safety code.
+
+Consider using an older, compatible Dart SDK or try the following sdk
+constraint:
+
+environment:
+  sdk: '^3.1.0'
+
+For details, see https://dart.dev/null-safety
+''',
+      exitCode: exit_codes.DATA,
+    );
+
+    await d.dir(appPath, [
+      // The lockfile should not be created.
+      d.nothing('pubspec.lock'),
+      // The "packages" directory should not have been generated.
+      d.nothing('packages'),
+      // The package config file should not have been created.
+      d.nothing('.dart_tool/package_config.json'),
+    ]).validate();
+  });
 }
diff --git a/test/hosted/short_syntax_test.dart b/test/hosted/short_syntax_test.dart
index 6ea6851..eb1003f 100644
--- a/test/hosted/short_syntax_test.dart
+++ b/test/hosted/short_syntax_test.dart
@@ -18,7 +18,7 @@
       'foo',
       '1.2.3',
       pubspec: {
-        'environment': {'sdk': '^2.0.0'}
+        'environment': {'sdk': '^2.12.0'}
       },
     );
   });
@@ -73,15 +73,11 @@
           deps: {
             'foo': {'hosted': 'foo', 'version': '^1.2.3'}
           },
-          sdk: '^2.0.0',
+          sdk: '^2.14.0',
         ),
       ]).create();
 
-      await pubCommand(
-        command,
-        exitCode: 0,
-        environment: {'_PUB_TEST_SDK_VERSION': '2.15.0'},
-      );
+      await pubCommand(command);
 
       final lockFile = loadYaml(
         await File(p.join(d.sandbox, appPath, 'pubspec.lock')).readAsString(),
diff --git a/test/must_pub_get_test.dart b/test/must_pub_get_test.dart
index 7663401..4eace86 100644
--- a/test/must_pub_get_test.dart
+++ b/test/must_pub_get_test.dart
@@ -258,7 +258,7 @@
           'foo',
           '3.0.0',
           pubspec: {
-            'environment': {'sdk': '>=1.0.0 <2.0.0'}
+            'environment': {'sdk': '>=3.0.0 <3.1.0'}
           },
         );
 
@@ -267,12 +267,12 @@
             'name': 'myapp',
             'dependencies': {'foo': '3.0.0'},
             'environment': {
-              'sdk': '>=1.0.0 <2.0.0',
+              'sdk': '>=3.0.0 <3.1.0',
             },
           }),
         ]).create();
 
-        await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.2.3+4'});
+        await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '3.0.0'});
       });
 
       _requiresPubGet("Dart 3.1.2+3 is incompatible with your dependencies' "
diff --git a/test/run/enable_experiments_test.dart b/test/run/enable_experiments_test.dart
deleted file mode 100644
index a21fee3..0000000
--- a/test/run/enable_experiments_test.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2014, 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:test/test.dart';
-
-import '../descriptor.dart' as d;
-import '../test_pub.dart';
-
-void main() {
-  test('Succeeds running experimental code.', () async {
-    await d.dir(appPath, [
-      d.pubspec({
-        'name': 'myapp',
-        'environment': {'sdk': '>=2.10.0 <=3.0.0'},
-      }),
-      d.dir('bin', [
-        d.file('script.dart', '''
-  main() {
-    int? a = int.tryParse('123');
-  }
-''')
-      ])
-    ]).create();
-    await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '2.10.0'});
-    await runPub(
-      args: ['run', '--enable-experiment=non-nullable', 'bin/script.dart'],
-      environment: {'_PUB_TEST_SDK_VERSION': '2.10.0'},
-    );
-  });
-}
diff --git a/test/validator/analyze_test.dart b/test/validator/analyze_test.dart
index a20f4cd..1ce8b4f 100644
--- a/test/validator/analyze_test.dart
+++ b/test/validator/analyze_test.dart
@@ -7,50 +7,30 @@
 
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
-
-Future<void> expectValidation(
-  error,
-  int exitCode, {
-  List<String> extraArgs = const [],
-  Map<String, String> environment = const {},
-  String? workingDirectory,
-}) async {
-  await runPub(
-    error: error,
-    args: ['publish', '--dry-run', ...extraArgs],
-    environment: {'_PUB_TEST_SDK_VERSION': '1.12.0', ...environment},
-    workingDirectory: workingDirectory ?? d.path(appPath),
-    exitCode: exitCode,
-  );
-}
+import 'utils.dart';
 
 void main() {
   test('should consider a package valid if it contains no warnings or errors',
       () async {
     await d.dir(appPath, [
-      d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'),
+      d.validPubspec(),
       d.file('LICENSE', 'Eh, do what you want.'),
       d.file('README.md', "This package isn't real."),
       d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
       d.dir('lib', [d.file('test_pkg.dart', 'int i = 1;')])
     ]).create();
-
-    await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
-    await expectValidation(contains('Package has 0 warnings.'), 0);
+    await expectValidation();
   });
 
   test('should handle having no code in the analyzed directories', () async {
     await d.dir(appPath, [
-      d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'),
+      d.validPubspec(),
       d.file('LICENSE', 'Eh, do what you want.'),
       d.file('README.md', "This package isn't real."),
       d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
     ]).create();
 
-    await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
-    await expectValidation(contains('Package has 0 warnings.'), 0);
+    await expectValidation();
   });
 
   test(
@@ -59,7 +39,7 @@
     await d.dir(appPath, [
       d.libPubspec(
         'test_pkg', '1.0.0',
-        sdk: '>=1.8.0 <=2.0.0',
+        sdk: '^3.0.0',
         // Using http where https is recommended.
         extras: {'repository': 'http://repo.org/'},
       ),
@@ -73,16 +53,14 @@
 ''')
     ]).create();
 
-    await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
     await expectValidation(
-      allOf([
+      error: allOf([
         contains(
           "The 'http' protocol shouldn't be used because it isn't secure. Try using a secure protocol, such as 'https'.",
         ),
         contains('Package has 1 warning.'),
       ]),
-      DATA,
+      exitCode: DATA,
     );
   });
 
@@ -90,7 +68,7 @@
       'should consider a package valid even if it contains errors in the example/ sub-folder',
       () async {
     await d.dir(appPath, [
-      d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'),
+      d.validPubspec(),
       d.file('LICENSE', 'Eh, do what you want.'),
       d.file('README.md', "This package isn't real."),
       d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
@@ -104,16 +82,14 @@
       ])
     ]).create();
 
-    await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
-    await expectValidation(contains('Package has 0 warnings.'), 0);
+    await expectValidation();
   });
 
   test(
       'should warn if package contains errors in bin/, and works with --directory',
       () async {
     await d.dir(appPath, [
-      d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'),
+      d.validPubspec(),
       d.file('LICENSE', 'Eh, do what you want.'),
       d.file('README.md', "This package isn't real."),
       d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
@@ -126,17 +102,15 @@
       ])
     ]).create();
 
-    await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
     await expectValidation(
-      allOf([
+      error: allOf([
         contains('`dart analyze` found the following issue(s):'),
         contains('Analyzing lib, bin, pubspec.yaml...'),
         contains('error -'),
         contains("Expected to find '}'."),
         contains('Package has 1 warning.')
       ]),
-      DATA,
+      exitCode: DATA,
       extraArgs: ['--directory', appPath],
       workingDirectory: d.sandbox,
     );
@@ -144,7 +118,7 @@
 
   test('should warn if package contains infos in test folder', () async {
     await d.dir(appPath, [
-      d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'),
+      d.validPubspec(),
       d.file('LICENSE', 'Eh, do what you want.'),
       d.file('README.md', "This package isn't real."),
       d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
@@ -158,17 +132,15 @@
       ]),
     ]).create();
 
-    await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'});
-
     await expectValidation(
-      allOf([
+      error: allOf([
         contains('`dart analyze` found the following issue(s):'),
         contains('Analyzing lib, test, pubspec.yaml...'),
         contains('info -'),
         contains("The value of the local variable 'a' isn't used"),
         contains('Package has 1 warning.')
       ]),
-      DATA,
+      exitCode: DATA,
     );
   });
 }
diff --git a/test/validator/dependency_test.dart b/test/validator/dependency_test.dart
index 6d8349e..dead156 100644
--- a/test/validator/dependency_test.dart
+++ b/test/validator/dependency_test.dart
@@ -93,12 +93,6 @@
       await expectValidation();
     });
 
-    test('has a ^ constraint with an appropriate SDK constraint', () async {
-      (await servePackages()).serve('foo', '1.2.3', sdk: '^1.8.3');
-      await package(deps: {'foo': '^1.2.3'}, sdk: '^1.8.3').create();
-      await expectValidation(environment: {'_PUB_TEST_SDK_VERSION': '1.18.0'});
-    });
-
     test('with a dependency on a pre-release while being one', () async {
       (await servePackages()).serve('foo', '1.2.3-dev');
       await package(version: '1.0.0-dev', deps: {'foo': '^1.2.3-dev'}).create();
@@ -109,7 +103,7 @@
         () async {
       await servePackages();
       await d.git('foo', [
-        d.dir('subdir', [d.libPubspec('foo', '1.0.0', sdk: '^2.0.0')]),
+        d.dir('subdir', [d.libPubspec('foo', '1.0.0')]),
       ]).create();
       await package(
         deps: {
@@ -117,7 +111,6 @@
             'git': {'url': '../foo', 'path': 'subdir'}
           }
         },
-        sdk: '>=2.0.0 <3.0.0',
       ).create();
 
       // We should get a warning for using a git dependency, but not an error.
@@ -127,25 +120,20 @@
           contains("Publishable packages can't have 'git' dependencies"),
         ]),
         count: 2,
-        environment: {'_PUB_TEST_SDK_VERSION': '2.0.0'},
       );
     });
 
     test('depends on Flutter from an SDK source', () async {
       await d.dir('flutter', [d.file('version', '1.2.3')]).create();
-      await flutterPackage('flutter', sdk: '>=1.19.0 <2.0.0').create();
+      await flutterPackage('flutter').create();
       await package(
         deps: {
           'flutter': {'sdk': 'flutter'}
         },
-        sdk: '>=1.19.0 <2.0.0',
       ).create();
 
       await expectValidation(
-        environment: {
-          '_PUB_TEST_SDK_VERSION': '1.19.0',
-          'FLUTTER_ROOT': path.join(d.sandbox, 'flutter')
-        },
+        environment: {'FLUTTER_ROOT': path.join(d.sandbox, 'flutter')},
       );
     });
 
@@ -153,18 +141,16 @@
       'depends on a package from Flutter with an appropriate Dart SDK constraint',
       () async {
         await d.dir('flutter', [d.file('version', '1.2.3')]).create();
-        await flutterPackage('foo', sdk: '^1.0.0').create();
+        await flutterPackage('foo').create();
         await d.dir('flutter', [d.file('version', '1.2.3')]).create();
         await package(
           deps: {
             'foo': {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'},
           },
-          sdk: '>=1.19.0 <2.0.0',
         ).create();
 
         await expectValidation(
           environment: {
-            '_PUB_TEST_SDK_VERSION': '1.19.0',
             'FLUTTER_ROOT': path.join(d.sandbox, 'flutter'),
           },
         );
@@ -174,9 +160,8 @@
     test(
       'depends on a package from Fuchsia with an appropriate Dart SDK constraint',
       () async {
-        await fuschiaPackage('foo', sdk: '>=2.0.0 <3.0.0').create();
+        await fuschiaPackage('foo', sdk: '^3.0.0').create();
         await package(
-          sdk: '>=2.0.0 <3.0.0',
           deps: {
             'foo': {'sdk': 'fuchsia', 'version': '>=1.2.3 <2.0.0'}
           },
@@ -185,7 +170,6 @@
         await expectValidation(
           environment: {
             'FUCHSIA_DART_SDK_ROOT': path.join(d.sandbox, 'fuchsia'),
-            '_PUB_TEST_SDK_VERSION': '2.12.0',
           },
         );
       },
@@ -199,16 +183,14 @@
       group('where a hosted version exists', () {
         test('and should suggest the hosted primary version', () async {
           await d.dir('foo', [
-            d.libPubspec('foo', '1.2.3', sdk: 'any'),
+            d.libPubspec('foo', '1.2.3'),
           ]).create();
           await setUpDependency(
-            sdk: '^1.8.0',
             {'path': path.join(d.sandbox, 'foo')},
             hostedVersions: ['3.0.0-pre', '2.0.0', '1.0.0'],
           );
           await expectValidationError(
             '  foo: ^2.0.0',
-            environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
           );
         });
 
@@ -216,32 +198,28 @@
             "and should suggest the hosted prerelease version if it's the only version available",
             () async {
           await d.dir('foo', [
-            d.libPubspec('foo', '1.2.3', sdk: 'any'),
+            d.libPubspec('foo', '1.2.3'),
           ]).create();
           await setUpDependency(
-            sdk: '^1.8.0',
             {'path': path.join(d.sandbox, 'foo')},
             hostedVersions: ['3.0.0-pre', '2.0.0-pre'],
           );
           await expectValidationError(
             '  foo: ^3.0.0-pre',
-            environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
           );
         });
 
         test('and should suggest a tighter constraint if primary is pre-1.0.0',
             () async {
           await d.dir('foo', [
-            d.libPubspec('foo', '1.2.3', sdk: 'any'),
+            d.libPubspec('foo', '1.2.3'),
           ]).create();
           await setUpDependency(
-            sdk: '^1.8.0',
             {'path': path.join(d.sandbox, 'foo')},
             hostedVersions: ['0.0.1', '0.0.2'],
           );
           await expectValidationError(
             '  foo: ^0.0.2',
-            environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
           );
         });
       });
@@ -249,15 +227,14 @@
       group('where no hosted version exists', () {
         test("and should use the other source's version", () async {
           await d.dir('foo', [
-            d.libPubspec('foo', '1.2.3', sdk: 'any'),
+            d.libPubspec('foo', '1.2.3'),
           ]).create();
-          await setUpDependency(sdk: '^1.8.0', {
+          await setUpDependency({
             'path': path.join(d.sandbox, 'foo'),
             'version': '>=1.0.0 <2.0.0'
           });
           await expectValidationError(
             '  foo: ">=1.0.0 <2.0.0"',
-            environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
           );
         });
 
@@ -265,15 +242,13 @@
             "and should use the other source's unquoted version if "
             'concrete', () async {
           await d.dir('foo', [
-            d.libPubspec('foo', '0.2.3', sdk: '^1.8.0'),
+            d.libPubspec('foo', '0.2.3'),
           ]).create();
           await setUpDependency(
-            sdk: '^1.8.0',
             {'path': path.join(d.sandbox, 'foo'), 'version': '0.2.3'},
           );
           await expectValidationError(
             '  foo: 0.2.3',
-            environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
           );
         });
       });
@@ -318,20 +293,18 @@
     });
 
     test('with a dependency on a pre-release without being one', () async {
-      (await servePackages()).serve('foo', '1.2.3-dev', sdk: '^1.8.0');
+      (await servePackages()).serve('foo', '1.2.3-dev');
 
       await d.dir(appPath, [
         d.libPubspec(
           'test_pkg',
           '1.0.0',
           deps: {'foo': '^1.2.3-dev'},
-          sdk: '>=1.8.0 <2.0.0',
         )
       ]).create();
 
       await expectValidationWarning(
         'Packages dependent on a pre-release',
-        environment: {'_PUB_TEST_SDK_VERSION': '1.8.0'},
       );
     });
     test(
@@ -427,157 +400,6 @@
         await expectValidationWarning('  foo: ">1.2.3 <2.0.0"');
       });
     });
-
-    group('has a ^ dependency', () {
-      test('with a too-broad SDK constraint', () async {
-        (await servePackages()).serve('foo', '1.2.3', sdk: '^1.4.0');
-        await d.dir(appPath, [
-          d.libPubspec(
-            'test_pkg',
-            '1.0.0',
-            deps: {'foo': '^1.2.3'},
-            sdk: '>=1.5.0 <2.0.0',
-          )
-        ]).create();
-
-        await expectValidationError(
-          '  sdk: "^1.8.0"',
-          environment: {'_PUB_TEST_SDK_VERSION': '1.5.0'},
-        );
-      });
-    });
-
-    group('has a git path dependency', () {
-      test('without an SDK constraint', () async {
-        // Ensure we don't report anything from the real pub.dev.
-        await setUpDependency({});
-        await d.git('foo', [
-          d.dir('subdir', [
-            d.libPubspec('foo', '1.0.0', extras: {'dependencies': {}})
-          ]),
-        ]).create();
-        await d.dir(appPath, [
-          d.libPubspec(
-            'integration_pkg',
-            '1.0.0',
-            deps: {
-              'foo': {
-                'git': {'url': d.path('foo'), 'path': 'subdir'}
-              },
-            },
-            sdk: '>=1.0.0 <4.0.0',
-          )
-        ]).create();
-
-        await expectValidation(
-          error: allOf(
-            contains('  sdk: "^2.0.0"'),
-            contains('  foo: any'),
-          ),
-          exitCode: DATA,
-        );
-      });
-
-      test('with a too-broad SDK constraint', () async {
-        // Ensure we don't report anything from the real pub.dev.
-        await setUpDependency({});
-        await d.git('foo', [
-          d.dir(
-            'subdir',
-            [d.libPubspec('foo', '1.0.0', sdk: '>=0.0.0 <3.0.0')],
-          ),
-        ]).create();
-        await d.dir(appPath, [
-          d.libPubspec(
-            'integration_pkg',
-            '1.0.0',
-            deps: {
-              'foo': {
-                'git': {'url': d.path('foo'), 'path': 'subdir'}
-              }
-            },
-            sdk: '>=1.24.0 <3.0.0',
-          )
-        ]).create();
-
-        await expectValidation(
-          error: allOf([
-            contains('  sdk: "^2.0.0"'),
-            contains('  foo: any'),
-          ]),
-          environment: {'_PUB_TEST_SDK_VERSION': '1.24.0'},
-          exitCode: DATA,
-        );
-      });
-    });
-
-    test('depends on Flutter from a non-SDK source', () async {
-      (await servePackages()).serve('flutter', '1.5.0');
-      await d.dir(appPath, [
-        d.libPubspec('test_pkg', '1.0.0', deps: {'flutter': '>=1.2.3 <2.0.0'})
-      ]).create();
-
-      await expectValidationError('sdk: >=1.2.3 <2.0.0');
-    });
-
-    test('depends on a Flutter package with a too-broad SDK constraint',
-        () async {
-      await d.dir('flutter', [d.file('version', '1.2.3')]).create();
-      await flutterPackage('foo', sdk: 'any').create();
-      await package(
-        deps: {
-          'foo': {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}
-        },
-        sdk: '>=1.18.0 <2.0.0',
-      ).create();
-
-      await expectValidationError(
-        'sdk: "^1.19.0"',
-        environment: {
-          '_PUB_TEST_SDK_VERSION': '1.19.0',
-          'FLUTTER_ROOT': path.join(d.sandbox, 'flutter'),
-        },
-      );
-    });
-
-    test('depends on a Flutter package with no SDK constraint', () async {
-      await d.dir('flutter', [d.file('version', '1.2.3')]).create();
-      await flutterPackage('foo', sdk: '>=0.0.0 <1.0.0').create();
-      await package(
-        sdk: '>=0.0.0 <=0.0.1',
-        deps: {
-          'foo': {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}
-        },
-      ).create();
-
-      await expectValidationError(
-        'sdk: "^1.19.0"',
-        environment: {
-          '_PUB_TEST_SDK_VERSION': '0.0.0',
-          'FLUTTER_ROOT': path.join(d.sandbox, 'flutter'),
-        },
-      );
-    });
-
-    test('depends on a Fuchsia package with a too-broad SDK constraint',
-        () async {
-      await fuschiaPackage('foo', sdk: '>=0.0.0 <3.0.0').create();
-
-      await package(
-        sdk: '>=2.0.0-dev.50.0 <2.0.2',
-        deps: {
-          'foo': {'sdk': 'fuchsia', 'version': '>=1.2.3 <2.0.0'}
-        },
-      ).create();
-
-      await expectValidationError(
-        'sdk: ">=2.0.0 <2.0.2"',
-        environment: {
-          'FUCHSIA_DART_SDK_ROOT': path.join(d.sandbox, 'fuchsia'),
-          '_PUB_TEST_SDK_VERSION': '2.0.1-dev.51.0',
-        },
-      );
-    });
   });
 }
 
@@ -599,13 +421,12 @@
 d.Descriptor flutterPackage(
   String name, {
   Map<String, String> deps = const {},
-  String? sdk,
 }) {
   return d.dir('flutter', [
     d.dir('packages', [
       d.dir(name, [
         d.libDir(name, 'f(x) => 2 * x;'),
-        d.libPubspec(name, '1.5.0', deps: deps, sdk: sdk),
+        d.libPubspec(name, '1.5.0', deps: deps),
       ]),
     ]),
   ]);
diff --git a/test/validator/flutter_constraint_test.dart b/test/validator/flutter_constraint_test.dart
index f477038..815e6e4 100644
--- a/test/validator/flutter_constraint_test.dart
+++ b/test/validator/flutter_constraint_test.dart
@@ -12,7 +12,6 @@
     error: error,
     args: ['publish', '--dry-run'],
     environment: {
-      '_PUB_TEST_SDK_VERSION': '2.12.0',
       'FLUTTER_ROOT': fakeFlutterRoot.io.path,
     },
     workingDirectory: d.path(appPath),
@@ -36,16 +35,13 @@
       'homepage': 'https://example.com/',
       'version': '1.0.0',
       'environment': {
-        'sdk': '>=2.9.0 <3.0.0',
+        'sdk': '^3.0.0',
         if (flutterConstraint != null) 'flutter': flutterConstraint
       },
     }),
   ]).create();
   await pubGet(
-    environment: {
-      '_PUB_TEST_SDK_VERSION': '2.12.0',
-      'FLUTTER_ROOT': fakeFlutterRoot.io.path
-    },
+    environment: {'FLUTTER_ROOT': fakeFlutterRoot.io.path},
   );
 }
 
diff --git a/test/validator/language_version_test.dart b/test/validator/language_version_test.dart
index cfcb0d8..9832fd2 100644
--- a/test/validator/language_version_test.dart
+++ b/test/validator/language_version_test.dart
@@ -2,78 +2,74 @@
 // for 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/validator.dart';
-import 'package:pub/src/validator/language_version.dart';
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
 import '../test_pub.dart';
 import 'utils.dart';
 
-Validator validator() => LanguageVersionValidator();
-
 Future<void> setup({
   required String sdkConstraint,
   String? libraryLanguageVersion,
 }) async {
   await d.validPackage.create();
   await d.dir(appPath, [
-    d.pubspec({
-      'name': 'test_pkg',
-      'version': '1.0.0',
-      'environment': {'sdk': sdkConstraint},
-    }),
+    d.validPubspec(
+      extras: {
+        'environment': {'sdk': sdkConstraint},
+      },
+    ),
     d.dir('lib', [
       if (libraryLanguageVersion != null)
         d.file('library.dart', '// @dart = $libraryLanguageVersion\n'),
     ])
   ]).create();
-  await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '2.7.0'});
 }
 
 void main() {
   group('should consider a package valid if it', () {
     test('has no library-level language version annotations', () async {
-      await setup(sdkConstraint: '>=2.4.0 <3.0.0');
-      await expectValidationDeprecated(validator);
+      await setup(sdkConstraint: '^3.0.0');
+      await expectValidation();
     });
 
     test('opts in to older language versions', () async {
       await setup(
-        sdkConstraint: '>=2.4.0 <3.0.0',
-        libraryLanguageVersion: '2.0',
+        sdkConstraint: '^3.0.0',
+        libraryLanguageVersion: '2.14',
       );
-      await d.dir(appPath, []).create();
-      await expectValidationDeprecated(validator);
+      await expectValidation();
     });
     test('opts in to same language versions', () async {
       await setup(
-        sdkConstraint: '>=2.4.0 <3.0.0',
-        libraryLanguageVersion: '2.4',
+        sdkConstraint: '^3.0.0',
+        libraryLanguageVersion: '3.0',
       );
-      await d.dir(appPath, []).create();
-      await expectValidationDeprecated(validator);
+      await expectValidation();
     });
 
     test('opts in to older language version, with non-range constraint',
         () async {
-      await setup(sdkConstraint: '2.7.0', libraryLanguageVersion: '2.3');
-      await d.dir(appPath, []).create();
-      await expectValidationDeprecated(validator);
+      await setup(sdkConstraint: '3.1.2+3', libraryLanguageVersion: '2.18');
+      await expectValidation();
     });
   });
 
-  group('should error if it', () {
+  group('should warn if it', () {
     test('opts in to a newer version.', () async {
       await setup(
-        sdkConstraint: '>=2.4.1 <3.0.0',
-        libraryLanguageVersion: '2.5',
+        sdkConstraint: '^3.0.0',
+        libraryLanguageVersion: '3.1',
       );
-      await expectValidationDeprecated(validator, errors: isNotEmpty);
+      await expectValidationWarning(
+        'The language version override can\'t specify a version greater than the latest known language version',
+      );
     });
     test('opts in to a newer version, with non-range constraint.', () async {
-      await setup(sdkConstraint: '2.7.0', libraryLanguageVersion: '2.8');
-      await expectValidationDeprecated(validator, errors: isNotEmpty);
+      await setup(sdkConstraint: '3.1.2+3', libraryLanguageVersion: '3.2');
+      await expectValidationWarning(
+        'The language version override can\'t specify a version greater than the latest known language version',
+      );
     });
   });
 }
diff --git a/test/validator/relative_version_numbering_test.dart b/test/validator/relative_version_numbering_test.dart
index 34dc23d..6b73dff 100644
--- a/test/validator/relative_version_numbering_test.dart
+++ b/test/validator/relative_version_numbering_test.dart
@@ -27,44 +27,6 @@
 
 void main() {
   group('should consider a package valid if it', () {
-    test('is not opting in to null-safety with previous non-null-safe version',
-        () async {
-      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');
-      await expectValidationDeprecated(validator);
-    });
-
-    test(
-        'is not opting in to null-safety with previous non-null-safe version. '
-        'Even with a later null-safe version', () async {
-      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 expectValidationDeprecated(validator);
-    });
-
     test('is opting in to null-safety with previous null-safe version',
         () async {
       final server = await servePackages();
@@ -125,36 +87,6 @@
       await expectValidationDeprecated(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();
-
-      await expectValidationDeprecated(validator);
-    });
-
-    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()
-        ..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 expectValidationDeprecated(validator);
-    });
-
     test(
         'opts in to null-safety, with previous stable version not-null-safe. '
         'With an in-between non-null-safe prerelease', () async {
@@ -196,44 +128,6 @@
     });
 
     test(
-        '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');
-      final server = await servePackages();
-      server.serve(
-        'test_pkg',
-        '0.0.2-dev',
-        pubspec: {
-          'environment': {'sdk': '>=2.12.0<3.0.0'}
-        },
-      );
-
-      await expectValidationDeprecated(validator, hints: isNotEmpty);
-    });
-    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()
-        ..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 expectValidationDeprecated(validator, hints: isNotEmpty);
-    });
-
-    test(
         'opts in to null-safety, with previous version not-null-safe. '
         'Even with a later null-safe version', () async {
       await servePackages()
@@ -256,44 +150,6 @@
       await expectValidationDeprecated(validator, hints: isNotEmpty);
     });
 
-    test('is not opting in to null-safety with previous null-safe version',
-        () async {
-      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');
-      await expectValidationDeprecated(validator, hints: isNotEmpty);
-    });
-
-    test(
-        'is not opting in to null-safety with previous null-safe version. '
-        'Even with a later non-null-safe version', () async {
-      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 expectValidationDeprecated(validator, hints: isNotEmpty);
-    });
-
     test(
         'is opting in to null-safety with previous null-safe stable version. '
         'with an in-between non-null-safe prerelease', () async {
diff --git a/test/validator/sdk_constraint_test.dart b/test/validator/sdk_constraint_test.dart
index 4f0e2db..b050c72 100644
--- a/test/validator/sdk_constraint_test.dart
+++ b/test/validator/sdk_constraint_test.dart
@@ -94,66 +94,6 @@
       );
     });
 
-    test(
-        'has a Flutter SDK constraint with a too-broad SDK '
-        'constraint', () async {
-      await d.dir(appPath, [
-        d.pubspec({
-          'name': 'test_pkg',
-          'version': '1.0.0',
-          'environment': {'sdk': '>=1.18.0 <1.50.0', 'flutter': '^1.2.3'}
-        })
-      ]).create();
-      await expectValidationDeprecated(
-        sdkConstraint,
-        errors: anyElement(contains('">=1.19.0 <1.50.0"')),
-      );
-    });
-
-    test('has a Flutter SDK constraint with no SDK constraint', () async {
-      await d.dir(appPath, [
-        d.rawPubspec({
-          'name': 'test_pkg',
-          'version': '1.0.0',
-          'environment': {'flutter': '^1.2.3'}
-        })
-      ]).create();
-      await expectValidationDeprecated(
-        sdkConstraint,
-        errors: anyElement(contains('"^1.19.0"')),
-      );
-    });
-
-    test(
-        'has a Fuchsia SDK constraint with a too-broad SDK '
-        'constraint', () async {
-      await d.dir(appPath, [
-        d.rawPubspec({
-          'name': 'test_pkg',
-          'version': '1.0.0-dev.1',
-          'environment': {'sdk': '>=2.0.0-dev.50.0 <2.0.0', 'fuchsia': '^1.2.3'}
-        })
-      ]).create();
-      await expectValidationDeprecated(
-        sdkConstraint,
-        errors: anyElement(contains('"^2.0.0"')),
-      );
-    });
-
-    test('has a Fuchsia SDK constraint with no SDK constraint', () async {
-      await d.dir(appPath, [
-        d.rawPubspec({
-          'name': 'test_pkg',
-          'version': '1.0.0',
-          'environment': {'fuchsia': '^1.2.3'}
-        })
-      ]).create();
-      await expectValidationDeprecated(
-        sdkConstraint,
-        errors: anyElement(contains('"^2.0.0"')),
-      );
-    });
-
     test('depends on a pre-release sdk from a non-pre-release', () async {
       await d.dir(appPath, [
         d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0-dev.1 <2.0.0')
diff --git a/test/validator/utils.dart b/test/validator/utils.dart
index ffbe892..2262a55 100644
--- a/test/validator/utils.dart
+++ b/test/validator/utils.dart
@@ -28,13 +28,16 @@
   error,
   int exitCode = 0,
   Map<String, String> environment = const {},
+  List<String>? extraArgs,
+  String? workingDirectory,
 }) async {
   await runPub(
     error: error ?? contains('Package has 0 warnings.'),
-    args: ['publish', '--dry-run'],
+    args: ['publish', '--dry-run', ...?extraArgs],
     // workingDirectory: d.path(appPath),
     exitCode: exitCode,
     environment: environment,
+    workingDirectory: workingDirectory,
   );
 }