[flutter_tools] allow using flutter test for testing the tool too (#69911)

diff --git a/dev/missing_dependency_tests/trivial_expectation.txt b/dev/missing_dependency_tests/trivial_expectation.txt
index 79bf7d3..cfd88b3 100644
--- a/dev/missing_dependency_tests/trivial_expectation.txt
+++ b/dev/missing_dependency_tests/trivial_expectation.txt
@@ -1,7 +1,7 @@
 <<skip until matching line>>
 <<stderr>>
 <<skip until matching line>>
-Error: cannot run without a dependency on "package:flutter_test". Ensure the following lines are present in your pubspec.yaml:
+Error: cannot run without a dependency on either "package:flutter_test" or "package:test". Ensure the following lines are present in your pubspec.yaml:
 
 dev_dependencies:
   flutter_test:
diff --git a/packages/flutter_tools/README.md b/packages/flutter_tools/README.md
index 7bd4dea..2f6b29b 100644
--- a/packages/flutter_tools/README.md
+++ b/packages/flutter_tools/README.md
@@ -15,14 +15,14 @@
 First, ensure that the Dart SDK and other necessary artifacts are available by
 invoking the Flutter Tools wrapper script. In this directory run:
 ```shell
-$ ../../bin/flutter --version
+$ flutter --version
 ```
 
 ### Running the Tool
 
 To run Flutter Tools from source, in this directory run:
 ```shell
-$ ../../bin/dart bin/flutter_tools.dart
+$ dart bin/flutter_tools.dart
 ```
 followed by command-line arguments, as usual.
 
@@ -31,7 +31,7 @@
 
 To run the analyzer on Flutter Tools, in this directory run:
 ```shell
-$ ../../bin/flutter analyze
+$ flutter analyze
 ```
 
 ### Writing tests
@@ -50,12 +50,6 @@
 file called `file_test.dart` in the subdirectory that matches the behavior of
 the test.
 
-We measure [test coverage](https://codecov.io/gh/flutter/flutter) post-submit.
-A change that deletes code might decrease test coverage, however, most changes
-that add new code should aim to increase coverage. In particular, the coverage
-of the diff should be close to the average coverage, and should ideally be
-better.
-
 #### Using local engine builds in integration tests
 
 The integration tests can be configured to use a specific local engine
@@ -67,15 +61,15 @@
 
 ```shell
 export FLUTTER_LOCAL_ENGINE=android_debug_unopt
-../../bin/dart test test/integration.shard/some_test_case
+flutter test test/integration.shard/some_test_case
 ```
 
 ### Running the tests
 
-To run the tests in the `test/` directory, first ensure that there are no
-connected devices. Then, in this directory run:
+To run the tests in the `test/` directory:
+
 ```shell
-$ ../../bin/dart pub run test
+$ flutter test
 ```
 
 The tests in `test/integration.shard` are slower to run than the tests in
@@ -83,12 +77,12 @@
 to be set and pointing to the root of the Flutter SDK. To run only the tests in `test/general.shard`, in this
 directory run:
 ```shell
-$ ../../bin/dart pub run test test/general.shard
+$ flutter test test/general.shard
 ```
 
 To run the tests in a specific file, run:
 ```shell
-$ ../../bin/dart pub run test test/general.shard/utils_test.dart
+$ flutter test test/general.shard/utils_test.dart
 ```
 
 ### Forcing snapshot regeneration
diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart
index 246f287..f6ae079 100644
--- a/packages/flutter_tools/lib/src/commands/test.dart
+++ b/packages/flutter_tools/lib/src/commands/test.dart
@@ -131,6 +131,17 @@
               'interact with the vmservice at runtime.\n'
               'This flag is ignored if --start-paused or coverage are requested. '
               'The vmservice will be enabled no matter what in those cases.'
+      )
+      ..addOption('reporter',
+        abbr: 'r',
+        defaultsTo: 'compact',
+        help: 'Set how to print test results.\n'
+        '[compact] (default)         A single line, updated continuously.\n'
+        '[expanded]                  A separate line for each update.\n'
+        '[json]                      A machine-readable format (see https://dart.dev/go/test-docs/json_reporter.md).\n')
+      ..addOption('timeout',
+        help: 'The default test timeout. For example: 15s, 2x, none. Defaults to "30s"',
+        defaultsTo: '30s',
       );
       addDdsOptions(verboseHelp: verboseHelp);
   }
