Add API to integrate with testWidgets. (#188)

diff --git a/pkgs/leak_tracker/CHANGELOG.md b/pkgs/leak_tracker/CHANGELOG.md
index e571d44..3451973 100644
--- a/pkgs/leak_tracker/CHANGELOG.md
+++ b/pkgs/leak_tracker/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 9.0.17
+
+* Move LeakTesting to leak_tracker_testing.
+
 ## 9.0.16
 
 * Stub web implementation for retaining path to serve G3.
diff --git a/pkgs/leak_tracker/lib/leak_tracker.dart b/pkgs/leak_tracker/lib/leak_tracker.dart
index c84268b..1ba1375 100644
--- a/pkgs/leak_tracker/lib/leak_tracker.dart
+++ b/pkgs/leak_tracker/lib/leak_tracker.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 export 'src/leak_tracking/helpers.dart';
-export 'src/leak_tracking/leak_testing.dart';
 export 'src/leak_tracking/leak_tracking.dart';
 export 'src/leak_tracking/primitives/model.dart';
 export 'src/shared/shared_model.dart';
diff --git a/pkgs/leak_tracker/pubspec.yaml b/pkgs/leak_tracker/pubspec.yaml
index 97bba93..3b79e3a 100644
--- a/pkgs/leak_tracker/pubspec.yaml
+++ b/pkgs/leak_tracker/pubspec.yaml
@@ -1,5 +1,5 @@
 name: leak_tracker
-version: 9.0.16
+version: 9.0.17
 description: A framework for memory leak tracking for Dart and Flutter applications.
 repository: https://github.com/dart-lang/leak_tracker/tree/main/pkgs/leak_tracker
 
diff --git a/pkgs/leak_tracker_flutter_testing/CHANGELOG.md b/pkgs/leak_tracker_flutter_testing/CHANGELOG.md
index 900b773..d996cba 100644
--- a/pkgs/leak_tracker_flutter_testing/CHANGELOG.md
+++ b/pkgs/leak_tracker_flutter_testing/CHANGELOG.md
@@ -1,6 +1,7 @@
-## 1.0.11-wip
+## 1.0.12
 
-* Updated to use `package:lints/recommended.yaml` for analysis.
+* Update to use `package:lints/recommended.yaml` for analysis.
+* Add API to integrate with testWidgets.
 
 ## 1.0.10
 
diff --git a/pkgs/leak_tracker_flutter_testing/lib/leak_tracker_flutter_testing.dart b/pkgs/leak_tracker_flutter_testing/lib/leak_tracker_flutter_testing.dart
index 7ee10e6..3bf816a 100644
--- a/pkgs/leak_tracker_flutter_testing/lib/leak_tracker_flutter_testing.dart
+++ b/pkgs/leak_tracker_flutter_testing/lib/leak_tracker_flutter_testing.dart
@@ -5,3 +5,8 @@
 export 'src/matchers.dart';
 export 'src/model.dart';
 export 'src/test_widgets.dart';
+export 'src/testing.dart';
+export 'package:leak_tracker/leak_tracker.dart'
+    show Leaks, LeakTracking, IgnoredLeaks, LeakType, LeakReport;
+export 'package:leak_tracker_testing/leak_tracker_testing.dart'
+    show isLeakFree, LeakTesting;
diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/test_widgets.dart b/pkgs/leak_tracker_flutter_testing/lib/src/test_widgets.dart
index e4cbae6..523aaac 100644
--- a/pkgs/leak_tracker_flutter_testing/lib/src/test_widgets.dart
+++ b/pkgs/leak_tracker_flutter_testing/lib/src/test_widgets.dart
@@ -8,6 +8,9 @@
 import 'package:leak_tracker_testing/leak_tracker_testing.dart';
 import 'package:meta/meta.dart';
 
+// TODO: remove this library
+// https://github.com/flutter/flutter/issues/135856
+
 void _flutterEventToLeakTracker(ObjectEvent event) {
   return LeakTracking.dispatchObjectEvent(event.toMap());
 }
diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart
new file mode 100644
index 0000000..7d661fd
--- /dev/null
+++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2023, 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:flutter/foundation.dart';
+import 'package:leak_tracker/leak_tracker.dart';
+import 'package:leak_tracker_testing/leak_tracker_testing.dart';
+
+/// Makes sure leak tracking is set up for a test.
+///
+/// If `settings.ignore` is true, the method is noop.
+/// If leak tracking is not started, starts it.
+/// Configures `LeakTracking.phase` to match [settings].
+void maybeSetupLeakTrackingForTest(
+  LeakTesting? settings,
+  String testDescription,
+) {
+  final leakTesting = settings ?? LeakTesting.settings;
+  if (leakTesting.ignore) return;
+
+  if (!_checkPlatformAndMayBePrintWarning(
+      platformName: defaultTargetPlatform.name, isBrowser: kIsWeb)) {
+    return;
+  }
+
+  _maybeStartLeakTracking();
+
+  final PhaseSettings phase = PhaseSettings(
+    name: testDescription,
+    leakDiagnosticConfig: leakTesting.leakDiagnosticConfig,
+    ignoredLeaks: leakTesting.ignoredLeaks,
+    baselining: leakTesting.baselining,
+    ignoreLeaks: leakTesting.ignore,
+  );
+
+  LeakTracking.phase = phase;
+}
+
+/// If leak tracking is enabled, stops it and declares notDisposed objects as leaks.
+void maybeTearDownLeakTrackingForTest() {
+  if (!LeakTracking.isStarted || LeakTracking.phase.ignoreLeaks) return;
+  LeakTracking.phase = const PhaseSettings.ignored();
+}
+
+/// Should be invoked after execution of all tests to report found leaks.
+///
+/// Is noop if leak tracking is not started.
+Future<void> maybeTearDownLeakTrackingForAll() async {
+  if (!LeakTracking.isStarted) {
+    return;
+  }
+
+  // The listener is not added/removed for each test,
+  // because GC may happen after test is complete.
+  MemoryAllocations.instance.removeListener(_dispatchFlutterEventToLeakTracker);
+  await forceGC(fullGcCycles: defaultNumberOfGcCycles);
+  LeakTracking.declareNotDisposedObjectsAsLeaks();
+  final Leaks leaks = await LeakTracking.collectLeaks();
+  LeakTracking.stop();
+
+  LeakTesting.collectedLeaksReporter(leaks);
+}
+
+void _dispatchFlutterEventToLeakTracker(ObjectEvent event) {
+  return LeakTracking.dispatchObjectEvent(event.toMap());
+}
+
+bool _notSupportedWarningPrinted = false;
+
+/// Checks if platform supported and, if no, prints warning if the warning is needed.
+///
+/// Warning is printed one time if `LeakTracking.warnForNotSupportedPlatforms` is true.
+bool _checkPlatformAndMayBePrintWarning(
+    {required String platformName, required bool isBrowser}) {
+  final isSupported = !isBrowser;
+
+  if (isSupported) return true;
+
+  final shouldPrintWarning =
+      LeakTracking.warnForUnsupportedPlatforms && !_notSupportedWarningPrinted;
+
+  if (!shouldPrintWarning) return false;
+
+  _notSupportedWarningPrinted = true;
+  debugPrint(
+    "Leak tracking is not supported on the platform '$platformName'.\n"
+    'To turn off this message, set `LeakTracking.warnForNotSupportedPlatforms` to false.',
+  );
+
+  return false;
+}
+
+/// Starts leak tracking with all leaks ignored.
+void _maybeStartLeakTracking() {
+  if (LeakTracking.isStarted) return;
+
+  LeakTracking.phase = const PhaseSettings.ignored();
+  LeakTracking.start(config: LeakTrackingConfig.passive());
+  MemoryAllocations.instance.addListener(_dispatchFlutterEventToLeakTracker);
+}
diff --git a/pkgs/leak_tracker_flutter_testing/pubspec.yaml b/pkgs/leak_tracker_flutter_testing/pubspec.yaml
index c92ad73..45f088f 100644
--- a/pkgs/leak_tracker_flutter_testing/pubspec.yaml
+++ b/pkgs/leak_tracker_flutter_testing/pubspec.yaml
@@ -1,5 +1,5 @@
 name: leak_tracker_flutter_testing
-version: 1.0.12-wip
+version: 1.0.12
 description: An internal package to test leak tracking with Flutter.
 repository: https://github.com/dart-lang/leak_tracker/tree/main/pkgs/leak_tracker_flutter_testing
 
@@ -13,6 +13,7 @@
     sdk: flutter
   leak_tracker: ^9.0.10
   leak_tracker_testing: ^1.0.5
+  matcher: ^0.12.16
   meta: ^1.8.0
 
 dev_dependencies:
diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/failing_tests/flutter_test_config.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/failing_tests/flutter_test_config.dart
index f0025dd..8b3db85 100644
--- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/failing_tests/flutter_test_config.dart
+++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/failing_tests/flutter_test_config.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 
 import 'package:flutter_test/flutter_test.dart';
-import 'package:leak_tracker/leak_tracker.dart';
 import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
 
 import 'failure_test.dart';
diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/no_config_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/no_config_test.dart
index 9c26b94..22bb04a 100644
--- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/no_config_test.dart
+++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/no_config_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:flutter_test/flutter_test.dart';
-import 'package:leak_tracker/leak_tracker.dart';
 import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
 
 import '../../test_infra/flutter_classes.dart';
diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/per_test_config_test/flutter_test_config.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/per_test_config_test/flutter_test_config.dart
index aaebf9f..8bfca8b 100644
--- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/per_test_config_test/flutter_test_config.dart
+++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/per_test_config_test/flutter_test_config.dart
@@ -5,9 +5,7 @@
 import 'dart:async';
 
 import 'package:flutter_test/flutter_test.dart';
-import 'package:leak_tracker/leak_tracker.dart';
 import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
-import 'package:leak_tracker_testing/leak_tracker_testing.dart';
 
 import '../../../test_infra/dart_classes.dart';
 import 'per_test_config_test.dart';
diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/per_test_config_test/per_test_config_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/per_test_config_test/per_test_config_test.dart
index e232b0e..855b6cf 100644
--- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/per_test_config_test/per_test_config_test.dart
+++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/per_test_config_test/per_test_config_test.dart
@@ -4,7 +4,6 @@
 
 import 'package:flutter/widgets.dart';
 import 'package:flutter_test/flutter_test.dart';
-import 'package:leak_tracker/leak_tracker.dart';
 import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
 
 import '../../../test_infra/flutter_classes.dart';
diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/settings_not_disposed_off_test/flutter_test_config.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/settings_not_disposed_off_test/flutter_test_config.dart
index a87f04c..0815e3b 100644
--- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/settings_not_disposed_off_test/flutter_test_config.dart
+++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/settings_not_disposed_off_test/flutter_test_config.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 
 import 'package:flutter_test/flutter_test.dart';
-import 'package:leak_tracker/leak_tracker.dart';
 import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
 
 /// Test configuration for each test library in this directory.
diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/settings_not_gced_off_test/flutter_test_config.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/settings_not_gced_off_test/flutter_test_config.dart
index 3867e80..bb1e25b 100644
--- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/settings_not_gced_off_test/flutter_test_config.dart
+++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/settings_not_gced_off_test/flutter_test_config.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 
 import 'package:flutter_test/flutter_test.dart';
-import 'package:leak_tracker/leak_tracker.dart';
 import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
 
 /// Test configuration for each test library in this directory.
diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/leak_tracking_for_tests_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/leak_tracking_for_tests_test.dart
index e51c710..2220eb3 100644
--- a/pkgs/leak_tracker_flutter_testing/test/tests/leak_tracking_for_tests_test.dart
+++ b/pkgs/leak_tracker_flutter_testing/test/tests/leak_tracking_for_tests_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:flutter_test/flutter_test.dart';
 import 'package:leak_tracker/leak_tracker.dart';
+import 'package:leak_tracker_testing/leak_tracker_testing.dart';
 
 class _Classes {
   static const anyLeak1 = 'anyLeak1';
diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/testing_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/testing_test.dart
new file mode 100644
index 0000000..44c69d7
--- /dev/null
+++ b/pkgs/leak_tracker_flutter_testing/test/tests/testing_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2023, 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:flutter_test/flutter_test.dart';
+import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
+
+final LeakTesting settings =
+    LeakTesting.settings.withIgnored(allNotDisposed: true, allNotGCed: true);
+
+void main() {
+  group('maybeSetupLeakTrackingForTest', () {
+    setUp(() {
+      LeakTesting.settings = LeakTesting.settings.withTrackedAll();
+    });
+
+    tearDown(() {
+      LeakTracking.stop();
+    });
+
+    test('If settings is null, respects globals', () {
+      maybeSetupLeakTrackingForTest(null, 'myTest1');
+      expect(LeakTracking.isStarted, true);
+      expect(LeakTracking.phase.name, 'myTest1');
+      expect(LeakTracking.phase.ignoreLeaks, LeakTesting.settings.ignore);
+      expect(
+        LeakTracking.phase.ignoredLeaks,
+        LeakTesting.settings.ignoredLeaks,
+      );
+    });
+
+    test('If settings are provided, respects them', () {
+      maybeSetupLeakTrackingForTest(settings, 'myTest2');
+      expect(LeakTracking.isStarted, true);
+      expect(LeakTracking.phase.name, 'myTest2');
+      expect(LeakTracking.phase.ignoreLeaks, settings.ignore);
+      expect(
+        LeakTracking.phase.ignoredLeaks,
+        settings.ignoredLeaks,
+      );
+    });
+  });
+
+  group('maybeTearDownLeakTrackingForTest', () {
+    setUp(() {
+      LeakTesting.settings = LeakTesting.settings.withTrackedAll();
+      maybeSetupLeakTrackingForTest(null, 'myTest1');
+    });
+
+    tearDown(() {
+      LeakTracking.stop();
+    });
+
+    test('Pauses leak tracking and can be invoiked twice', () {
+      maybeTearDownLeakTrackingForTest();
+      expect(LeakTracking.phase.name, null);
+      expect(LeakTracking.isStarted, true);
+      expect(LeakTracking.phase.ignoreLeaks, true);
+
+      maybeTearDownLeakTrackingForTest();
+      expect(LeakTracking.phase.name, null);
+      expect(LeakTracking.isStarted, true);
+      expect(LeakTracking.phase.ignoreLeaks, true);
+    });
+  });
+
+  group('maybeTearDownLeakTrackingForAll', () {
+    setUp(() {
+      LeakTesting.settings = LeakTesting.settings.withTrackedAll();
+      maybeSetupLeakTrackingForTest(null, 'myTest1');
+      maybeTearDownLeakTrackingForTest();
+    });
+
+    tearDown(() {
+      LeakTracking.stop();
+    });
+
+    test('Stops leak tracking', () async {
+      await maybeTearDownLeakTrackingForAll();
+      expect(LeakTracking.isStarted, false);
+    });
+  });
+}
diff --git a/pkgs/leak_tracker_testing/CHANGELOG.md b/pkgs/leak_tracker_testing/CHANGELOG.md
index 16240a8..9ce6acf 100644
--- a/pkgs/leak_tracker_testing/CHANGELOG.md
+++ b/pkgs/leak_tracker_testing/CHANGELOG.md
@@ -1,6 +1,7 @@
-## 1.0.6-wip
+## 1.0.6
 
 * Updated to use `package:lints/recommended.yaml` for analysis.
+* Move LeakTesting from leak_tracker to this library.
 
 ## 1.0.5
 
diff --git a/pkgs/leak_tracker_testing/lib/leak_tracker_testing.dart b/pkgs/leak_tracker_testing/lib/leak_tracker_testing.dart
index 8dd0655..77e6955 100644
--- a/pkgs/leak_tracker_testing/lib/leak_tracker_testing.dart
+++ b/pkgs/leak_tracker_testing/lib/leak_tracker_testing.dart
@@ -3,3 +3,4 @@
 // BSD-style license that can be found in the LICENSE file.
 
 export 'src/matchers.dart';
+export 'src/leak_testing.dart';
diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/leak_testing.dart b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart
similarity index 93%
rename from pkgs/leak_tracker/lib/src/leak_tracking/leak_testing.dart
rename to pkgs/leak_tracker_testing/lib/src/leak_testing.dart
index 9e5393d..f19ce33 100644
--- a/pkgs/leak_tracker/lib/src/leak_tracking/leak_testing.dart
+++ b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart
@@ -2,10 +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.
 
+import 'package:leak_tracker/leak_tracker.dart';
+import 'package:matcher/expect.dart';
 import 'package:meta/meta.dart';
 
-import '../shared/shared_model.dart';
-import 'primitives/model.dart';
+import 'matchers.dart';
 
 void _emptyLeakHandler(Leaks leaks) {}
 
@@ -43,6 +44,16 @@
     this.baselining = const MemoryBaselining.none(),
   });
 
