From f8ffe3f75384fbca7a62a8d8bed947fd723e490b Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 11 Dec 2023 08:59:59 -0800 Subject: [PATCH 01/46] Update model.dart --- .../lib/src/leak_tracking/primitives/model.dart | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart index c6f713da..e3563aaa 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart @@ -29,11 +29,15 @@ class IgnoredLeaksSet { /// in case when you want to preserve list of classes, while temporarily turning off /// the entire leak tracking, so that when you turn it back on for a subset of tests /// with `copyWith(ignoreAll: false)`, the list of classes is set to needed value. - const IgnoredLeaksSet({this.byClass = const {}, this.ignoreAll = false}); + const IgnoredLeaksSet({ + this.byClass = const {}, + this.ignoreAll = false, + }); const IgnoredLeaksSet.ignore() : this(ignoreAll: true, byClass: const {}); - const IgnoredLeaksSet.byClass(this.byClass) : ignoreAll = false; + const IgnoredLeaksSet.byClass(Map byClass) + : this(byClass: byClass); /// Classes to ignore during leak tracking. /// @@ -123,6 +127,7 @@ class IgnoredLeaks { const IgnoredLeaks({ this.notGCed = const IgnoredLeaksSet(), this.notDisposed = const IgnoredLeaksSet(), + this.creationFrames = const {}, }); /// Ignore list for notGCed leaks. @@ -131,6 +136,9 @@ class IgnoredLeaks { /// Ignore list for notDisposed leaks. final IgnoredLeaksSet notDisposed; + /// A leak will be ignored if one of the object creation stack frames is listed in [creationFrames]. + final Set creationFrames; + /// Returns true if the class is ignored. /// /// If [leakType] is null, returns true if the class is ignored for all From 4fe85fc7cb44c18f3adf7ad19e88b36d23e251b1 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 16 Dec 2023 20:22:44 -0800 Subject: [PATCH 02/46] - --- .github/workflows/ci.yaml | 4 ++++ pkgs/leak_tracker/analysis_options.yaml | 1 + pkgs/leak_tracker_testing/analysis_options.yaml | 1 + pkgs/memory_usage/analysis_options.yaml | 7 +++++++ 4 files changed, 13 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d876067c..fea3e18d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -35,6 +35,10 @@ jobs: run: dart test working-directory: pkgs/leak_tracker + - name: dart test + run: dart test + working-directory: pkgs/leak_tracker_testing + - name: flutter test run: flutter test --enable-vmservice working-directory: pkgs/leak_tracker_flutter_testing diff --git a/pkgs/leak_tracker/analysis_options.yaml b/pkgs/leak_tracker/analysis_options.yaml index 50af61ae..dbb38f45 100644 --- a/pkgs/leak_tracker/analysis_options.yaml +++ b/pkgs/leak_tracker/analysis_options.yaml @@ -11,3 +11,4 @@ linter: - avoid_print - comment_references - only_throw_errors + - unawaited_futures diff --git a/pkgs/leak_tracker_testing/analysis_options.yaml b/pkgs/leak_tracker_testing/analysis_options.yaml index 50af61ae..dbb38f45 100644 --- a/pkgs/leak_tracker_testing/analysis_options.yaml +++ b/pkgs/leak_tracker_testing/analysis_options.yaml @@ -11,3 +11,4 @@ linter: - avoid_print - comment_references - only_throw_errors + - unawaited_futures diff --git a/pkgs/memory_usage/analysis_options.yaml b/pkgs/memory_usage/analysis_options.yaml index d978f811..e6ebe45a 100644 --- a/pkgs/memory_usage/analysis_options.yaml +++ b/pkgs/memory_usage/analysis_options.yaml @@ -1 +1,8 @@ include: package:dart_flutter_team_lints/analysis_options.yaml + +linter: + rules: + - avoid_catching_errors + - comment_references + - only_throw_errors + - unawaited_futures From 6f0036247bd1436e2d71dfcc37e76e2c698d0880 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sun, 17 Dec 2023 17:33:30 -0800 Subject: [PATCH 03/46] Create test_helpers_test.dart --- .../test/tests/end_to_end/test_helpers_test.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart new file mode 100644 index 00000000..6f59ce31 --- /dev/null +++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart @@ -0,0 +1,10 @@ +// 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:test/test.dart'; + +/// These tests +void main() { + test('Leak is declared without helper', () {}); +} From 4b8e35f55771d4b416983c06aa6781d3eb6a3ab9 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sun, 17 Dec 2023 19:31:21 -0800 Subject: [PATCH 04/46] - --- .../src/leak_tracking/_object_tracker.dart | 2 +- .../src/leak_tracking/primitives/model.dart | 6 ++-- .../src/test_classes.dart} | 30 +++++++++++++++- .../test/test_infra/dart_classes.dart | 29 ---------------- .../tests/end_to_end/test_helpers_test.dart | 34 +++++++++++++++++-- 5 files changed, 65 insertions(+), 36 deletions(-) rename pkgs/leak_tracker_flutter_testing/{test/test_infra/flutter_classes.dart => lib/src/test_classes.dart} (54%) delete mode 100644 pkgs/leak_tracker_flutter_testing/test/test_infra/dart_classes.dart diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart b/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart index 40834854..058b6de2 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart @@ -89,7 +89,7 @@ class ObjectTracker implements LeakProvider { void _declareNotDisposedLeak(ObjectRecord record) { if (record.isGCedLateLeak(disposalTime, numberOfGcCycles)) { _objects.gcedLateLeaks.add(record); - } else if (record.isNotDisposedLeak) { + } else if (!record.isDisposed) { _objects.gcedNotDisposedLeaks.add(record); } diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart index e3563aaa..048329fd 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart @@ -127,7 +127,7 @@ class IgnoredLeaks { const IgnoredLeaks({ this.notGCed = const IgnoredLeaksSet(), this.notDisposed = const IgnoredLeaksSet(), - this.creationFrames = const {}, + this.createdByTestHelpers = false, }); /// Ignore list for notGCed leaks. @@ -136,8 +136,8 @@ class IgnoredLeaks { /// Ignore list for notDisposed leaks. final IgnoredLeaksSet notDisposed; - /// A leak will be ignored if one of the object creation stack frames is listed in [creationFrames]. - final Set creationFrames; + /// Leaking objects created by test helpers will be ignored. + final bool createdByTestHelpers; /// Returns true if the class is ignored. /// diff --git a/pkgs/leak_tracker_flutter_testing/test/test_infra/flutter_classes.dart b/pkgs/leak_tracker_flutter_testing/lib/src/test_classes.dart similarity index 54% rename from pkgs/leak_tracker_flutter_testing/test/test_infra/flutter_classes.dart rename to pkgs/leak_tracker_flutter_testing/lib/src/test_classes.dart index bdd5aada..d3d8063e 100644 --- a/pkgs/leak_tracker_flutter_testing/test/test_infra/flutter_classes.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/test_classes.dart @@ -3,11 +3,13 @@ // BSD-style license that can be found in the LICENSE file. import 'package:flutter/widgets.dart'; +import 'package:leak_tracker/leak_tracker.dart'; -import 'dart_classes.dart'; +// The classes are declared not under `test` to test [IgnoredLeaks.testHelpers]. final _notGcedStorage = []; +@visibleForTesting class StatelessLeakingWidget extends StatelessWidget { StatelessLeakingWidget({ super.key, @@ -31,3 +33,29 @@ class StatelessLeakingWidget extends StatelessWidget { return const Placeholder(); } } + +@visibleForTesting +class LeakTrackedClass { + LeakTrackedClass() { + LeakTracking.dispatchObjectCreated( + library: library, + className: '$LeakTrackedClass', + object: this, + ); + } + + static const library = 'package:my_package/lib/src/my_lib.dart'; + + void dispose() { + LeakTracking.dispatchObjectDisposed(object: this); + } +} + +final _notGCedObjects = []; + +@visibleForTesting +class LeakingClass { + LeakingClass() { + _notGCedObjects.add(LeakTrackedClass()..dispose()); + } +} diff --git a/pkgs/leak_tracker_flutter_testing/test/test_infra/dart_classes.dart b/pkgs/leak_tracker_flutter_testing/test/test_infra/dart_classes.dart deleted file mode 100644 index b182a5fb..00000000 --- a/pkgs/leak_tracker_flutter_testing/test/test_infra/dart_classes.dart +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'package:leak_tracker/leak_tracker.dart'; - -class LeakTrackedClass { - LeakTrackedClass() { - LeakTracking.dispatchObjectCreated( - library: library, - className: '$LeakTrackedClass', - object: this, - ); - } - - static const library = 'package:my_package/lib/src/my_lib.dart'; - - void dispose() { - LeakTracking.dispatchObjectDisposed(object: this); - } -} - -final _notGCedObjects = []; - -class LeakingClass { - LeakingClass() { - _notGCedObjects.add(LeakTrackedClass()..dispose()); - } -} diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart index 6f59ce31..abd217a5 100644 --- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart +++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart @@ -2,9 +2,39 @@ // for 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/cupertino.dart'; +import 'package:leak_tracker/leak_tracker.dart'; +import 'package:leak_tracker_flutter_testing/src/test_classes.dart'; import 'package:test/test.dart'; -/// These tests +/// These tests verify that value of +/// [IgnoredLeaks.createdByTestHelpers] is respected. void main() { - test('Leak is declared without helper', () {}); + setUp(() { + LeakTracking.start(config: LeakTrackingConfig.passive()); + LeakTracking.phase = + PhaseSettings(ignoredLeaks: IgnoredLeaks(createdByTestHelpers: true)); + }); + + tearDown(() { + LeakTracking.stop(); + }); + + test('Prod leak is detected.', () async { + StatelessLeakingWidget(); + + LeakTracking.declareNotDisposedObjectsAsLeaks(); + final leaks = await LeakTracking.collectLeaks(); + expect(leaks.notDisposed.length, 1); + }); + + test('Test leak is ignored.', () async { + createTestWidget(); + + LeakTracking.declareNotDisposedObjectsAsLeaks(); + final leaks = await LeakTracking.collectLeaks(); + expect(leaks.notDisposed.length, 0); + }); } + +StatelessLeakingWidget createTestWidget() => StatelessLeakingWidget(); From b57b706e55b976d5a32c40b3642942c4c4b5b4fc Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 19 Dec 2023 10:53:56 -0800 Subject: [PATCH 05/46] - --- .../src/leak_tracking/_object_tracker.dart | 11 ++- .../primitives/_test_helper_detector.dart | 74 +++++++++++++++++++ .../tests/end_to_end/test_helpers_test.dart | 14 +++- .../lib/src/leak_testing.dart | 2 + 4 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart b/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart index 058b6de2..ebec06b4 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart @@ -15,6 +15,7 @@ import 'primitives/_finalizer.dart'; import 'primitives/_gc_counter.dart'; import 'primitives/_retaining_path/_connection.dart'; import 'primitives/_retaining_path/_retaining_path.dart'; +import 'primitives/_test_helper_detector.dart'; import 'primitives/model.dart'; /// Keeps collection of object records until @@ -62,11 +63,19 @@ class ObjectTracker implements LeakProvider { throwIfDisposed(); if (phase.ignoreLeaks) return; + StackTrace? stackTrace; + + if (phase.ignoredLeaks.createdByTestHelpers) { + stackTrace = StackTrace.current; + if (isCreatedByTestHelper(stackTrace)) return; + } + final record = _objects.notGCed.putIfAbsent(object, context, phase, trackedClass); if (phase.leakDiagnosticConfig.collectStackTraceOnStart) { - record.setContext(ContextKeys.startCallstack, StackTrace.current); + stackTrace ??= StackTrace.current; + record.setContext(ContextKeys.startCallstack, stackTrace); } _finalizer.attach(object, record); diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart new file mode 100644 index 00000000..2efccbf9 --- /dev/null +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -0,0 +1,74 @@ +// 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. + +/// Frames pointing the folder `test` or the package `flutter_test`. +const _testHelperFrame = r'(?:\/test\/|\(package:flutter_test\/)'; + +/// If a stack frame contains this string, it is start of test. +const _testClosureSign = r' main. \(file:\/\/\/'; + +const _anyText = r'[\S\s]*'; + +final _expr = + RegExp('$_testHelperFrame$_anyText$_testClosureSign', multiLine: true); + +bool isCreatedByTestHelper(StackTrace trace) { + return _expr.hasMatch(trace.toString()); +} + +// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) +// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) +// #3 new LeakTrackedClass (package:leak_tracker_flutter_testing/src/test_classes.dart:40:18) +// #4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/test_classes.dart:20:27) +// #5 main. (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:30:5) +// #6 Declarer.test.. (package:test_api/src/backend/declarer.dart:215:19) +// +// #7 Declarer.test. (package:test_api/src/backend/declarer.dart:213:7) +// +// #8 Invoker._waitForOutstandingCallbacks. (package:test_api/src/backend/invoker.dart:258:9) +// + +// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) +// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) +// #3 new LeakTrackedClass (package:leak_tracker_flutter_testing/src/test_classes.dart:40:18) +// #4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/test_classes.dart:24:33) +// #5 main. (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:30:5) +// #6 Declarer.test.. (package:test_api/src/backend/declarer.dart:215:19) +// +// #7 Declarer.test. (package:test_api/src/backend/declarer.dart:213:7) +// +// #8 Invoker._waitForOutstandingCallbacks. (package:test_api/src/backend/invoker.dart:258:9) +// + +// ✓ Prod leak is detected. +// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) +// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) +// #3 new LeakTrackedClass (package:leak_tracker_flutter_testing/src/test_classes.dart:40:18) +// #4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/test_classes.dart:20:27) +// #5 createTestWidget (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:46:46) +// #6 main. (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:38:5) +// #7 Declarer.test.. (package:test_api/src/backend/declarer.dart:215:19) +// +// #8 Declarer.test. (package:test_api/src/backend/declarer.dart:213:7) +// +// #9 Invoker._waitForOutstandingCallbacks. (package:test_api/src/backend/invoker.dart:258:9) +// + +// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) +// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) +// #3 new LeakTrackedClass (package:leak_tracker_flutter_testing/src/test_classes.dart:40:18) +// #4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/test_classes.dart:24:33) +// #5 createTestWidget (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:46:46) +// #6 main. (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:38:5) +// #7 Declarer.test.. (package:test_api/src/backend/declarer.dart:215:19) +// +// #8 Declarer.test. (package:test_api/src/backend/declarer.dart:213:7) +// +// #9 Invoker._waitForOutstandingCallbacks. (package:test_api/src/backend/invoker.dart:258:9) +// + diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart index abd217a5..6bb6ac22 100644 --- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart +++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart'; import 'package:leak_tracker/leak_tracker.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import 'package:leak_tracker_flutter_testing/src/test_classes.dart'; import 'package:test/test.dart'; @@ -11,13 +12,18 @@ import 'package:test/test.dart'; /// [IgnoredLeaks.createdByTestHelpers] is respected. void main() { setUp(() { - LeakTracking.start(config: LeakTrackingConfig.passive()); - LeakTracking.phase = - PhaseSettings(ignoredLeaks: IgnoredLeaks(createdByTestHelpers: true)); + LeakTesting.collectedLeaksReporter = (leaks) {}; + maybeSetupLeakTrackingForTest( + LeakTesting.settings.withTrackedAll().withIgnored( + allNotGCed: true, + createdByTestHelpers: true, + ), + '-', + ); }); tearDown(() { - LeakTracking.stop(); + maybeTearDownLeakTrackingForAll(); }); test('Prod leak is detected.', () async { diff --git a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart index ee29348a..d1ce5eee 100644 --- a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart +++ b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart @@ -108,6 +108,7 @@ class LeakTesting { Map notDisposed = const {}, bool allNotDisposed = false, List classes = const [], + bool createdByTestHelpers = false, }) { Map addClassesToMap( Map map, @@ -133,6 +134,7 @@ class LeakTesting { ignoreAll: allNotDisposed, ), ), + createdByTestHelpers: createdByTestHelpers, ), ); } From 04a4a8ed3b819cdc4847521247b5cfc947b3207d Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 19 Dec 2023 10:54:11 -0800 Subject: [PATCH 06/46] Update test_helpers_test.dart --- .../test/tests/end_to_end/test_helpers_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart index 6bb6ac22..e41daa62 100644 --- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart +++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart @@ -2,8 +2,6 @@ // for 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/cupertino.dart'; -import 'package:leak_tracker/leak_tracker.dart'; import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import 'package:leak_tracker_flutter_testing/src/test_classes.dart'; import 'package:test/test.dart'; From ac83246bb262e06bbfab421f08db375e1805290e Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 19 Dec 2023 13:52:03 -0800 Subject: [PATCH 07/46] Update leak_testing.dart --- pkgs/leak_tracker_testing/lib/src/leak_testing.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart index d1ce5eee..13c18f10 100644 --- a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart +++ b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart @@ -149,6 +149,7 @@ class LeakTesting { List classes = const [], bool allNotGCed = false, bool allNotDisposed = false, + bool createdByTestHelpers = false, }) { var newNotGCed = ignoredLeaks.notGCed.track([...notGCed, ...classes]); if (allNotGCed) { @@ -165,6 +166,7 @@ class LeakTesting { ignoredLeaks: IgnoredLeaks( notGCed: newNotGCed, notDisposed: newNotDisposed, + createdByTestHelpers: !createdByTestHelpers, ), ); return result; From b1f96fe6646f0a387b4a79763902bb79b6d12845 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 19 Dec 2023 15:55:44 -0800 Subject: [PATCH 08/46] Update _test_helper_detector.dart --- .../src/leak_tracking/primitives/_test_helper_detector.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index 2efccbf9..7d6a54fd 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -5,7 +5,9 @@ /// Frames pointing the folder `test` or the package `flutter_test`. const _testHelperFrame = r'(?:\/test\/|\(package:flutter_test\/)'; -/// If a stack frame contains this string, it is start of test. +/// Stack frame, containing this string, is start of a test. +/// +/// There are many spaces to make RegEx faster. const _testClosureSign = r' main. \(file:\/\/\/'; const _anyText = r'[\S\s]*'; From 8c1a4732f9cb3b3b30f0820078f165f9fbaa055b Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Wed, 20 Dec 2023 12:27:55 -0800 Subject: [PATCH 09/46] Update _test_helper_detector.dart --- .../src/leak_tracking/primitives/_test_helper_detector.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index 7d6a54fd..58f71db7 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -8,12 +8,12 @@ const _testHelperFrame = r'(?:\/test\/|\(package:flutter_test\/)'; /// Stack frame, containing this string, is start of a test. /// /// There are many spaces to make RegEx faster. -const _testClosureSign = r' main. \(file:\/\/\/'; +const _testStartFrame = r' main. \(file:\/\/\/'; const _anyText = r'[\S\s]*'; final _expr = - RegExp('$_testHelperFrame$_anyText$_testClosureSign', multiLine: true); + RegExp('$_testHelperFrame$_anyText$_testStartFrame', multiLine: true); bool isCreatedByTestHelper(StackTrace trace) { return _expr.hasMatch(trace.toString()); From d801df73feadae1507fa3d448f1da4f7b23b2798 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 21 Dec 2023 17:37:41 -0800 Subject: [PATCH 10/46] - --- pkgs/leak_tracker/pubspec.yaml | 2 +- pkgs/leak_tracker_flutter_testing/CHANGELOG.md | 4 ++++ pkgs/leak_tracker_flutter_testing/pubspec.yaml | 6 +++--- pkgs/leak_tracker_testing/CHANGELOG.md | 4 ++++ .../lib/src/leak_testing.dart | 15 +++++++++++++++ pkgs/leak_tracker_testing/pubspec.yaml | 2 +- 6 files changed, 28 insertions(+), 5 deletions(-) diff --git a/pkgs/leak_tracker/pubspec.yaml b/pkgs/leak_tracker/pubspec.yaml index feb2d8b4..411bdefd 100644 --- a/pkgs/leak_tracker/pubspec.yaml +++ b/pkgs/leak_tracker/pubspec.yaml @@ -1,5 +1,5 @@ name: leak_tracker -version: 9.0.18 +version: 10.0.0 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 cbc9a518..e751c9ce 100644 --- a/pkgs/leak_tracker_flutter_testing/CHANGELOG.md +++ b/pkgs/leak_tracker_flutter_testing/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.1 + +* Upgrade to leak_tracker 10.0.0 and leak_trecker_testing 2.0.1. + ## 2.0.0 * Remove declaration of testWidgetsWithLeakTracking. diff --git a/pkgs/leak_tracker_flutter_testing/pubspec.yaml b/pkgs/leak_tracker_flutter_testing/pubspec.yaml index 2fe47f1d..3d323172 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: 2.0.0 +version: 2.0.1 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 @@ -9,8 +9,8 @@ environment: dependencies: flutter: sdk: flutter - leak_tracker: '>=9.0.0 <11.0.0' - leak_tracker_testing: '>=1.0.5 <3.0.0' + leak_tracker: '>=10.0.0 <11.0.0' + leak_tracker_testing: '>=2.0.1 <3.0.0' matcher: ^0.12.16 meta: ^1.8.0 diff --git a/pkgs/leak_tracker_testing/CHANGELOG.md b/pkgs/leak_tracker_testing/CHANGELOG.md index d68a3339..9c57b0a1 100644 --- a/pkgs/leak_tracker_testing/CHANGELOG.md +++ b/pkgs/leak_tracker_testing/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.1 + +* Add LeakTesting.enabled. + ## 2.0.0 * Remove fields `failOnLeaksCollected` and `onLeaks` from `LeakTesting`. diff --git a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart index ee29348a..335a333b 100644 --- a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart +++ b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart @@ -40,6 +40,21 @@ class LeakTesting { this.baselining = const MemoryBaselining.none(), }); + static bool _enabled = false; + + /// If true leak tracking is inabled. + /// + /// If value is true before test method is invoked, [settings] will be respected. + /// Use this property to enable leak tracking. + /// + /// To turn leak tracking off/on for individual tests use [ignore]. + static bool get enabled => _enabled; + + /// Invoke in flutter_test_config.dart to enable leak tracking. + /// + /// Set [ignore] to true, to pause leak tracking after it is enabled. + static void enable() => _enabled = true; + /// Handler for memory leaks found in tests. /// /// Set it to analyse the leaks programmatically. diff --git a/pkgs/leak_tracker_testing/pubspec.yaml b/pkgs/leak_tracker_testing/pubspec.yaml index a2df8274..a7b64a2f 100644 --- a/pkgs/leak_tracker_testing/pubspec.yaml +++ b/pkgs/leak_tracker_testing/pubspec.yaml @@ -1,5 +1,5 @@ name: leak_tracker_testing -version: 2.0.0 +version: 2.0.1 description: Leak tracking code intended for usage in tests. repository: https://github.com/dart-lang/leak_tracker/tree/main/pkgs/leak_tracker_testing From f02b51a9b20e611e401786cb2beb153b4acc7655 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 21 Dec 2023 17:41:54 -0800 Subject: [PATCH 11/46] Update testing.dart --- pkgs/leak_tracker_flutter_testing/lib/src/testing.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart index 7d661fdb..4121576b 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart @@ -15,6 +15,8 @@ void maybeSetupLeakTrackingForTest( LeakTesting? settings, String testDescription, ) { + if (!LeakTesting.enabled) return; + final leakTesting = settings ?? LeakTesting.settings; if (leakTesting.ignore) return; @@ -38,7 +40,9 @@ void maybeSetupLeakTrackingForTest( /// If leak tracking is enabled, stops it and declares notDisposed objects as leaks. void maybeTearDownLeakTrackingForTest() { - if (!LeakTracking.isStarted || LeakTracking.phase.ignoreLeaks) return; + if (!LeakTesting.enabled || + !LeakTracking.isStarted || + LeakTracking.phase.ignoreLeaks) return; LeakTracking.phase = const PhaseSettings.ignored(); } @@ -46,7 +50,7 @@ void maybeTearDownLeakTrackingForTest() { /// /// Is noop if leak tracking is not started. Future maybeTearDownLeakTrackingForAll() async { - if (!LeakTracking.isStarted) { + if (!LeakTesting.enabled || !LeakTracking.isStarted) { return; } From 5c8cf7dffc056e990c052fe555e4931d50faada6 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 21 Dec 2023 20:37:59 -0800 Subject: [PATCH 12/46] Update testing_test.dart --- pkgs/leak_tracker_flutter_testing/test/tests/testing_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/testing_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/testing_test.dart index 6cfd6b50..584a0ee5 100644 --- a/pkgs/leak_tracker_flutter_testing/test/tests/testing_test.dart +++ b/pkgs/leak_tracker_flutter_testing/test/tests/testing_test.dart @@ -11,6 +11,7 @@ final LeakTesting settings = void main() { group('maybeSetupLeakTrackingForTest', () { setUp(() { + LeakTesting.enable(); LeakTesting.settings = LeakTesting.settings.withTrackedAll(); }); From e1f3ef146648aab4d1e7d0de0a0016a938af1ba7 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 22 Dec 2023 13:06:33 -0800 Subject: [PATCH 13/46] Update testing.dart --- pkgs/leak_tracker_flutter_testing/lib/src/testing.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart index 4121576b..d496d21c 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart @@ -51,6 +51,8 @@ void maybeTearDownLeakTrackingForTest() { /// Is noop if leak tracking is not started. Future maybeTearDownLeakTrackingForAll() async { if (!LeakTesting.enabled || !LeakTracking.isStarted) { + // Reporter is invoked so that test can verify the number of collected leaks is as expected. + LeakTesting.collectedLeaksReporter(Leaks({})); return; } From 5826392f803017e38aba97919a1be89ee82f07f5 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 22 Dec 2023 16:32:20 -0800 Subject: [PATCH 14/46] - --- .../primitives/_test_helper_detector.dart | 17 ++++++++++++++ .../lib/leak_tracker_flutter_testing.dart | 1 + .../src/{test_classes.dart => examples.dart} | 22 +++++++++---------- .../tests/end_to_end/test_helpers_test.dart | 1 - 4 files changed, 29 insertions(+), 12 deletions(-) rename pkgs/leak_tracker_flutter_testing/lib/src/{test_classes.dart => examples.dart} (68%) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index 58f71db7..83bce019 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -16,9 +16,26 @@ final _expr = RegExp('$_testHelperFrame$_anyText$_testStartFrame', multiLine: true); bool isCreatedByTestHelper(StackTrace trace) { + // print(trace); + // print('\n\n\n'); return _expr.hasMatch(trace.toString()); } + +// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) +// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) +// #3 new LeakTrackedClass (file:///Users/polinach/_/flutter_dev/packages/flutter_test/test/utils/leaking_classes.dart:10:18) +// #4 new StatelessLeakingWidget (file:///Users/polinach/_/flutter_dev/packages/flutter_test/test/utils/leaking_classes.dart:39:27) +// #5 main. (file:///Users/polinach/_/flutter_dev/packages/flutter_test/test/widget_tester_leaks_test.dart:58:35) +// #6 testWidgets.. (package:flutter_test/src/widget_tester.dart:183:29) +// +// #7 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1017:5) +// +// #8 StackZoneSpecification._registerCallback. (package:stack_trace/src/stack_zone_specification.dart:114:42) +// + + // #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) // #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) // #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) 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 1b565d2a..a751ede4 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,6 +5,7 @@ export 'src/matchers.dart'; export 'src/model.dart'; export 'src/testing.dart'; +export 'src/examples.dart'; export 'package:leak_tracker/leak_tracker.dart' show Leaks, LeakTracking, IgnoredLeaks, LeakType, LeakReport; export 'package:leak_tracker_testing/leak_tracker_testing.dart' diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/test_classes.dart b/pkgs/leak_tracker_flutter_testing/lib/src/examples.dart similarity index 68% rename from pkgs/leak_tracker_flutter_testing/lib/src/test_classes.dart rename to pkgs/leak_tracker_flutter_testing/lib/src/examples.dart index d3d8063e..71535c52 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/test_classes.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/examples.dart @@ -7,9 +7,9 @@ import 'package:leak_tracker/leak_tracker.dart'; // The classes are declared not under `test` to test [IgnoredLeaks.testHelpers]. -final _notGcedStorage = []; +final _notGcedStorage = []; -@visibleForTesting +/// Example of stateless leaking widget. class StatelessLeakingWidget extends StatelessWidget { StatelessLeakingWidget({ super.key, @@ -17,11 +17,11 @@ class StatelessLeakingWidget extends StatelessWidget { this.notDisposed = true, }) { if (notGCed) { - _notGcedStorage.add(LeakTrackedClass()..dispose()); + _notGcedStorage.add(InstrumentedDisposable()..dispose()); } if (notDisposed) { // ignore: unused_local_variable - final notDisposedObject = LeakTrackedClass(); + final notDisposedObject = InstrumentedDisposable(); } } @@ -34,12 +34,12 @@ class StatelessLeakingWidget extends StatelessWidget { } } -@visibleForTesting -class LeakTrackedClass { - LeakTrackedClass() { +/// Example of instrumented disposable +class InstrumentedDisposable { + InstrumentedDisposable() { LeakTracking.dispatchObjectCreated( library: library, - className: '$LeakTrackedClass', + className: '$InstrumentedDisposable', object: this, ); } @@ -51,11 +51,11 @@ class LeakTrackedClass { } } -final _notGCedObjects = []; +final _notGCedObjects = []; -@visibleForTesting +/// Example of leaking class. class LeakingClass { LeakingClass() { - _notGCedObjects.add(LeakTrackedClass()..dispose()); + _notGCedObjects.add(InstrumentedDisposable()..dispose()); } } diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart index e41daa62..6b75123c 100644 --- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart +++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; -import 'package:leak_tracker_flutter_testing/src/test_classes.dart'; import 'package:test/test.dart'; /// These tests verify that value of From 000e93cdc1ef641890655aab911ab88139e83f62 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 22 Dec 2023 16:37:29 -0800 Subject: [PATCH 15/46] - --- pkgs/leak_tracker_flutter_testing/lib/src/testing.dart | 3 ++- pkgs/leak_tracker_testing/lib/src/leak_testing.dart | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart index 12ef577c..aed8873b 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing.dart @@ -52,7 +52,8 @@ void maybeTearDownLeakTrackingForTest() { /// Is noop if leak tracking is not started. Future maybeTearDownLeakTrackingForAll() async { if (!LeakTesting.enabled || !LeakTracking.isStarted) { - // Reporter is invoked so that test can verify the number of collected leaks is as expected. + // Reporter is invoked so that tests can verify the number of + // collected leaks is as expected. LeakTesting.collectedLeaksReporter(Leaks({})); return; } diff --git a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart index 627431c0..827e015e 100644 --- a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart +++ b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart @@ -44,7 +44,8 @@ class LeakTesting { /// If true leak tracking is inabled. /// - /// If value is true before test method is invoked, [settings] will be respected. + /// If value is true before test method is invoked, + /// [settings] will be respected. /// Use this property to enable leak tracking. /// /// To turn leak tracking off/on for individual tests use [ignore]. From d77c650451bb712b0d2dda9adadd4a53956e352d Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 22 Dec 2023 17:05:09 -0800 Subject: [PATCH 16/46] Update leak_tracker_flutter_testing.dart --- .../lib/leak_tracker_flutter_testing.dart | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) 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 fd3b31c4..485d6ae1 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 @@ -7,11 +7,7 @@ export 'package:leak_tracker/leak_tracker.dart' export 'package:leak_tracker_testing/leak_tracker_testing.dart' show LeakTesting, isLeakFree; +export 'src/examples.dart'; export 'src/matchers.dart'; export 'src/model.dart'; export 'src/testing.dart'; -export 'src/examples.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; From 378ee006fac0b4d430ed128813d92a7f6a38d3cc Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 22 Dec 2023 17:05:43 -0800 Subject: [PATCH 17/46] Update test_helpers_test.dart --- .../test/tests/end_to_end/test_helpers_test.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart index 6b75123c..ac989b0f 100644 --- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart +++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart @@ -19,9 +19,7 @@ void main() { ); }); - tearDown(() { - maybeTearDownLeakTrackingForAll(); - }); + tearDown(maybeTearDownLeakTrackingForAll); test('Prod leak is detected.', () async { StatelessLeakingWidget(); From 8ec30cf2644994311cc6cac402acb20022122475 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 22 Dec 2023 17:45:07 -0800 Subject: [PATCH 18/46] - --- pkgs/leak_tracker_testing/lib/src/leak_testing.dart | 3 ++- pkgs/leak_tracker_testing/test/leak_testing_test.dart | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart index 169ada89..e6b8d341 100644 --- a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart +++ b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart @@ -152,7 +152,8 @@ class LeakTesting { ignoreAll: allNotDisposed, ), ), - createdByTestHelpers: createdByTestHelpers, + createdByTestHelpers: + ignoredLeaks.createdByTestHelpers || createdByTestHelpers, ), ); } diff --git a/pkgs/leak_tracker_testing/test/leak_testing_test.dart b/pkgs/leak_tracker_testing/test/leak_testing_test.dart index 0d4441a2..94a3cf8f 100644 --- a/pkgs/leak_tracker_testing/test/leak_testing_test.dart +++ b/pkgs/leak_tracker_testing/test/leak_testing_test.dart @@ -11,6 +11,8 @@ void main() { test('debug info preserves other settings', () { final settings = LeakTesting.settings .withIgnored(notDisposed: {'MyClass': 1}) + .withIgnored(createdByTestHelpers: true) + .withIgnored() .withCreationStackTrace() .withDisposalStackTrace() .withRetainingPath(); @@ -31,6 +33,10 @@ void main() { settings.ignoredLeaks.notDisposed.byClass.keys.firstOrNull, 'MyClass', ); + expect( + settings.ignoredLeaks.createdByTestHelpers, + true, + ); }); group('withTracked', () { From 688da78eaa77baf6525639fed1e977944eb9e465 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 22 Dec 2023 17:56:58 -0800 Subject: [PATCH 19/46] Update _test_helper_detector.dart --- .../primitives/_test_helper_detector.dart | 59 ++++++++----------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index 83bce019..450f6d69 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -6,9 +6,7 @@ const _testHelperFrame = r'(?:\/test\/|\(package:flutter_test\/)'; /// Stack frame, containing this string, is start of a test. -/// -/// There are many spaces to make RegEx faster. -const _testStartFrame = r' main. \(file:\/\/\/'; +const _testStartFrame = r' main.'; const _anyText = r'[\S\s]*'; @@ -16,12 +14,32 @@ final _expr = RegExp('$_testHelperFrame$_anyText$_testStartFrame', multiLine: true); bool isCreatedByTestHelper(StackTrace trace) { - // print(trace); - // print('\n\n\n'); - return _expr.hasMatch(trace.toString()); + print(trace); + print('\n\n\n'); + final result = _expr.hasMatch(trace.toString()); + print(result); + print('\n\n\n'); + return result; } +// helper: +// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:126:35) +// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:135:6) +// #3 dispatchObjectEvent (package:leak_tracker/src/leak_tracking/primitives/_dispatcher.dart:48:20) +// #4 LeakTracking.dispatchObjectEvent. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:103:18) +// #5 LeakTracking.dispatchObjectEvent (package:leak_tracker/src/leak_tracking/leak_tracking.dart:109:6) +// #6 _dispatchFlutterEventToLeakTracker (package:leak_tracker_flutter_testing/src/testing.dart:73:23) +// #7 MemoryAllocations.dispatchObjectEvent (package:flutter/src/foundation/memory_allocations.dart:241:23) +// #8 MemoryAllocations.dispatchObjectCreated (package:flutter/src/foundation/memory_allocations.dart:275:5) +// #9 new GestureRecognizer (package:flutter/src/gestures/recognizer.dart:111:34) +// #10 new IndefiniteGestureRecognizer (file:///Users/polinach/_/flutter_dev/packages/flutter/test/gestures/recognizer_test.dart) +// #11 main.. (file:///Users/polinach/_/flutter_dev/packages/flutter/test/gestures/recognizer_test.dart:122:54) +// #12 testGesture.. (file:///Users/polinach/_/flutter_dev/packages/flutter/test/gestures/gesture_tester.dart:31:15) +// #13 FakeAsync.run.. (package:fake_async/fake_async.dart:182:54) + +// no helper: // #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) // #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) // #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) @@ -35,34 +53,7 @@ bool isCreatedByTestHelper(StackTrace trace) { // #8 StackZoneSpecification._registerCallback. (package:stack_trace/src/stack_zone_specification.dart:114:42) // - -// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) -// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) -// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) -// #3 new LeakTrackedClass (package:leak_tracker_flutter_testing/src/test_classes.dart:40:18) -// #4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/test_classes.dart:20:27) -// #5 main. (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:30:5) -// #6 Declarer.test.. (package:test_api/src/backend/declarer.dart:215:19) -// -// #7 Declarer.test. (package:test_api/src/backend/declarer.dart:213:7) -// -// #8 Invoker._waitForOutstandingCallbacks. (package:test_api/src/backend/invoker.dart:258:9) -// - -// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) -// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) -// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) -// #3 new LeakTrackedClass (package:leak_tracker_flutter_testing/src/test_classes.dart:40:18) -// #4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/test_classes.dart:24:33) -// #5 main. (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:30:5) -// #6 Declarer.test.. (package:test_api/src/backend/declarer.dart:215:19) -// -// #7 Declarer.test. (package:test_api/src/backend/declarer.dart:213:7) -// -// #8 Invoker._waitForOutstandingCallbacks. (package:test_api/src/backend/invoker.dart:258:9) -// - -// ✓ Prod leak is detected. +// helper: // #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) // #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) // #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) From bbb5cbcf74c03fb52f266b858aa70047116bba60 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 22 Dec 2023 17:57:36 -0800 Subject: [PATCH 20/46] Update _test_helper_detector.dart --- .../leak_tracking/primitives/_test_helper_detector.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index 450f6d69..db984c91 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -14,11 +14,11 @@ final _expr = RegExp('$_testHelperFrame$_anyText$_testStartFrame', multiLine: true); bool isCreatedByTestHelper(StackTrace trace) { - print(trace); - print('\n\n\n'); + // print(trace); + // print('\n\n\n'); final result = _expr.hasMatch(trace.toString()); - print(result); - print('\n\n\n'); + // print(result); + // print('\n\n\n'); return result; } From 06127827b8486d87740476d3a74360be89d4f4c4 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 23 Dec 2023 11:15:40 -0800 Subject: [PATCH 21/46] Update _test_helper_detector.dart --- .../primitives/_test_helper_detector.dart | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index db984c91..6a414959 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -6,7 +6,7 @@ const _testHelperFrame = r'(?:\/test\/|\(package:flutter_test\/)'; /// Stack frame, containing this string, is start of a test. -const _testStartFrame = r' main.'; +const _testStartFrame = r'(?:TestAsyncUtils.guard.| main.)'; const _anyText = r'[\S\s]*'; @@ -22,6 +22,25 @@ bool isCreatedByTestHelper(StackTrace trace) { return result; } +// helper: +// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:126:35) +// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:135:6) +// #3 dispatchObjectEvent (package:leak_tracker/src/leak_tracking/primitives/_dispatcher.dart:48:20) +// #4 LeakTracking.dispatchObjectEvent. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:103:18) +// #5 LeakTracking.dispatchObjectEvent (package:leak_tracker/src/leak_tracking/leak_tracking.dart:109:6) +// #6 _dispatchFlutterEventToLeakTracker (package:leak_tracker_flutter_testing/src/testing.dart:73:23) +// #7 MemoryAllocations.dispatchObjectEvent (package:flutter/src/foundation/memory_allocations.dart:241:23) +// #8 MemoryAllocations._imageOnCreate (package:flutter/src/foundation/memory_allocations.dart:315:5) +// #9 new Image._ (dart:ui/painting.dart:1688:15) +// #10 Image.clone (dart:ui/painting.dart:1895:18) +// #11 createTestImage. (package:flutter_test/src/image.dart:42:30) +// +// #12 TestAsyncUtils.guard. (package:flutter_test/src/test_async_utils.dart:117:7) +// +// #13 _AsyncCompleter.complete (dart:async/future_impl.dart:41:3) +// + // helper: // #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) // #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:126:35) From aab712083b9a9298974392aa55a7acbeae8812ce Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 23 Dec 2023 11:52:02 -0800 Subject: [PATCH 22/46] - --- .../src/leak_tracking/_object_tracker.dart | 2 +- .../primitives/_test_helper_detector.dart | 87 +----------- .../_test_helper_detector_test.dart | 129 ++++++++++++++++++ 3 files changed, 134 insertions(+), 84 deletions(-) create mode 100644 pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart b/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart index bc647993..fb2ba226 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart @@ -67,7 +67,7 @@ class ObjectTracker implements LeakProvider { if (phase.ignoredLeaks.createdByTestHelpers) { stackTrace = StackTrace.current; - if (isCreatedByTestHelper(stackTrace)) return; + if (isCreatedByTestHelper(stackTrace.toString())) return; } final record = diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index 6a414959..c163008c 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -6,98 +6,19 @@ const _testHelperFrame = r'(?:\/test\/|\(package:flutter_test\/)'; /// Stack frame, containing this string, is start of a test. -const _testStartFrame = r'(?:TestAsyncUtils.guard.| main.)'; +const _testStartFrame = + r'(?:TestAsyncUtils.guard.| main.)'; const _anyText = r'[\S\s]*'; final _expr = RegExp('$_testHelperFrame$_anyText$_testStartFrame', multiLine: true); -bool isCreatedByTestHelper(StackTrace trace) { +bool isCreatedByTestHelper(String trace) { // print(trace); // print('\n\n\n'); - final result = _expr.hasMatch(trace.toString()); + final result = _expr.hasMatch(trace); // print(result); // print('\n\n\n'); return result; } - -// helper: -// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) -// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:126:35) -// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:135:6) -// #3 dispatchObjectEvent (package:leak_tracker/src/leak_tracking/primitives/_dispatcher.dart:48:20) -// #4 LeakTracking.dispatchObjectEvent. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:103:18) -// #5 LeakTracking.dispatchObjectEvent (package:leak_tracker/src/leak_tracking/leak_tracking.dart:109:6) -// #6 _dispatchFlutterEventToLeakTracker (package:leak_tracker_flutter_testing/src/testing.dart:73:23) -// #7 MemoryAllocations.dispatchObjectEvent (package:flutter/src/foundation/memory_allocations.dart:241:23) -// #8 MemoryAllocations._imageOnCreate (package:flutter/src/foundation/memory_allocations.dart:315:5) -// #9 new Image._ (dart:ui/painting.dart:1688:15) -// #10 Image.clone (dart:ui/painting.dart:1895:18) -// #11 createTestImage. (package:flutter_test/src/image.dart:42:30) -// -// #12 TestAsyncUtils.guard. (package:flutter_test/src/test_async_utils.dart:117:7) -// -// #13 _AsyncCompleter.complete (dart:async/future_impl.dart:41:3) -// - -// helper: -// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) -// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:126:35) -// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:135:6) -// #3 dispatchObjectEvent (package:leak_tracker/src/leak_tracking/primitives/_dispatcher.dart:48:20) -// #4 LeakTracking.dispatchObjectEvent. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:103:18) -// #5 LeakTracking.dispatchObjectEvent (package:leak_tracker/src/leak_tracking/leak_tracking.dart:109:6) -// #6 _dispatchFlutterEventToLeakTracker (package:leak_tracker_flutter_testing/src/testing.dart:73:23) -// #7 MemoryAllocations.dispatchObjectEvent (package:flutter/src/foundation/memory_allocations.dart:241:23) -// #8 MemoryAllocations.dispatchObjectCreated (package:flutter/src/foundation/memory_allocations.dart:275:5) -// #9 new GestureRecognizer (package:flutter/src/gestures/recognizer.dart:111:34) -// #10 new IndefiniteGestureRecognizer (file:///Users/polinach/_/flutter_dev/packages/flutter/test/gestures/recognizer_test.dart) -// #11 main.. (file:///Users/polinach/_/flutter_dev/packages/flutter/test/gestures/recognizer_test.dart:122:54) -// #12 testGesture.. (file:///Users/polinach/_/flutter_dev/packages/flutter/test/gestures/gesture_tester.dart:31:15) -// #13 FakeAsync.run.. (package:fake_async/fake_async.dart:182:54) - - -// no helper: -// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) -// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) -// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) -// #3 new LeakTrackedClass (file:///Users/polinach/_/flutter_dev/packages/flutter_test/test/utils/leaking_classes.dart:10:18) -// #4 new StatelessLeakingWidget (file:///Users/polinach/_/flutter_dev/packages/flutter_test/test/utils/leaking_classes.dart:39:27) -// #5 main. (file:///Users/polinach/_/flutter_dev/packages/flutter_test/test/widget_tester_leaks_test.dart:58:35) -// #6 testWidgets.. (package:flutter_test/src/widget_tester.dart:183:29) -// -// #7 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1017:5) -// -// #8 StackZoneSpecification._registerCallback. (package:stack_trace/src/stack_zone_specification.dart:114:42) -// - -// helper: -// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) -// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) -// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) -// #3 new LeakTrackedClass (package:leak_tracker_flutter_testing/src/test_classes.dart:40:18) -// #4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/test_classes.dart:20:27) -// #5 createTestWidget (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:46:46) -// #6 main. (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:38:5) -// #7 Declarer.test.. (package:test_api/src/backend/declarer.dart:215:19) -// -// #8 Declarer.test. (package:test_api/src/backend/declarer.dart:213:7) -// -// #9 Invoker._waitForOutstandingCallbacks. (package:test_api/src/backend/invoker.dart:258:9) -// - -// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) -// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) -// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) -// #3 new LeakTrackedClass (package:leak_tracker_flutter_testing/src/test_classes.dart:40:18) -// #4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/test_classes.dart:24:33) -// #5 createTestWidget (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:46:46) -// #6 main. (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:38:5) -// #7 Declarer.test.. (package:test_api/src/backend/declarer.dart:215:19) -// -// #8 Declarer.test. (package:test_api/src/backend/declarer.dart:213:7) -// -// #9 Invoker._waitForOutstandingCallbacks. (package:test_api/src/backend/invoker.dart:258:9) -// - diff --git a/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart b/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart new file mode 100644 index 00000000..27a8920f --- /dev/null +++ b/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart @@ -0,0 +1,129 @@ +import 'package:leak_tracker/src/leak_tracking/primitives/_test_helper_detector.dart'; +import 'package:test/test.dart'; + +class _Test { + final String stackTrace; + final bool isHelper; + final String name; + + _Test({required this.stackTrace, required this.isHelper, required this.name}); +} + +final _tests = [ + _Test( + name: 'empty', + isHelper: false, + stackTrace: '', + ), + _Test( + name: 'no test helper', + isHelper: false, + stackTrace: ''' +#0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +#1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) +#2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) +#3 new LeakTrackedClass (package:leak_tracker/src/leak_tracking/leak_tracking.dart:10:18) +#4 new StatelessLeakingWidget (package:leak_tracker/src/leak_tracking/leak_tracking.dart:39:27) +#5 main. (file:///Users/polinach/_/flutter_dev/packages/flutter_test/test/widget_tester_leaks_test.dart:58:35) +#6 testWidgets.. (package:flutter_test/src/widget_tester.dart:183:29) + +#7 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1017:5) + +#8 StackZoneSpecification._registerCallback. (package:stack_trace/src/stack_zone_specification.dart:114:42) + +''', + ), + _Test( + name: 'test helper, runAsync and pumpWidget', + isHelper: true, + stackTrace: ''' +#0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +#1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:126:35) +#2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:135:6) +#3 dispatchObjectEvent (package:leak_tracker/src/leak_tracking/primitives/_dispatcher.dart:48:20) +#4 LeakTracking.dispatchObjectEvent. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:103:18) +#5 LeakTracking.dispatchObjectEvent (package:leak_tracker/src/leak_tracking/leak_tracking.dart:109:6) +#6 _dispatchFlutterEventToLeakTracker (package:leak_tracker_flutter_testing/src/testing.dart:73:23) +#7 MemoryAllocations.dispatchObjectEvent (package:flutter/src/foundation/memory_allocations.dart:241:23) +#8 MemoryAllocations._imageOnCreate (package:flutter/src/foundation/memory_allocations.dart:315:5) +#9 new Image._ (dart:ui/painting.dart:1688:15) +#10 Image.clone (dart:ui/painting.dart:1895:18) +#11 createTestImage. (package:flutter_test/src/image.dart:42:30) + +#12 TestAsyncUtils.guard. (package:flutter_test/src/test_async_utils.dart:117:7) + +#13 _AsyncCompleter.complete (dart:async/future_impl.dart:41:3) + +''', + ), + _Test( + name: 'no test helper, runAsync and pumpWidget', + isHelper: false, + stackTrace: ''' +#0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +#1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:126:35) +#2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:135:6) +#3 dispatchObjectEvent (package:leak_tracker/src/leak_tracking/primitives/_dispatcher.dart:48:20) +#4 LeakTracking.dispatchObjectEvent. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:103:18) +#5 LeakTracking.dispatchObjectEvent (package:leak_tracker/src/leak_tracking/leak_tracking.dart:109:6) +#6 _dispatchFlutterEventToLeakTracker (package:leak_tracker_flutter_testing/src/testing.dart:73:23) +#7 MemoryAllocations.dispatchObjectEvent (package:flutter/src/foundation/memory_allocations.dart:241:23) +#8 MemoryAllocations._imageOnCreate (package:flutter/src/foundation/memory_allocations.dart:315:5) +#9 new Image._ (dart:ui/painting.dart:1688:15) +#10 Image.clone (dart:ui/painting.dart:1895:18) +#11 createImage. (package:myLibrary/src/image.dart:42:30) + +#12 TestAsyncUtils.guard. (package:flutter_test/src/test_async_utils.dart:117:7) + +#13 _AsyncCompleter.complete (dart:async/future_impl.dart:41:3) + +''', + ), + _Test( + name: 'test-only GestureRecognizer', + isHelper: true, + stackTrace: ''' +#0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +#1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:126:35) +#2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:135:6) +#3 dispatchObjectEvent (package:leak_tracker/src/leak_tracking/primitives/_dispatcher.dart:48:20) +#4 LeakTracking.dispatchObjectEvent. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:103:18) +#5 LeakTracking.dispatchObjectEvent (package:leak_tracker/src/leak_tracking/leak_tracking.dart:109:6) +#6 _dispatchFlutterEventToLeakTracker (package:leak_tracker_flutter_testing/src/testing.dart:73:23) +#7 MemoryAllocations.dispatchObjectEvent (package:flutter/src/foundation/memory_allocations.dart:241:23) +#8 MemoryAllocations.dispatchObjectCreated (package:flutter/src/foundation/memory_allocations.dart:275:5) +#9 new GestureRecognizer (package:flutter/src/gestures/recognizer.dart:111:34) +#10 new IndefiniteGestureRecognizer (file:///Users/polinach/_/flutter_dev/packages/flutter/test/gestures/recognizer_test.dart) +#11 main.. (file:///Users/polinach/_/flutter_dev/packages/flutter/test/gestures/recognizer_test.dart:122:54) +#12 testGesture.. (file:///Users/polinach/_/flutter_dev/packages/flutter/test/gestures/gesture_tester.dart:31:15) +#13 FakeAsync.run.. (package:fake_async/fake_async.dart:182:54) +''', + ), + _Test( + name: 'factory method', + isHelper: true, + stackTrace: ''' +// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) +// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) +// #3 new LeakTrackedClass (package:leak_tracker_flutter_testing/src/test_classes.dart:40:18) +// #4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/test_classes.dart:20:27) +// #5 createTestWidget (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:46:46) +// #6 main. (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:38:5) +// #7 Declarer.test.. (package:test_api/src/backend/declarer.dart:215:19) +// +// #8 Declarer.test. (package:test_api/src/backend/declarer.dart:213:7) +// +// #9 Invoker._waitForOutstandingCallbacks. (package:test_api/src/backend/invoker.dart:258:9) +// +''', + ), +]; + +void main() { + for (final t in _tests) { + test('isCreatedByTestHelper: ${t.name}', () { + expect(isCreatedByTestHelper(t.stackTrace), t.isHelper); + }); + } +} From 01c05a6bd7a2d2cb02077c9df2cbff47db2259ad Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sun, 24 Dec 2023 18:26:23 -0800 Subject: [PATCH 23/46] - --- .../primitives/_test_helper_detector.dart | 26 ++++++++-------- .../lib/src/shared/shared_model.dart | 14 +++++++++ .../_test_helper_detector_test.dart | 31 ++++++++++--------- 3 files changed, 43 insertions(+), 28 deletions(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index c163008c..8da09b3a 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -5,20 +5,20 @@ /// Frames pointing the folder `test` or the package `flutter_test`. const _testHelperFrame = r'(?:\/test\/|\(package:flutter_test\/)'; -/// Stack frame, containing this string, is start of a test. -const _testStartFrame = - r'(?:TestAsyncUtils.guard.| main.)'; - -const _anyText = r'[\S\s]*'; +/// Frames inside flutter_test, but not pointing a test helper. +const _exception = + r'(?:WidgetTester.runAsync \(package:flutter_test/src/widget_tester.dart:)'; -final _expr = - RegExp('$_testHelperFrame$_anyText$_testStartFrame', multiLine: true); +/// Start of a test or closure inside test. +const _startFrame = + r'(?:TestAsyncUtils.guard.| main.)'; bool isCreatedByTestHelper(String trace) { - // print(trace); - // print('\n\n\n'); - final result = _expr.hasMatch(trace); - // print(result); - // print('\n\n\n'); - return result; + final frames = trace.split('\n'); + for (final frame in frames) { + if (RegExp(_exception).hasMatch(frame)) continue; + if (RegExp(_testHelperFrame).hasMatch(frame)) return true; + if (RegExp(_startFrame).hasMatch(frame)) return false; + } + return false; } diff --git a/pkgs/leak_tracker/lib/src/shared/shared_model.dart b/pkgs/leak_tracker/lib/src/shared/shared_model.dart index 675eeedf..8d70441e 100644 --- a/pkgs/leak_tracker/lib/src/shared/shared_model.dart +++ b/pkgs/leak_tracker/lib/src/shared/shared_model.dart @@ -116,6 +116,20 @@ class Leaks { int get total => byType.values.map((e) => e.length).sum; + late final Map byPhase = () { + final leaks = >>{}; + for (final entry in byType.entries) { + for (final leak in entry.value) { + leaks[leak.phase] ??= {}; + leaks[leak.phase]![entry.key] ??= []; + leaks[leak.phase]![entry.key]!.add(leak); + } + } + return { + for (final entry in leaks.entries) entry.key: Leaks(entry.value), + }; + }(); + String toYaml({required bool phasesAreTests}) { if (total == 0) return ''; final leaks = LeakType.values diff --git a/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart b/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart index 27a8920f..161f5f77 100644 --- a/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart +++ b/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart @@ -2,9 +2,9 @@ import 'package:leak_tracker/src/leak_tracking/primitives/_test_helper_detector. import 'package:test/test.dart'; class _Test { + final String name; final String stackTrace; final bool isHelper; - final String name; _Test({required this.stackTrace, required this.isHelper, required this.name}); } @@ -34,7 +34,7 @@ final _tests = [ ''', ), _Test( - name: 'test helper, runAsync and pumpWidget', + name: 'test helper, inside runAsync and pumpWidget', isHelper: true, stackTrace: ''' #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) @@ -57,25 +57,26 @@ final _tests = [ ''', ), _Test( - name: 'no test helper, runAsync and pumpWidget', + name: 'no test helper, inside runAsync and pumpWidget', isHelper: false, stackTrace: ''' #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:126:35) #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:135:6) -#3 dispatchObjectEvent (package:leak_tracker/src/leak_tracking/primitives/_dispatcher.dart:48:20) -#4 LeakTracking.dispatchObjectEvent. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:103:18) -#5 LeakTracking.dispatchObjectEvent (package:leak_tracker/src/leak_tracking/leak_tracking.dart:109:6) -#6 _dispatchFlutterEventToLeakTracker (package:leak_tracker_flutter_testing/src/testing.dart:73:23) -#7 MemoryAllocations.dispatchObjectEvent (package:flutter/src/foundation/memory_allocations.dart:241:23) -#8 MemoryAllocations._imageOnCreate (package:flutter/src/foundation/memory_allocations.dart:315:5) -#9 new Image._ (dart:ui/painting.dart:1688:15) -#10 Image.clone (dart:ui/painting.dart:1895:18) -#11 createImage. (package:myLibrary/src/image.dart:42:30) +#3 new InstrumentedDisposable (package:leak_tracker_flutter_testing/src/examples.dart:40:18) +#4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/examples.dart:20:27) +#5 main.. (file:///Users/polinach/_/flutter_dev/packages/flutter_test/test/widget_tester_leaks_test.dart:93:31) +#6 AutomatedTestWidgetsFlutterBinding.runAsync. (package:flutter_test/src/binding.dart:1308:17) +#7 _rootRun (dart:async/zone.dart:1399:13) +#8 _CustomZone.run (dart:async/zone.dart:1301:19) +#9 AutomatedTestWidgetsFlutterBinding.runAsync (package:flutter_test/src/binding.dart:1304:26) +#10 WidgetTester.runAsync (package:flutter_test/src/widget_tester.dart:831:17) +#11 main. (file:///Users/polinach/_/flutter_dev/packages/flutter_test/test/widget_tester_leaks_test.dart:92:18) +#12 testWidgets.. (package:flutter_test/src/widget_tester.dart:183:29) -#12 TestAsyncUtils.guard. (package:flutter_test/src/test_async_utils.dart:117:7) +#13 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1017:5) -#13 _AsyncCompleter.complete (dart:async/future_impl.dart:41:3) +#14 StackZoneSpecification._registerCallback. (package:stack_trace/src/stack_zone_specification.dart:114:42) ''', ), @@ -100,7 +101,7 @@ final _tests = [ ''', ), _Test( - name: 'factory method', + name: 'test-only factory method', isHelper: true, stackTrace: ''' // #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) From e779e7e3a20dad3d22dcba5c99042f4620a356e9 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 25 Dec 2023 07:19:08 -0800 Subject: [PATCH 24/46] - --- .../lib/leak_tracker_flutter_testing.dart | 2 +- .../lib/src/testing_for_testing/README.md | 2 + .../{ => testing_for_testing}/examples.dart | 0 .../src/testing_for_testing/test_case.dart | 81 +++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md rename pkgs/leak_tracker_flutter_testing/lib/src/{ => testing_for_testing}/examples.dart (100%) create mode 100644 pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart 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 485d6ae1..2921af44 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 @@ -7,7 +7,7 @@ export 'package:leak_tracker/leak_tracker.dart' export 'package:leak_tracker_testing/leak_tracker_testing.dart' show LeakTesting, isLeakFree; -export 'src/examples.dart'; +export 'src/testing_for_testing/examples.dart'; export 'src/matchers.dart'; export 'src/model.dart'; export 'src/testing.dart'; diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md new file mode 100644 index 00000000..387d98a4 --- /dev/null +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md @@ -0,0 +1,2 @@ +This forlder contains model and tests to test that test methods +test leaks as expected. diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/examples.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/examples.dart similarity index 100% rename from pkgs/leak_tracker_flutter_testing/lib/src/examples.dart rename to pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/examples.dart diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart new file mode 100644 index 00000000..2e667c99 --- /dev/null +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart @@ -0,0 +1,81 @@ +// Copyright 2014 The Flutter Authors. 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/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:leak_tracker/leak_tracker.dart'; +import 'package:leak_tracker_testing/leak_tracker_testing.dart'; +import 'package:matcher/expect.dart'; + +typedef PumpWidgetsCallback = Future Function( + Widget widget, [ + Duration? duration, +]); + +typedef RunAsyncCallback = Future Function( + Future Function() callback, +); + +typedef TestCallback = Future Function( + PumpWidgetsCallback? pumpWidgetsCallback, + RunAsyncCallback? runAsyncCallback, +); + +class TestCase { + final String name; + final TestCallback body; + final int notDisposedTotal; + final int notGCedTotal; + final int notDisposedInHelpers; + final int notGCedInHelpers; + + TestCase({ + required this.name, + required this.body, + this.notDisposedTotal = 0, + this.notGCedTotal = 0, + this.notDisposedInHelpers = 0, + this.notGCedInHelpers = 0, + }); + + /// Verifies [leaks] contain expected number of leaks for the test [testDescription]. + void _verifyLeaks(Leaks leaks, String testDescription, LeakTesting settings) { + for (final LeakType type in expectedContextKeys.keys) { + final List leaks = testLeaks.byType[type] ?? []; + final List expectedKeys = expectedContextKeys[type]!..sort(); + for (final LeakReport leak in leaks) { + final List actualKeys = + leak.context?.keys.toList() ?? []; + expect(actualKeys..sort(), equals(expectedKeys), + reason: '$testDescription, $type'); + } + } + + _verifyLeakList( + testLeaks.notDisposed, + notDisposed, + name, + ); + _verifyLeakList( + testLeaks.notGCed, + notGCed, + testDescription, + ); + } + + void _verifyLeakList( + List list, + int expectedTotalLeaks, + int expectedInHelpersLeaks, + String testDescription, + List expectedContextKeys, + bool ignoreHelpers, + ) { + final expectedCount = ignoreHelpers + ? expectedTotalLeaks - expectedInHelpersLeaks + : expectedTotalLeaks; + + expect(list.length, expectedCount, reason: testDescription); + } +} From 277fed35b11f7532319e1de9887a4ad1be1c3454 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 25 Dec 2023 07:31:32 -0800 Subject: [PATCH 25/46] Update leak_testing.dart --- pkgs/leak_tracker_testing/lib/src/leak_testing.dart | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart index 827e015e..032bc7e5 100644 --- a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart +++ b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart @@ -42,18 +42,20 @@ class LeakTesting { static bool _enabled = false; - /// If true leak tracking is inabled. + /// If true leak tracking is enabled. /// - /// If value is true before test method is invoked, - /// [settings] will be respected. + /// If value is true before a test `main` started, + /// [settings] will be respected during testing. /// Use this property to enable leak tracking. /// - /// To turn leak tracking off/on for individual tests use [ignore]. + /// To turn leak tracking off/on for individual tests + /// after enabling, use [ignore]. static bool get enabled => _enabled; /// Invoke in flutter_test_config.dart to enable leak tracking. /// - /// Set [ignore] to true, to pause leak tracking after it is enabled. + /// Use [withIgnoredAll] and [withTrackedAll], to pause/resume + /// leak tracking after it is enabled. static void enable() => _enabled = true; /// Handler for memory leaks found in tests. From 2603191d2f76c2cf457df41dab1b17f89c49b4fd Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 25 Dec 2023 07:33:00 -0800 Subject: [PATCH 26/46] Update leak_testing.dart --- pkgs/leak_tracker_testing/lib/src/leak_testing.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart index 032bc7e5..b1af4954 100644 --- a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart +++ b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart @@ -42,7 +42,7 @@ class LeakTesting { static bool _enabled = false; - /// If true leak tracking is enabled. + /// If true, leak tracking is enabled. /// /// If value is true before a test `main` started, /// [settings] will be respected during testing. From 2dedfa285e882d803f2d6c6c8d8f8e83f5c7092c Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 25 Dec 2023 14:23:08 -0800 Subject: [PATCH 27/46] Update test_case.dart --- .../src/testing_for_testing/test_case.dart | 73 ++++++++++++------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart index 2e667c99..7d9ad04f 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart @@ -22,7 +22,7 @@ typedef TestCallback = Future Function( RunAsyncCallback? runAsyncCallback, ); -class TestCase { +class LeakTestCase { final String name; final TestCallback body; final int notDisposedTotal; @@ -30,7 +30,7 @@ class TestCase { final int notDisposedInHelpers; final int notGCedInHelpers; - TestCase({ + LeakTestCase({ required this.name, required this.body, this.notDisposedTotal = 0, @@ -40,42 +40,59 @@ class TestCase { }); /// Verifies [leaks] contain expected number of leaks for the test [testDescription]. - void _verifyLeaks(Leaks leaks, String testDescription, LeakTesting settings) { - for (final LeakType type in expectedContextKeys.keys) { - final List leaks = testLeaks.byType[type] ?? []; - final List expectedKeys = expectedContextKeys[type]!..sort(); - for (final LeakReport leak in leaks) { - final List actualKeys = - leak.context?.keys.toList() ?? []; - expect(actualKeys..sort(), equals(expectedKeys), - reason: '$testDescription, $type'); - } - } + void verifyLeaks(Leaks leaks, String testDescription, LeakTesting settings) { + final expectedContextKeys = [ + if (settings.leakDiagnosticConfig.collectStackTraceOnStart) + ContextKeys.startCallstack, + if (settings.leakDiagnosticConfig.collectStackTraceOnDisposal) + ContextKeys.disposalCallstack, + ]; _verifyLeakList( - testLeaks.notDisposed, - notDisposed, - name, + testDescription, + LeakType.notDisposed, + leaks, + expectedCount: notDisposedTotal - + (settings.ignoredLeaks.createdByTestHelpers + ? notDisposedInHelpers + : 0), + expectedContextKeys: expectedContextKeys, ); + + if (settings.leakDiagnosticConfig.collectRetainingPathForNotGCed) { + expectedContextKeys.add(ContextKeys.retainingPath); + } + _verifyLeakList( - testLeaks.notGCed, - notGCed, testDescription, + LeakType.notGCed, + leaks, + expectedCount: notGCedTotal - + (settings.ignoredLeaks.createdByTestHelpers ? notGCedInHelpers : 0), + expectedContextKeys: expectedContextKeys, ); } void _verifyLeakList( - List list, - int expectedTotalLeaks, - int expectedInHelpersLeaks, String testDescription, - List expectedContextKeys, - bool ignoreHelpers, - ) { - final expectedCount = ignoreHelpers - ? expectedTotalLeaks - expectedInHelpersLeaks - : expectedTotalLeaks; + LeakType type, + Leaks leaks, { + required int expectedCount, + required List expectedContextKeys, + }) { + final list = leaks.byType[type] ?? []; + + expect( + list.length, + expectedCount, + reason: testDescription, + ); - expect(list.length, expectedCount, reason: testDescription); + // Verify context keys. + for (final leak in list) { + final actualKeys = leak.context?.keys.toList() ?? []; + expect(actualKeys..sort(), equals(expectedContextKeys..sort()), + reason: '$testDescription, $type'); + } } } From 2f1d091243673d0d92110d4b8db6eceade25c44d Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 25 Dec 2023 14:27:07 -0800 Subject: [PATCH 28/46] - --- .../lib/leak_tracker_flutter_testing.dart | 2 +- .../lib/src/testing_for_testing/test_case.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 2921af44..4e4ffd0a 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 @@ -7,7 +7,7 @@ export 'package:leak_tracker/leak_tracker.dart' export 'package:leak_tracker_testing/leak_tracker_testing.dart' show LeakTesting, isLeakFree; -export 'src/testing_for_testing/examples.dart'; export 'src/matchers.dart'; export 'src/model.dart'; export 'src/testing.dart'; +export 'src/testing_for_testing/examples.dart'; diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart index 7d9ad04f..d11c8dfc 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart @@ -39,7 +39,7 @@ class LeakTestCase { this.notGCedInHelpers = 0, }); - /// Verifies [leaks] contain expected number of leaks for the test [testDescription]. + /// Verifies [leaks] contain expected leaks for the test. void verifyLeaks(Leaks leaks, String testDescription, LeakTesting settings) { final expectedContextKeys = [ if (settings.leakDiagnosticConfig.collectStackTraceOnStart) From fda50bf8f13472ccb71f54832a39ea39c7d8ddeb Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 26 Dec 2023 10:56:10 -0800 Subject: [PATCH 29/46] - --- .../lib/leak_tracker_flutter_testing.dart | 4 +++- .../{examples.dart => leaking_classes.dart} | 2 +- .../src/testing_for_testing/test_case.dart | 10 ++++---- .../testing_for_testing/test_settings.dart | 24 +++++++++++++++++++ 4 files changed, 33 insertions(+), 7 deletions(-) rename pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/{examples.dart => leaking_classes.dart} (95%) create mode 100644 pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart 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 4e4ffd0a..85f0c0a1 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 @@ -10,4 +10,6 @@ export 'package:leak_tracker_testing/leak_tracker_testing.dart' export 'src/matchers.dart'; export 'src/model.dart'; export 'src/testing.dart'; -export 'src/testing_for_testing/examples.dart'; +export 'src/testing_for_testing/leaking_classes.dart'; +export 'src/testing_for_testing/test_case.dart'; +export 'src/testing_for_testing/test_settings.dart'; diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/examples.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/leaking_classes.dart similarity index 95% rename from pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/examples.dart rename to pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/leaking_classes.dart index 71535c52..f4a59337 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/examples.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/leaking_classes.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// 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. diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart index d11c8dfc..c417128e 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart @@ -1,6 +1,6 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// 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/cupertino.dart'; import 'package:flutter/material.dart'; @@ -18,8 +18,8 @@ typedef RunAsyncCallback = Future Function( ); typedef TestCallback = Future Function( - PumpWidgetsCallback? pumpWidgetsCallback, - RunAsyncCallback? runAsyncCallback, + PumpWidgetsCallback? pumpWidgets, + RunAsyncCallback? runAsync, ); class LeakTestCase { diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart new file mode 100644 index 00000000..ecc566fb --- /dev/null +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart @@ -0,0 +1,24 @@ +// 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:leak_tracker_testing/leak_tracker_testing.dart'; + +final _trackingOn = LeakTesting.settings + .withTrackedAll() + .withTracked(allNotDisposed: true, allNotGCed: true); + +final Map leakTestingCases = { + 'on': _trackingOn, + 'off': _trackingOn.withIgnoredAll(), + 'notGCed off': _trackingOn.withIgnored(allNotGCed: true), + 'notDisposed off': _trackingOn.withIgnored(allNotDisposed: true), + 'testHelpers off': _trackingOn.withIgnored(createdByTestHelpers: true), + 'creation trace': _trackingOn.withCreationStackTrace(), + 'disposal trace': _trackingOn.withDisposalStackTrace(), + 'retaining path': _trackingOn.withRetainingPath(), + 'all diagnostics': _trackingOn + .withCreationStackTrace() + .withDisposalStackTrace() + .withRetainingPath(), +}; From 8762c46353992b56f33d7d3f1fd236d64e2d7cb6 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 26 Dec 2023 14:00:05 -0800 Subject: [PATCH 30/46] Update test_settings.dart --- .../lib/src/testing_for_testing/test_settings.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart index ecc566fb..eab2ce18 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart @@ -8,7 +8,7 @@ final _trackingOn = LeakTesting.settings .withTrackedAll() .withTracked(allNotDisposed: true, allNotGCed: true); -final Map leakTestingCases = { +final Map leakTestingSettingsCases = { 'on': _trackingOn, 'off': _trackingOn.withIgnoredAll(), 'notGCed off': _trackingOn.withIgnored(allNotGCed: true), From 4e2dae6794a6d8c4f3e726ed47884ecd7b94748f Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 26 Dec 2023 14:31:56 -0800 Subject: [PATCH 31/46] - --- pkgs/leak_tracker/lib/src/shared/shared_model.dart | 2 ++ .../lib/src/testing_for_testing/test_case.dart | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/leak_tracker/lib/src/shared/shared_model.dart b/pkgs/leak_tracker/lib/src/shared/shared_model.dart index 8d70441e..a3d967bb 100644 --- a/pkgs/leak_tracker/lib/src/shared/shared_model.dart +++ b/pkgs/leak_tracker/lib/src/shared/shared_model.dart @@ -90,6 +90,8 @@ class LeakSummary { class Leaks { Leaks(this.byType); + Leaks.empty() : this({}); + factory Leaks.fromJson(Map json) => Leaks( json.map( (key, value) => MapEntry( diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart index c417128e..73b6f879 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart @@ -40,7 +40,7 @@ class LeakTestCase { }); /// Verifies [leaks] contain expected leaks for the test. - void verifyLeaks(Leaks leaks, String testDescription, LeakTesting settings) { + void verifyLeaks(Leaks leaks, LeakTesting settings, {String testDescription}) { final expectedContextKeys = [ if (settings.leakDiagnosticConfig.collectStackTraceOnStart) ContextKeys.startCallstack, From c6f2ece115ab36ead6ffacec4ededb7aaa8b324e Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Tue, 26 Dec 2023 14:36:55 -0800 Subject: [PATCH 32/46] Update test_case.dart --- .../lib/src/testing_for_testing/test_case.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart index 73b6f879..c5c59253 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart @@ -40,7 +40,8 @@ class LeakTestCase { }); /// Verifies [leaks] contain expected leaks for the test. - void verifyLeaks(Leaks leaks, LeakTesting settings, {String testDescription}) { + void verifyLeaks(Leaks leaks, LeakTesting settings, + {required String testDescription}) { final expectedContextKeys = [ if (settings.leakDiagnosticConfig.collectStackTraceOnStart) ContextKeys.startCallstack, From 9d77ef813f1d661a80fd02f2fcba5c399129701d Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 30 Dec 2023 08:07:56 -0800 Subject: [PATCH 33/46] Update test_settings.dart --- .../lib/src/testing_for_testing/test_settings.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart index eab2ce18..d577d594 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart @@ -9,8 +9,8 @@ final _trackingOn = LeakTesting.settings .withTracked(allNotDisposed: true, allNotGCed: true); final Map leakTestingSettingsCases = { - 'on': _trackingOn, - 'off': _trackingOn.withIgnoredAll(), + 'tracking on': _trackingOn, + 'tracking off': _trackingOn.withIgnoredAll(), 'notGCed off': _trackingOn.withIgnored(allNotGCed: true), 'notDisposed off': _trackingOn.withIgnored(allNotDisposed: true), 'testHelpers off': _trackingOn.withIgnored(createdByTestHelpers: true), From 8cd992047c086b35c660a834aa0deeda255db2b5 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Thu, 4 Jan 2024 18:20:42 -0800 Subject: [PATCH 34/46] - --- .../primitives/_test_helper_detector.dart | 22 ++++++++++++------- .../src/leak_tracking/primitives/model.dart | 7 ++++++ .../testing_for_testing/test_settings.dart | 22 +++++++++---------- .../lib/src/leak_testing.dart | 3 +++ 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index 8da09b3a..1b2a94f2 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -3,22 +3,28 @@ // BSD-style license that can be found in the LICENSE file. /// Frames pointing the folder `test` or the package `flutter_test`. -const _testHelperFrame = r'(?:\/test\/|\(package:flutter_test\/)'; +const _testHelperFrame = RegExp(r'(?:\/test\/|\(package:flutter_test\/)'); -/// Frames inside flutter_test, but not pointing a test helper. +/// Frames that match [_testHelperFrame], but are not test helpers. const _exception = - r'(?:WidgetTester.runAsync \(package:flutter_test/src/widget_tester.dart:)'; + RegExp(r'(?:WidgetTester.runAsync \(package:flutter_test/src/widget_tester.dart:)'); /// Start of a test or closure inside test. const _startFrame = - r'(?:TestAsyncUtils.guard.| main.)'; + RegExp(r'(?:TestAsyncUtils.guard.| main.)'); -bool isCreatedByTestHelper(String trace) { +bool isCreatedByTestHelper(String trace, RegExp? exception) { final frames = trace.split('\n'); for (final frame in frames) { - if (RegExp(_exception).hasMatch(frame)) continue; - if (RegExp(_testHelperFrame).hasMatch(frame)) return true; - if (RegExp(_startFrame).hasMatch(frame)) return false; + if (_exception.hasMatch(frame)) { + continue; + } + if (_testHelperFrame.hasMatch(frame)) { + return true; + } + if (_startFrame.hasMatch(frame)) { + return false; + } } return false; } diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart index 61a3dfc9..01fec96f 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart @@ -129,6 +129,7 @@ class IgnoredLeaks { this.notGCed = const IgnoredLeaksSet(), this.notDisposed = const IgnoredLeaksSet(), this.createdByTestHelpers = false, + this.testHelperExceptions = const [], }); /// Ignore list for notGCed leaks. @@ -140,6 +141,12 @@ class IgnoredLeaks { /// Leaking objects created by test helpers will be ignored. final bool createdByTestHelpers; + /// If a stack frame matches this pattern, it will not be considered as test helper. + /// + /// Is used when [createdByTestHelpers] is true, to test functionality of + /// the leak tracker. + final List testHelperExceptions; + /// Returns true if the class is ignored. /// /// If [leakType] is null, returns true if the class is ignored for all diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart index d577d594..a317f473 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart @@ -10,15 +10,15 @@ final _trackingOn = LeakTesting.settings final Map leakTestingSettingsCases = { 'tracking on': _trackingOn, - 'tracking off': _trackingOn.withIgnoredAll(), - 'notGCed off': _trackingOn.withIgnored(allNotGCed: true), - 'notDisposed off': _trackingOn.withIgnored(allNotDisposed: true), - 'testHelpers off': _trackingOn.withIgnored(createdByTestHelpers: true), - 'creation trace': _trackingOn.withCreationStackTrace(), - 'disposal trace': _trackingOn.withDisposalStackTrace(), - 'retaining path': _trackingOn.withRetainingPath(), - 'all diagnostics': _trackingOn - .withCreationStackTrace() - .withDisposalStackTrace() - .withRetainingPath(), + // 'tracking off': _trackingOn.withIgnoredAll(), + // 'notGCed off': _trackingOn.withIgnored(allNotGCed: true), + // 'notDisposed off': _trackingOn.withIgnored(allNotDisposed: true), + // 'testHelpers off': _trackingOn.withIgnored(createdByTestHelpers: true), + // 'creation trace': _trackingOn.withCreationStackTrace(), + // 'disposal trace': _trackingOn.withDisposalStackTrace(), + // 'retaining path': _trackingOn.withRetainingPath(), + // 'all diagnostics': _trackingOn + // .withCreationStackTrace() + // .withDisposalStackTrace() + // .withRetainingPath(), }; diff --git a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart index 6e3ecd8a..90b3874b 100644 --- a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart +++ b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart @@ -129,6 +129,7 @@ class LeakTesting { bool allNotDisposed = false, List classes = const [], bool createdByTestHelpers = false, + List testHelperExceptions = const [], }) { Map addClassesToMap( Map map, @@ -156,6 +157,8 @@ class LeakTesting { ), createdByTestHelpers: ignoredLeaks.createdByTestHelpers || createdByTestHelpers, + testHelperExceptions: + ignoredLeaks.testHelperExceptions.addAll(ignoredLeaks.testHelperExceptions), ), ); } From d8617a5010b9dd63ffd8f0a4a75ee4afff6ac409 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 5 Jan 2024 06:22:25 -0800 Subject: [PATCH 35/46] - --- .../src/leak_tracking/_object_tracker.dart | 5 +++- .../primitives/_test_helper_detector.dart | 23 ++++++++++--------- .../src/leak_tracking/primitives/model.dart | 11 +++++++-- .../_test_helper_detector_test.dart | 2 +- .../testing_for_testing/test_settings.dart | 12 ++++++---- .../lib/src/leak_testing.dart | 10 +++++--- .../test/leak_testing_test.dart | 11 ++++++--- 7 files changed, 49 insertions(+), 25 deletions(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart b/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart index fb2ba226..42d36e0e 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/_object_tracker.dart @@ -67,7 +67,10 @@ class ObjectTracker implements LeakProvider { if (phase.ignoredLeaks.createdByTestHelpers) { stackTrace = StackTrace.current; - if (isCreatedByTestHelper(stackTrace.toString())) return; + if (isCreatedByTestHelper( + stackTrace.toString(), + phase.ignoredLeaks.testHelperExceptions, + )) return; } final record = diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index 1b2a94f2..43641266 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -3,28 +3,29 @@ // BSD-style license that can be found in the LICENSE file. /// Frames pointing the folder `test` or the package `flutter_test`. -const _testHelperFrame = RegExp(r'(?:\/test\/|\(package:flutter_test\/)'); +final _testHelperFrame = RegExp(r'(?:\/test\/|\(package:flutter_test\/)'); /// Frames that match [_testHelperFrame], but are not test helpers. -const _exception = - RegExp(r'(?:WidgetTester.runAsync \(package:flutter_test/src/widget_tester.dart:)'); +final _exception = RegExp( + r'(?:WidgetTester.runAsync \(package:flutter_test/src/widget_tester.dart:)'); /// Start of a test or closure inside test. -const _startFrame = - RegExp(r'(?:TestAsyncUtils.guard.| main.)'); +final _startFrame = RegExp( + r'(?:TestAsyncUtils.guard.| main.)'); -bool isCreatedByTestHelper(String trace, RegExp? exception) { +bool isCreatedByTestHelper(String trace, List exceptions) { final frames = trace.split('\n'); for (final frame in frames) { - if (_exception.hasMatch(frame)) { - continue; + if (_startFrame.hasMatch(frame)) { + return false; } if (_testHelperFrame.hasMatch(frame)) { + if (exceptions.any((exception) => exception.hasMatch(frame)) || + _exception.hasMatch(frame)) { + continue; + } return true; } - if (_startFrame.hasMatch(frame)) { - return false; - } } return false; } diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart index 01fec96f..3448034e 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart @@ -141,7 +141,7 @@ class IgnoredLeaks { /// Leaking objects created by test helpers will be ignored. final bool createdByTestHelpers; - /// If a stack frame matches this pattern, it will not be considered as test helper. + /// Stack frames that match this pattern, will not be treated as test helpers. /// /// Is used when [createdByTestHelpers] is true, to test functionality of /// the leak tracker. @@ -173,13 +173,20 @@ class IgnoredLeaks { } return other is IgnoredLeaks && other.notGCed == notGCed && - other.notDisposed == notDisposed; + other.notDisposed == notDisposed && + other.createdByTestHelpers == createdByTestHelpers && + const DeepCollectionEquality().equals( + other.testHelperExceptions, + testHelperExceptions, + ); } @override int get hashCode => Object.hash( notGCed, notDisposed, + createdByTestHelpers, + testHelperExceptions, ); } diff --git a/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart b/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart index 161f5f77..8fb1e094 100644 --- a/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart +++ b/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart @@ -124,7 +124,7 @@ final _tests = [ void main() { for (final t in _tests) { test('isCreatedByTestHelper: ${t.name}', () { - expect(isCreatedByTestHelper(t.stackTrace), t.isHelper); + expect(isCreatedByTestHelper(t.stackTrace, []), t.isHelper); }); } } diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart index a317f473..9b355fd6 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart @@ -4,11 +4,15 @@ import 'package:leak_tracker_testing/leak_tracker_testing.dart'; -final _trackingOn = LeakTesting.settings - .withTrackedAll() - .withTracked(allNotDisposed: true, allNotGCed: true); +LeakTesting _trackingOn(LeakTesting settings) { + final result = settings + .withTrackedAll() + .withTracked(allNotDisposed: true, allNotGCed: true); + return result; +} -final Map leakTestingSettingsCases = { +final Map + leakTestingSettingsCases = { 'tracking on': _trackingOn, // 'tracking off': _trackingOn.withIgnoredAll(), // 'notGCed off': _trackingOn.withIgnored(allNotGCed: true), diff --git a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart index 90b3874b..531c90b4 100644 --- a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart +++ b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart @@ -157,8 +157,10 @@ class LeakTesting { ), createdByTestHelpers: ignoredLeaks.createdByTestHelpers || createdByTestHelpers, - testHelperExceptions: - ignoredLeaks.testHelperExceptions.addAll(ignoredLeaks.testHelperExceptions), + testHelperExceptions: [ + ...ignoredLeaks.testHelperExceptions, + ...testHelperExceptions, + ], ), ); } @@ -190,7 +192,9 @@ class LeakTesting { ignoredLeaks: IgnoredLeaks( notGCed: newNotGCed, notDisposed: newNotDisposed, - createdByTestHelpers: !createdByTestHelpers, + createdByTestHelpers: + ignoredLeaks.createdByTestHelpers && !createdByTestHelpers, + testHelperExceptions: ignoredLeaks.testHelperExceptions, ), ); return result; diff --git a/pkgs/leak_tracker_testing/test/leak_testing_test.dart b/pkgs/leak_tracker_testing/test/leak_testing_test.dart index 94a3cf8f..08dabbd4 100644 --- a/pkgs/leak_tracker_testing/test/leak_testing_test.dart +++ b/pkgs/leak_tracker_testing/test/leak_testing_test.dart @@ -42,9 +42,11 @@ void main() { group('withTracked', () { test('not provided args do not affect the instance, tracked', () { final settings = LeakTesting.settings.withTrackedAll().withIgnored( - allNotDisposed: true, - allNotGCed: true, - ); + allNotDisposed: true, + allNotGCed: true, + createdByTestHelpers: true, + testHelperExceptions: [RegExp('my_test.dart')], + ); expect(settings.ignoredLeaks.notDisposed.ignoreAll, true); expect(settings.ignoredLeaks.notGCed.ignoreAll, true); @@ -54,6 +56,8 @@ void main() { expect(tracked.ignoredLeaks.notDisposed.ignoreAll, false); expect(tracked.ignoredLeaks.notGCed.ignoreAll, false); + expect(tracked.ignoredLeaks.createdByTestHelpers, true); + expect(tracked.ignoredLeaks.testHelperExceptions, hasLength(1)); }); }); @@ -81,6 +85,7 @@ void main() { allNotDisposed: true, allNotGCed: true, classes: ['MyClass'], + testHelperExceptions: [RegExp('my_test.dart')], ); expect(settings.ignore, true); From 8ae0506d93f1ab800e35325c61316bcd9ac40791 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 5 Jan 2024 06:32:40 -0800 Subject: [PATCH 36/46] - --- .../src/testing_for_testing/test_case.dart | 11 ++++++--- .../testing_for_testing/test_settings.dart | 23 ++++++++++--------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart index c5c59253..f62b7f05 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart @@ -45,14 +45,13 @@ class LeakTestCase { final expectedContextKeys = [ if (settings.leakDiagnosticConfig.collectStackTraceOnStart) ContextKeys.startCallstack, - if (settings.leakDiagnosticConfig.collectStackTraceOnDisposal) - ContextKeys.disposalCallstack, ]; _verifyLeakList( testDescription, LeakType.notDisposed, leaks, + ignore: settings.ignore || settings.ignoredLeaks.notDisposed.ignoreAll, expectedCount: notDisposedTotal - (settings.ignoredLeaks.createdByTestHelpers ? notDisposedInHelpers @@ -60,14 +59,19 @@ class LeakTestCase { expectedContextKeys: expectedContextKeys, ); + // Add diagnostics that is relevant for notGCed only. if (settings.leakDiagnosticConfig.collectRetainingPathForNotGCed) { expectedContextKeys.add(ContextKeys.retainingPath); } + if (settings.leakDiagnosticConfig.collectStackTraceOnDisposal) { + expectedContextKeys.add(ContextKeys.disposalCallstack); + } _verifyLeakList( testDescription, LeakType.notGCed, leaks, + ignore: settings.ignore || settings.ignoredLeaks.notGCed.ignoreAll, expectedCount: notGCedTotal - (settings.ignoredLeaks.createdByTestHelpers ? notGCedInHelpers : 0), expectedContextKeys: expectedContextKeys, @@ -80,12 +84,13 @@ class LeakTestCase { Leaks leaks, { required int expectedCount, required List expectedContextKeys, + required bool ignore, }) { final list = leaks.byType[type] ?? []; expect( list.length, - expectedCount, + ignore ? 0 : expectedCount, reason: testDescription, ); diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart index 9b355fd6..8ea25454 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart @@ -14,15 +14,16 @@ LeakTesting _trackingOn(LeakTesting settings) { final Map leakTestingSettingsCases = { 'tracking on': _trackingOn, - // 'tracking off': _trackingOn.withIgnoredAll(), - // 'notGCed off': _trackingOn.withIgnored(allNotGCed: true), - // 'notDisposed off': _trackingOn.withIgnored(allNotDisposed: true), - // 'testHelpers off': _trackingOn.withIgnored(createdByTestHelpers: true), - // 'creation trace': _trackingOn.withCreationStackTrace(), - // 'disposal trace': _trackingOn.withDisposalStackTrace(), - // 'retaining path': _trackingOn.withRetainingPath(), - // 'all diagnostics': _trackingOn - // .withCreationStackTrace() - // .withDisposalStackTrace() - // .withRetainingPath(), + 'tracking off': (s) => _trackingOn(s).withIgnoredAll(), + 'notGCed off': (s) => _trackingOn(s).withIgnored(allNotGCed: true), + 'notDisposed off': (s) => _trackingOn(s).withIgnored(allNotDisposed: true), + 'testHelpers off': (s) => + _trackingOn(s).withIgnored(createdByTestHelpers: true), + 'creation trace': (s) => _trackingOn(s).withCreationStackTrace(), + 'disposal trace': (s) => _trackingOn(s).withDisposalStackTrace(), + 'retaining path': (s) => _trackingOn(s).withRetainingPath(), + 'all diagnostics': (s) => _trackingOn(s) + .withCreationStackTrace() + .withDisposalStackTrace() + .withRetainingPath(), }; From 1697ca07f0b448d249b94dc4e75983c74101d9ae Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 5 Jan 2024 06:34:19 -0800 Subject: [PATCH 37/46] Update test_settings.dart --- .../lib/src/testing_for_testing/test_settings.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart index 8ea25454..a411b412 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart @@ -19,6 +19,8 @@ final Map 'notDisposed off': (s) => _trackingOn(s).withIgnored(allNotDisposed: true), 'testHelpers off': (s) => _trackingOn(s).withIgnored(createdByTestHelpers: true), + 'testHelpers on': (s) => + _trackingOn(s).withTracked(createdByTestHelpers: true), 'creation trace': (s) => _trackingOn(s).withCreationStackTrace(), 'disposal trace': (s) => _trackingOn(s).withDisposalStackTrace(), 'retaining path': (s) => _trackingOn(s).withRetainingPath(), From 7d7779f909f4639e634d250120684d09a990d857 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Fri, 5 Jan 2024 06:54:34 -0800 Subject: [PATCH 38/46] Update _test_helper_detector.dart --- .../primitives/_test_helper_detector.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index 43641266..f5144e36 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -7,11 +7,17 @@ final _testHelperFrame = RegExp(r'(?:\/test\/|\(package:flutter_test\/)'); /// Frames that match [_testHelperFrame], but are not test helpers. final _exception = RegExp( - r'(?:WidgetTester.runAsync \(package:flutter_test/src/widget_tester.dart:)'); + '(?:' + r'AutomatedTestWidgetsFlutterBinding.\w|' + r'WidgetTester.\w)', +); /// Start of a test or closure inside test. final _startFrame = RegExp( - r'(?:TestAsyncUtils.guard.| main.)'); + r'(?:' + r'TestAsyncUtils.guard.|' + r' main.)', +); bool isCreatedByTestHelper(String trace, List exceptions) { final frames = trace.split('\n'); From fba6c60f75904c33c75bd0a59a5e1303308afa24 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 6 Jan 2024 09:16:22 -0800 Subject: [PATCH 39/46] - --- .../primitives/_test_helper_detector.dart | 8 ++- .../test/test_infra/memory_leak_tests.dart | 56 +++++++++++++++++++ .../test/tests/end_to_end/testing_test.dart | 56 +++++++++++++++++++ .../lib/src/leak_testing.dart | 2 +- 4 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart create mode 100644 pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index f5144e36..d40b8b8d 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -6,13 +6,13 @@ final _testHelperFrame = RegExp(r'(?:\/test\/|\(package:flutter_test\/)'); /// Frames that match [_testHelperFrame], but are not test helpers. -final _exception = RegExp( +final _exceptions = RegExp( '(?:' r'AutomatedTestWidgetsFlutterBinding.\w|' r'WidgetTester.\w)', ); -/// Start of a test or closure inside test. +/// Test body or closure inside test body. final _startFrame = RegExp( r'(?:' r'TestAsyncUtils.guard.|' @@ -27,9 +27,11 @@ bool isCreatedByTestHelper(String trace, List exceptions) { } if (_testHelperFrame.hasMatch(frame)) { if (exceptions.any((exception) => exception.hasMatch(frame)) || - _exception.hasMatch(frame)) { + _exceptions.hasMatch(frame)) { continue; } + print('!!!!!'); + print(frame); return true; } } diff --git a/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart b/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart new file mode 100644 index 00000000..ad9bbe52 --- /dev/null +++ b/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart @@ -0,0 +1,56 @@ +// Copyright 2014 The Flutter Authors. 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/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; + +/// Objects that should not be GCed during. +final List _retainer = []; + +/// Test cases for memory leaks. +/// +/// They are separate from test execution to allow to except only them +/// from test helpers. +final List memoryLeakTests = [ + LeakTestCase( + name: 'no leaks', + body: (PumpWidgetsCallback? pumpWidgets, + RunAsyncCallback? runAsync) async { + Container(); + }, + ), + LeakTestCase( + name: 'not disposed disposable', + body: (PumpWidgetsCallback? pumpWidgets, + RunAsyncCallback? runAsync) async { + InstrumentedDisposable(); + }, + notDisposedTotal: 1, + ), + LeakTestCase( + name: 'not GCed disposable', + body: (PumpWidgetsCallback? pumpWidgets, + RunAsyncCallback? runAsync) async { + _retainer.add(InstrumentedDisposable()..dispose()); + }, + notGCedTotal: 1, + ), + LeakTestCase( + name: 'leaking widget', + body: (PumpWidgetsCallback? pumpWidgets, + RunAsyncCallback? runAsync) async { + StatelessLeakingWidget(); + }, + notDisposedTotal: 1, + notGCedTotal: 1, + ), +]; + +String memoryLeakTestsFilePath() { + return RegExp(r'(\/[^\/]*.dart):') + .firstMatch(StackTrace.current.toString())! + .group(1) + .toString(); +} diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart new file mode 100644 index 00000000..99d5b26f --- /dev/null +++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart @@ -0,0 +1,56 @@ +// Copyright 2023 The Chromium Authors. 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_flutter_testing/leak_tracker_flutter_testing.dart'; +import 'package:test/test.dart'; + +import '../../test_infra/memory_leak_tests.dart'; + +class _TestExecution { + _TestExecution( + {required this.settings, required this.settingName, required this.test}); + + final String settingName; + final LeakTesting settings; + final LeakTestCase test; + + String get name => '${test.name}, $settingName'; +} + +final List<_TestExecution> _testExecutions = <_TestExecution>[]; + +void main() { + LeakTesting.collectedLeaksReporter = _verifyLeaks; + LeakTesting.enable(); + LeakTesting.settings = LeakTesting.settings.withIgnored( + createdByTestHelpers: true, + testHelperExceptions: [RegExp(RegExp.escape(r'/test/test_infra/'))], + ); + + tearDown(maybeTearDownLeakTrackingForTest); + + tearDownAll(maybeTearDownLeakTrackingForAll); + + for (final t in memoryLeakTests) { + for (final settingsCase in leakTestingSettingsCases.entries) { + final settings = settingsCase.value(LeakTesting.settings); + final execution = _TestExecution( + settingName: settingsCase.key, test: t, settings: settings); + _testExecutions.add(execution); + + test(execution.name, () async { + maybeSetupLeakTrackingForTest(settings, execution.name); + await t.body(null, null); + }); + } + } +} + +void _verifyLeaks(Leaks leaks) { + for (final execution in _testExecutions) { + final testLeaks = leaks.byPhase[execution.name] ?? Leaks.empty(); + execution.test.verifyLeaks(testLeaks, execution.settings, + testDescription: execution.name); + } +} diff --git a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart index 531c90b4..8e74765b 100644 --- a/pkgs/leak_tracker_testing/lib/src/leak_testing.dart +++ b/pkgs/leak_tracker_testing/lib/src/leak_testing.dart @@ -34,7 +34,7 @@ import 'matchers.dart'; @immutable class LeakTesting { const LeakTesting._({ - this.ignore = true, + this.ignore = false, this.ignoredLeaks = const IgnoredLeaks(), this.leakDiagnosticConfig = const LeakDiagnosticConfig(), this.baselining = const MemoryBaselining.none(), From 229d5d4335be96729e27d019df735fecbd1c86aa Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 6 Jan 2024 09:23:01 -0800 Subject: [PATCH 40/46] Update _test_helper_detector.dart --- .../primitives/_test_helper_detector.dart | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index d40b8b8d..4501007c 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -3,20 +3,28 @@ // BSD-style license that can be found in the LICENSE file. /// Frames pointing the folder `test` or the package `flutter_test`. -final _testHelperFrame = RegExp(r'(?:\/test\/|\(package:flutter_test\/)'); +final _testHelperFrame = RegExp( + r'(?:' + + RegExp.escape(r'/test/') + + r'|' + + RegExp.escape(r'(package:flutter_test/') + + r')', +); /// Frames that match [_testHelperFrame], but are not test helpers. final _exceptions = RegExp( - '(?:' + r'(?:' r'AutomatedTestWidgetsFlutterBinding.\w|' - r'WidgetTester.\w)', + r'WidgetTester.\w' + ')', ); /// Test body or closure inside test body. final _startFrame = RegExp( r'(?:' r'TestAsyncUtils.guard.|' - r' main.)', + r' main.' + r')', ); bool isCreatedByTestHelper(String trace, List exceptions) { @@ -30,8 +38,6 @@ bool isCreatedByTestHelper(String trace, List exceptions) { _exceptions.hasMatch(frame)) { continue; } - print('!!!!!'); - print(frame); return true; } } From 6cedace99321053edd58ad47aa9da5aa7325f51b Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 6 Jan 2024 09:44:20 -0800 Subject: [PATCH 41/46] - --- .../test/test_infra/memory_leak_tests.dart | 13 +++++++++++++ .../test/test_infra/test_helpers.dart | 11 +++++++++++ .../test/tests/end_to_end/testing_test.dart | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 pkgs/leak_tracker_flutter_testing/test/test_infra/test_helpers.dart diff --git a/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart b/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart index ad9bbe52..9dbaf669 100644 --- a/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart +++ b/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart @@ -6,6 +6,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; +import 'test_helpers.dart'; + /// Objects that should not be GCed during. final List _retainer = []; @@ -46,6 +48,17 @@ final List memoryLeakTests = [ notDisposedTotal: 1, notGCedTotal: 1, ), + LeakTestCase( + name: 'leaks from test helpers', + body: (PumpWidgetsCallback? pumpWidgets, + RunAsyncCallback? runAsync) async { + createLeakingWidget(); + }, + notDisposedTotal: 1, + notGCedTotal: 1, + notDisposedInHelpers: 1, + notGCedInHelpers: 1, + ), ]; String memoryLeakTestsFilePath() { diff --git a/pkgs/leak_tracker_flutter_testing/test/test_infra/test_helpers.dart b/pkgs/leak_tracker_flutter_testing/test/test_infra/test_helpers.dart new file mode 100644 index 00000000..f1871171 --- /dev/null +++ b/pkgs/leak_tracker_flutter_testing/test/test_infra/test_helpers.dart @@ -0,0 +1,11 @@ +// Copyright 2014 The Flutter Authors. 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_flutter_testing/leak_tracker_flutter_testing.dart'; + +/// Test only function that create a leaking object. +/// +/// If test helpers are ignored in leak tracking settings, +/// leaks from objects created by this function will be ignored. +void createLeakingWidget() => StatelessLeakingWidget(); diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart index 99d5b26f..1c0e67a8 100644 --- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart +++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart @@ -25,7 +25,7 @@ void main() { LeakTesting.enable(); LeakTesting.settings = LeakTesting.settings.withIgnored( createdByTestHelpers: true, - testHelperExceptions: [RegExp(RegExp.escape(r'/test/test_infra/'))], + testHelperExceptions: [RegExp(RegExp.escape(memoryLeakTestsFilePath()))], ); tearDown(maybeTearDownLeakTrackingForTest); From fddae97ff59845f65d655fc21b6d7a2f62ba220f Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 6 Jan 2024 16:32:27 -0800 Subject: [PATCH 42/46] Update test_helpers_test.dart --- .../test/tests/end_to_end/test_helpers_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart index ac989b0f..da2ba126 100644 --- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart +++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart @@ -8,6 +8,8 @@ import 'package:test/test.dart'; /// These tests verify that value of /// [IgnoredLeaks.createdByTestHelpers] is respected. void main() { + setUpAll(LeakTesting.enable); + setUp(() { LeakTesting.collectedLeaksReporter = (leaks) {}; maybeSetupLeakTrackingForTest( From e12a1afe30b58448125f92eee0cb168db4f4fc81 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Sat, 6 Jan 2024 17:49:54 -0800 Subject: [PATCH 43/46] - --- .../src/leak_tracking/primitives/model.dart | 11 ++++++++-- .../lib/src/testing_for_testing/README.md | 6 ++++-- .../testing_for_testing/leaking_classes.dart | 4 +--- .../src/testing_for_testing/test_case.dart | 21 +++++++++++++++++++ .../testing_for_testing/test_settings.dart | 1 + 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart index 3448034e..8af0d50d 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart @@ -138,12 +138,19 @@ class IgnoredLeaks { /// Ignore list for notDisposed leaks. final IgnoredLeaksSet notDisposed; - /// Leaking objects created by test helpers will be ignored. + /// If true, leaking objects created by test helpers will be ignored. + /// + /// An object counts as created by a test helper if the stack trace of + /// start of leak tracking contains a frame, loactaed after the test body + /// frame, thet points to the folder `test` or the package `flutter_test`, + /// except: + /// * methods intended to be called from test body like `runAsunc` or `pump` + /// * frames that match [testHelperExceptions] final bool createdByTestHelpers; /// Stack frames that match this pattern, will not be treated as test helpers. /// - /// Is used when [createdByTestHelpers] is true, to test functionality of + /// Is used to test functionality of /// the leak tracker. final List testHelperExceptions; diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md index 387d98a4..da4449c4 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md @@ -1,2 +1,4 @@ -This forlder contains model and tests to test that test methods -test leaks as expected. +This forlder contains model and tests to test that methods like `testWidgets`, +that use API of this package, detect leaks as expected. + +See example of usage in [the test](../../../test/tests/end_to_end/testing_test.dart). diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/leaking_classes.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/leaking_classes.dart index f4a59337..13b34dba 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/leaking_classes.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/leaking_classes.dart @@ -5,8 +5,6 @@ import 'package:flutter/widgets.dart'; import 'package:leak_tracker/leak_tracker.dart'; -// The classes are declared not under `test` to test [IgnoredLeaks.testHelpers]. - final _notGcedStorage = []; /// Example of stateless leaking widget. @@ -34,7 +32,7 @@ class StatelessLeakingWidget extends StatelessWidget { } } -/// Example of instrumented disposable +/// Example of instrumented disposable. class InstrumentedDisposable { InstrumentedDisposable() { LeakTracking.dispatchObjectCreated( diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart index f62b7f05..1b36de7b 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart @@ -8,26 +8,41 @@ import 'package:leak_tracker/leak_tracker.dart'; import 'package:leak_tracker_testing/leak_tracker_testing.dart'; import 'package:matcher/expect.dart'; +/// Siugnature of `pumpWidget` method. typedef PumpWidgetsCallback = Future Function( Widget widget, [ Duration? duration, ]); +/// Siugnature of `runAsync` method. typedef RunAsyncCallback = Future Function( Future Function() callback, ); +/// Callback for test body, with access to Flutter specific test methods. typedef TestCallback = Future Function( PumpWidgetsCallback? pumpWidgets, RunAsyncCallback? runAsync, ); +/// A test case to verify leak detection. class LeakTestCase { + /// Name of the test. final String name; + + /// Test body. final TestCallback body; + + /// Expected number of not disposed objects. final int notDisposedTotal; + + /// Expected number of not GCed objects. final int notGCedTotal; + + /// Expected number of not disposed objects created by test helpers. final int notDisposedInHelpers; + + /// Expected number of not GCed objects created by test helpers. final int notGCedInHelpers; LeakTestCase({ @@ -40,6 +55,12 @@ class LeakTestCase { }); /// Verifies [leaks] contain expected leaks for the test. + /// + /// [settings] is used to determine: + /// * if some leaks should be ignored + /// * which diagnostics should be collected + /// + /// [testDescription] is used in description for the failed expectations. void verifyLeaks(Leaks leaks, LeakTesting settings, {required String testDescription}) { final expectedContextKeys = [ diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart index a411b412..a20951fc 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart @@ -11,6 +11,7 @@ LeakTesting _trackingOn(LeakTesting settings) { return result; } +/// Test cases for leak detection settings. final Map leakTestingSettingsCases = { 'tracking on': _trackingOn, From 7789fbd49a23f65f762e53c807b514e610dcf951 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Jan 2024 10:00:22 -0800 Subject: [PATCH 44/46] - --- .../primitives/_test_helper_detector.dart | 14 +++++++-- .../src/leak_tracking/primitives/model.dart | 7 +++-- .../lib/src/shared/shared_model.dart | 7 +++-- .../_test_helper_detector_test.dart | 30 +++++++++++-------- .../lib/src/testing_for_testing/README.md | 2 +- .../testing_for_testing/leaking_classes.dart | 2 +- .../src/testing_for_testing/test_case.dart | 2 +- .../testing_for_testing/test_settings.dart | 2 +- .../test/test_infra/memory_leak_tests.dart | 12 ++++---- .../test/test_infra/test_helpers.dart | 8 ++--- .../test/tests/end_to_end/testing_test.dart | 7 +++-- 11 files changed, 55 insertions(+), 38 deletions(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index 4501007c..eb3ed3aa 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2024, 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. @@ -27,8 +27,16 @@ final _startFrame = RegExp( r')', ); -bool isCreatedByTestHelper(String trace, List exceptions) { - final frames = trace.split('\n'); +/// If true, leaking objects created by test helpers will be ignored. +/// +/// Frames, that match [exceptions] will be ignored. +/// +/// See details in doc for `LeakTesting.createdByTestHelpers`. +bool isCreatedByTestHelper( + String objectCreationTrace, + List exceptions, +) { + final frames = objectCreationTrace.split('\n'); for (final frame in frames) { if (_startFrame.hasMatch(frame)) { return false; diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart index 8af0d50d..9ce3d8b7 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart @@ -141,17 +141,18 @@ class IgnoredLeaks { /// If true, leaking objects created by test helpers will be ignored. /// /// An object counts as created by a test helper if the stack trace of - /// start of leak tracking contains a frame, loactaed after the test body - /// frame, thet points to the folder `test` or the package `flutter_test`, + /// start of leak tracking contains a frame, located after the test body + /// frame, that points to the folder `test` or the package `flutter_test`, /// except: /// * methods intended to be called from test body like `runAsunc` or `pump` /// * frames that match [testHelperExceptions] final bool createdByTestHelpers; - /// Stack frames that match this pattern, will not be treated as test helpers. + /// Stack frames that match this pattern will not be treated as test helpers. /// /// Is used to test functionality of /// the leak tracker. + @visibleForTesting final List testHelperExceptions; /// Returns true if the class is ignored. diff --git a/pkgs/leak_tracker/lib/src/shared/shared_model.dart b/pkgs/leak_tracker/lib/src/shared/shared_model.dart index a3d967bb..7eb59db2 100644 --- a/pkgs/leak_tracker/lib/src/shared/shared_model.dart +++ b/pkgs/leak_tracker/lib/src/shared/shared_model.dart @@ -122,9 +122,10 @@ class Leaks { final leaks = >>{}; for (final entry in byType.entries) { for (final leak in entry.value) { - leaks[leak.phase] ??= {}; - leaks[leak.phase]![entry.key] ??= []; - leaks[leak.phase]![entry.key]!.add(leak); + leaks + .putIfAbsent(leak.phase, () => {}) + .putIfAbsent(entry.key, () => []) + .add(leak); } } return { diff --git a/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart b/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart index 8fb1e094..586c45e4 100644 --- a/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart +++ b/pkgs/leak_tracker/test/tests/leak_tracking/_primitives/_test_helper_detector_test.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2024, 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:leak_tracker/src/leak_tracking/primitives/_test_helper_detector.dart'; import 'package:test/test.dart'; @@ -104,19 +108,19 @@ final _tests = [ name: 'test-only factory method', isHelper: true, stackTrace: ''' -// #0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) -// #1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) -// #2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) -// #3 new LeakTrackedClass (package:leak_tracker_flutter_testing/src/test_classes.dart:40:18) -// #4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/test_classes.dart:20:27) -// #5 createTestWidget (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:46:46) -// #6 main. (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:38:5) -// #7 Declarer.test.. (package:test_api/src/backend/declarer.dart:215:19) -// -// #8 Declarer.test. (package:test_api/src/backend/declarer.dart:213:7) -// -// #9 Invoker._waitForOutstandingCallbacks. (package:test_api/src/backend/invoker.dart:258:9) -// +#0 ObjectTracker.startTracking (package:leak_tracker/src/leak_tracking/_object_tracker.dart:69:31) +#1 LeakTracking.dispatchObjectCreated. (package:leak_tracker/src/leak_tracking/leak_tracking.dart:124:35) +#2 LeakTracking.dispatchObjectCreated (package:leak_tracker/src/leak_tracking/leak_tracking.dart:133:6) +#3 new LeakTrackedClass (package:leak_tracker_flutter_testing/src/test_classes.dart:40:18) +#4 new StatelessLeakingWidget (package:leak_tracker_flutter_testing/src/test_classes.dart:20:27) +#5 createTestWidget (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:46:46) +#6 main. (file:///Users/polinach/_/leak_tracker/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/test_helpers_test.dart:38:5) +#7 Declarer.test.. (package:test_api/src/backend/declarer.dart:215:19) + +#8 Declarer.test. (package:test_api/src/backend/declarer.dart:213:7) + +#9 Invoker._waitForOutstandingCallbacks. (package:test_api/src/backend/invoker.dart:258:9) + ''', ), ]; diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md index da4449c4..864827e5 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/README.md @@ -1,4 +1,4 @@ -This forlder contains model and tests to test that methods like `testWidgets`, +This folder contains model and tests to test that methods like `testWidgets`, that use API of this package, detect leaks as expected. See example of usage in [the test](../../../test/tests/end_to_end/testing_test.dart). diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/leaking_classes.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/leaking_classes.dart index 13b34dba..4d76f3a1 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/leaking_classes.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/leaking_classes.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2024, 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. diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart index 1b36de7b..9c5b0c01 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_case.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2024, 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. diff --git a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart index a20951fc..2a2271d4 100644 --- a/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart +++ b/pkgs/leak_tracker_flutter_testing/lib/src/testing_for_testing/test_settings.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2024, 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. diff --git a/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart b/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart index 9dbaf669..91c8f6a7 100644 --- a/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart +++ b/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart @@ -1,6 +1,6 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// Copyright (c) 2024, 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/cupertino.dart'; import 'package:flutter/material.dart'; @@ -9,12 +9,12 @@ import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import 'test_helpers.dart'; /// Objects that should not be GCed during. -final List _retainer = []; +final _retainer = []; /// Test cases for memory leaks. /// -/// They are separate from test execution to allow to except only them -/// from test helpers. +/// They are separate from test execution to allow to allow +/// excluding them from test helpers. final List memoryLeakTests = [ LeakTestCase( name: 'no leaks', diff --git a/pkgs/leak_tracker_flutter_testing/test/test_infra/test_helpers.dart b/pkgs/leak_tracker_flutter_testing/test/test_infra/test_helpers.dart index f1871171..4aae0afd 100644 --- a/pkgs/leak_tracker_flutter_testing/test/test_infra/test_helpers.dart +++ b/pkgs/leak_tracker_flutter_testing/test/test_infra/test_helpers.dart @@ -1,10 +1,10 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// Copyright (c) 2024, 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:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; -/// Test only function that create a leaking object. +/// Test only function that creates a leaking object. /// /// If test helpers are ignored in leak tracking settings, /// leaks from objects created by this function will be ignored. diff --git a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart index 1c0e67a8..9b9a5df2 100644 --- a/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart +++ b/pkgs/leak_tracker_flutter_testing/test/tests/end_to_end/testing_test.dart @@ -8,8 +8,11 @@ import 'package:test/test.dart'; import '../../test_infra/memory_leak_tests.dart'; class _TestExecution { - _TestExecution( - {required this.settings, required this.settingName, required this.test}); + _TestExecution({ + required this.settings, + required this.settingName, + required this.test, + }); final String settingName; final LeakTesting settings; From 22ee0e5314d7b0de8b6769092ccc5f3150e1a714 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Jan 2024 10:05:51 -0800 Subject: [PATCH 45/46] Update model.dart --- pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart index 9ce3d8b7..bf6f6fc4 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/model.dart @@ -152,7 +152,6 @@ class IgnoredLeaks { /// /// Is used to test functionality of /// the leak tracker. - @visibleForTesting final List testHelperExceptions; /// Returns true if the class is ignored. From 10311d737d685a07ba08337ae45488a42ba86b73 Mon Sep 17 00:00:00 2001 From: Polina Cherkasova Date: Mon, 8 Jan 2024 18:33:11 -0800 Subject: [PATCH 46/46] - --- pkgs/leak_tracker/CHANGELOG.md | 4 ++++ .../src/leak_tracking/primitives/_test_helper_detector.dart | 6 ++++-- pkgs/leak_tracker/pubspec.yaml | 2 +- pkgs/leak_tracker_flutter_testing/CHANGELOG.md | 5 +++++ pkgs/leak_tracker_flutter_testing/pubspec.yaml | 6 +++--- .../test/test_infra/memory_leak_tests.dart | 2 +- pkgs/leak_tracker_testing/CHANGELOG.md | 5 +++++ pkgs/leak_tracker_testing/pubspec.yaml | 2 +- 8 files changed, 24 insertions(+), 8 deletions(-) diff --git a/pkgs/leak_tracker/CHANGELOG.md b/pkgs/leak_tracker/CHANGELOG.md index 2748c38b..53b2f4ca 100644 --- a/pkgs/leak_tracker/CHANGELOG.md +++ b/pkgs/leak_tracker/CHANGELOG.md @@ -1,3 +1,7 @@ +# 10.0.1 + +* Allow to ignore objects created by test helpers. + ## 10.0.0 * Remove `memory_usage`, as it is moved to https://github.com/dart-lang/leak_tracker/tree/main/pkgs/memory_usage. diff --git a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart index eb3ed3aa..c685e8fa 100644 --- a/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart +++ b/pkgs/leak_tracker/lib/src/leak_tracking/primitives/_test_helper_detector.dart @@ -27,11 +27,13 @@ final _startFrame = RegExp( r')', ); -/// If true, leaking objects created by test helpers will be ignored. +/// Returns whether the leak reported by [objectCreationTrace] +/// was created by a test helper. /// /// Frames, that match [exceptions] will be ignored. /// -/// See details in doc for `LeakTesting.createdByTestHelpers`. +/// See details on what means to be created by a test helper +/// in doc for `LeakTesting.createdByTestHelpers`. bool isCreatedByTestHelper( String objectCreationTrace, List exceptions, diff --git a/pkgs/leak_tracker/pubspec.yaml b/pkgs/leak_tracker/pubspec.yaml index 8b952ba7..1b4660c6 100644 --- a/pkgs/leak_tracker/pubspec.yaml +++ b/pkgs/leak_tracker/pubspec.yaml @@ -1,5 +1,5 @@ name: leak_tracker -version: 10.0.0 +version: 10.0.1 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 0e4ff600..3872dad6 100644 --- a/pkgs/leak_tracker_flutter_testing/CHANGELOG.md +++ b/pkgs/leak_tracker_flutter_testing/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.0.3 + +* Allow to ignore objects created by test helpers. +* Upgrade to leak_tracker 10.0.1 and leak_tracker_testing 2.0.2. + ## 2.0.2 * Replaced depracated `MemoryAllocations` with `FlutterMemoryAllocations`. diff --git a/pkgs/leak_tracker_flutter_testing/pubspec.yaml b/pkgs/leak_tracker_flutter_testing/pubspec.yaml index 765a52c1..01bdca21 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: 2.0.2 +version: 2.0.3 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 @@ -10,8 +10,8 @@ environment: dependencies: flutter: sdk: flutter - leak_tracker: '>=10.0.0 <11.0.0' - leak_tracker_testing: '>=2.0.1 <3.0.0' + leak_tracker: '>=10.0.1 <11.0.0' + leak_tracker_testing: '>=2.0.2 <3.0.0' matcher: ^0.12.16 meta: ^1.8.0 diff --git a/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart b/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart index 91c8f6a7..ecf5601e 100644 --- a/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart +++ b/pkgs/leak_tracker_flutter_testing/test/test_infra/memory_leak_tests.dart @@ -13,7 +13,7 @@ final _retainer = []; /// Test cases for memory leaks. /// -/// They are separate from test execution to allow to allow +/// They are separate from test execution to allow /// excluding them from test helpers. final List memoryLeakTests = [ LeakTestCase( diff --git a/pkgs/leak_tracker_testing/CHANGELOG.md b/pkgs/leak_tracker_testing/CHANGELOG.md index 9c57b0a1..bada0ba3 100644 --- a/pkgs/leak_tracker_testing/CHANGELOG.md +++ b/pkgs/leak_tracker_testing/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.0.2 + +* Allow to ignore objects created by test helpers. +* Set `ignore = false` by default. + ## 2.0.1 * Add LeakTesting.enabled. diff --git a/pkgs/leak_tracker_testing/pubspec.yaml b/pkgs/leak_tracker_testing/pubspec.yaml index 60f155b4..b73aff2e 100644 --- a/pkgs/leak_tracker_testing/pubspec.yaml +++ b/pkgs/leak_tracker_testing/pubspec.yaml @@ -1,5 +1,5 @@ name: leak_tracker_testing -version: 2.0.1 +version: 2.0.2 description: Leak tracking code intended for usage in tests. repository: https://github.com/dart-lang/leak_tracker/tree/main/pkgs/leak_tracker_testing