@@ -263,6 +274,8 @@
       web: stringArg('platform') == 'chrome',
       randomSeed: stringArg('test-randomize-ordering-seed'),
       nullAssertions: boolArg(FlutterOptions.kNullAssertions),
+      reporter: stringArg('reporter'),
+      timeout: stringArg('timeout'),
     );
 
     if (collector != null) {
diff --git a/packages/flutter_tools/lib/src/test/flutter_platform.dart b/packages/flutter_tools/lib/src/test/flutter_platform.dart
index 4d35eb9..408ba64 100644
--- a/packages/flutter_tools/lib/src/test/flutter_platform.dart
+++ b/packages/flutter_tools/lib/src/test/flutter_platform.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:io' as io; // ignore: dart_io_import;
 
 import 'package:dds/dds.dart';
 import 'package:meta/meta.dart';
@@ -125,6 +126,7 @@
   bool updateGoldens = false,
   String languageVersionHeader = '',
   bool nullSafety = false,
+  bool flutterTestDep = true,
 }) {
   assert(testUrl != null);
   assert(host != null);
@@ -142,8 +144,13 @@
 import 'dart:convert';  // ignore: dart_convert_import
 import 'dart:io';  // ignore: dart_io_import
 import 'dart:isolate';
-
+''');
+  if (flutterTestDep) {
+    buffer.write('''
 import 'package:flutter_test/flutter_test.dart';
+''');
+  }
+  buffer.write('''
 import 'package:test_api/src/remote_listener.dart';
 import 'package:stream_channel/stream_channel.dart';
 import 'package:stack_trace/stack_trace.dart';
@@ -186,9 +193,13 @@
   String server = Uri.decodeComponent('$encodedWebsocketUrl:\$serverPort');
   StreamChannel<dynamic> channel = serializeSuite(() {
     catchIsolateErrors();
-    goldenFileComparator = new LocalFileComparator(Uri.parse('$testUrl'));
-    autoUpdateGoldenFiles = $updateGoldens;
 ''');
+  if (flutterTestDep) {
+    buffer.write('''
+goldenFileComparator = LocalFileComparator(Uri.parse('$testUrl'));
+autoUpdateGoldenFiles = $updateGoldens;
+''');
+  }
   if (testConfigFile != null) {
     buffer.write('''
     return () => test_config.testExecutable(test.main);
@@ -289,23 +300,10 @@
     // LoadSuite to emit an error, which will be presented to the user.
     // Except for the Declarer error, which is a specific test incompatibility
     // error we need to catch.
-    try {
-      final StreamChannel<dynamic> channel = loadChannel(path, platform);
-      final RunnerSuiteController controller = deserializeSuite(path, platform,
-        suiteConfig, const PluginEnvironment(), channel, message);
-      return await controller.suite;
-    } on Exception catch (err) {
-      /// Rethrow a less confusing error if it is a test incompatibility.
-      if (err.toString().contains("type 'Declarer' is not a subtype of type 'Declarer'")) {
-        throw UnsupportedError('Package incompatibility between flutter and test packages:\n'
-          '  * flutter is incompatible with test <1.4.0.\n'
-          '  * flutter is incompatible with mockito <4.0.0\n'
-          "To fix this error, update test to at least '^1.4.0' and mockito to at least '^4.0.0'\n"
-        );
-      }
-      // Guess it was a different error.
-      rethrow;
-    }
+    final StreamChannel<dynamic> channel = loadChannel(path, platform);
+    final RunnerSuiteController controller = deserializeSuite(path, platform,
+      suiteConfig, const PluginEnvironment(), channel, message);
+    return controller.suite;
   }
 
   @override
@@ -457,7 +455,7 @@
       finalizers.add(() async {
         if (subprocessActive) {
           globals.printTrace('test $ourTestCount: ensuring end-of-process for shell');
-          process.kill();
+          process.kill(io.ProcessSignal.sigkill);
           final int exitCode = await process.exitCode;
           subprocessActive = false;
           if (!controllerSinkClosed && exitCode != -15) {
@@ -722,6 +720,7 @@
       testConfigFile: findTestConfigFile(globals.fs.file(testUrl)),
       host: host,
       updateGoldens: updateGoldens,
+      flutterTestDep: _packageConfig['flutter_test'] != null,
       languageVersionHeader: '// @dart=${languageVersion.major}.${languageVersion.minor}'
     );
   }
diff --git a/packages/flutter_tools/lib/src/test/runner.dart b/packages/flutter_tools/lib/src/test/runner.dart
index fb71684..dfc2325 100644
--- a/packages/flutter_tools/lib/src/test/runner.dart
+++ b/packages/flutter_tools/lib/src/test/runner.dart
@@ -49,6 +49,8 @@
     String randomSeed,
     bool nullAssertions = false,
     @required BuildInfo buildInfo,
+    String reporter,
+    String timeout,
   });
 }
 
@@ -83,6 +85,8 @@
     String randomSeed,
     bool nullAssertions = false,
     @required BuildInfo buildInfo,
+    String reporter,
+    String timeout,
   }) async {
     // Configure package:test to use the Flutter engine for child processes.
     final String shellPath = globals.artifacts.getArtifactPath(Artifact.flutterTester);
@@ -99,7 +103,9 @@
       if (machine)
         ...<String>['-r', 'json']
       else
-        ...<String>['-r', 'compact'],
+        ...<String>['-r', reporter ?? 'compact'],
+      if (timeout != null)
+        ...<String>['--timeout', timeout],
       '--concurrency=$concurrency',
       for (final String name in names)
         ...<String>['--name', name],
diff --git a/packages/flutter_tools/lib/src/test/test_compiler.dart b/packages/flutter_tools/lib/src/test/test_compiler.dart
index e8ac393..fbb79ad 100644
--- a/packages/flutter_tools/lib/src/test/test_compiler.dart
+++ b/packages/flutter_tools/lib/src/test/test_compiler.dart
@@ -134,10 +134,10 @@
       );
       // Compilation will fail if there is no flutter_test dependency, since
       // this library is imported by the generated entrypoint script.