+  /// Handler for memory leaks found in tests.
+  ///
+  /// Set it to analyse the leaks programmatically.
+  /// The handler is invoked on tear down of the test run.
+  /// The default reporter fails in case of found leaks.
+  ///
+  /// Used to test leak tracking functionality.
+  static LeaksCallback collectedLeaksReporter =
+      (Leaks leaks) => expect(leaks, isLeakFree);
+
   /// Current configuration for leak tracking.
   ///
   /// Is used by `testWidgets` if configuration is not provided for a test.
diff --git a/pkgs/leak_tracker_testing/pubspec.yaml b/pkgs/leak_tracker_testing/pubspec.yaml
index 1f736b4..7c7adc1 100644
--- a/pkgs/leak_tracker_testing/pubspec.yaml
+++ b/pkgs/leak_tracker_testing/pubspec.yaml
@@ -1,5 +1,5 @@
 name: leak_tracker_testing
-version: 1.0.6-wip
+version: 1.0.6
 description: Leak tracking code intended for usage in tests.
 repository: https://github.com/dart-lang/leak_tracker/tree/main/pkgs/leak_tracker_testing
 
@@ -12,6 +12,7 @@
 dependencies:
   leak_tracker: '>=9.0.0 <11.0.0'
   matcher: ^0.12.16
+  meta: ^1.11.0
 
 dev_dependencies:
   layerlens: ^1.0.0
diff --git a/pkgs/leak_tracker/test/tests/leak_tracking/leak_testing_test.dart b/pkgs/leak_tracker_testing/test/leak_testing_test.dart
similarity index 98%
rename from pkgs/leak_tracker/test/tests/leak_tracking/leak_testing_test.dart
rename to pkgs/leak_tracker_testing/test/leak_testing_test.dart
index 261e7ed..2470432 100644
--- a/pkgs/leak_tracker/test/tests/leak_tracking/leak_testing_test.dart
+++ b/pkgs/leak_tracker_testing/test/leak_testing_test.dart
@@ -2,8 +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.
 
-import 'package:leak_tracker/src/leak_tracking/leak_testing.dart';
 import 'package:leak_tracker/src/leak_tracking/primitives/model.dart';
+import 'package:leak_tracker_testing/src/leak_testing.dart';
 import 'package:test/test.dart';
 
 void main() {