-      if (_packageConfig['flutter_test'] == null) {
+      if (_packageConfig['test_api'] == null) {
         globals.printError(
           '\n'
-          'Error: cannot run without a dependency on "package:flutter_test". '
+          'Error: cannot run without a dependency on either "package:flutter_test" or "package:test". '
           'Ensure the following lines are present in your pubspec.yaml:'
           '\n\n'
           'dev_dependencies:\n'
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart
index 31a9953..ea89124 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart
@@ -188,6 +188,8 @@
     @override List<String> extraFrontEndOptions,
     bool nullAssertions = false,
     BuildInfo buildInfo,
+    String reporter,
+    String timeout,
   }) async {
     lastEnableObservatoryValue = enableObservatory;
     return exitCode;
diff --git a/packages/flutter_tools/test/general.shard/test_compiler_test.dart b/packages/flutter_tools/test/general.shard/test_compiler_test.dart
index 1597ea3..1c6bc87 100644
--- a/packages/flutter_tools/test/general.shard/test_compiler_test.dart
+++ b/packages/flutter_tools/test/general.shard/test_compiler_test.dart
@@ -33,7 +33,7 @@
     fileSystem.file('test/foo.dart').createSync(recursive: true);
     fileSystem.file('.packages')
       ..createSync()
-      ..writeAsStringSync('flutter_test:flutter_test/');
+      ..writeAsStringSync('test_api:test_api/\n');
     residentCompiler = MockResidentCompiler();
   });
 
@@ -109,7 +109,7 @@
     Logger: () => BufferLogger.test(),
   });
 
-  testUsingContext('TestCompiler reports an error when there is no dependency on flutter_test', () async {
+  testUsingContext('TestCompiler reports an error when there is no dependency on flutter_test or test', () async {
     final FakeTestCompiler testCompiler = FakeTestCompiler(
       BuildInfo.debug,
       FlutterProject.current(),
@@ -118,7 +118,8 @@
     fileSystem.file('.packages').writeAsStringSync('\n');
 
     expect(await testCompiler.compile(Uri.parse('test/foo.dart')), null);
-    expect(testLogger.errorText, contains('Error: cannot run without a dependency on "package:flutter_test"'));
+    expect(testLogger.errorText, contains('Error: cannot run without a dependency on '
+      'either "package:flutter_test" or "package:test'));
     verifyNever(residentCompiler.recompile(
       any,
       <Uri>[Uri.parse('test/foo.dart')],