Memory leaks clean up 1 (#145691)

This commit is contained in:
Kostia Sokolovskyi 2024-03-25 18:36:42 +01:00 committed by GitHub
parent 2dd276487b
commit 47bfa827ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 117 additions and 33 deletions

View file

@ -4,6 +4,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class InvalidOnInitLifecycleWidget extends StatefulWidget {
const InvalidOnInitLifecycleWidget({super.key});
@ -46,13 +47,17 @@ class InvalidDidUpdateWidgetLifecycleWidgetState extends State<InvalidDidUpdateW
}
void main() {
testWidgets('async onInit throws FlutterError', (WidgetTester tester) async {
testWidgets('async onInit throws FlutterError',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
await tester.pumpWidget(const InvalidOnInitLifecycleWidget());
expect(tester.takeException(), isFlutterError);
});
testWidgets('async didUpdateWidget throws FlutterError', (WidgetTester tester) async {
testWidgets('async didUpdateWidget throws FlutterError',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
await tester.pumpWidget(const InvalidDidUpdateWidgetLifecycleWidget(color: Colors.green));
await tester.pumpWidget(const InvalidDidUpdateWidgetLifecycleWidget(color: Colors.red));

View file

@ -4,6 +4,7 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
typedef TestCallback = void Function(BuildContext context);
@ -28,7 +29,9 @@ class TestWidgetState extends State<TestWidget> {
}
void main() {
testWidgets('dependOnInheritedWidgetOfExactType() called from dispose() throws error', (WidgetTester tester) async {
testWidgets('dependOnInheritedWidgetOfExactType() called from dispose() throws error',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
bool disposeCalled = false;
await tester.pumpWidget(
TestWidget((BuildContext context) {
@ -41,7 +44,9 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('getElementForInheritedWidgetOfExactType() called from dispose() throws error', (WidgetTester tester) async {
testWidgets('getElementForInheritedWidgetOfExactType() called from dispose() throws error',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
bool disposeCalled = false;
await tester.pumpWidget(
TestWidget((BuildContext context) {
@ -54,7 +59,9 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('findAncestorWidgetOfExactType() called from dispose() throws error', (WidgetTester tester) async {
testWidgets('findAncestorWidgetOfExactType() called from dispose() throws error',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
bool disposeCalled = false;
await tester.pumpWidget(
TestWidget((BuildContext context) {
@ -67,7 +74,9 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('findAncestorStateOfType() called from dispose() throws error', (WidgetTester tester) async {
testWidgets('findAncestorStateOfType() called from dispose() throws error',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
bool disposeCalled = false;
await tester.pumpWidget(
TestWidget((BuildContext context) {
@ -80,7 +89,9 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('findAncestorRenderObjectOfType() called from dispose() throws error', (WidgetTester tester) async {
testWidgets('findAncestorRenderObjectOfType() called from dispose() throws error',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
bool disposeCalled = false;
await tester.pumpWidget(
TestWidget((BuildContext context) {
@ -93,7 +104,9 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('visitAncestorElements() called from dispose() throws error', (WidgetTester tester) async {
testWidgets('visitAncestorElements() called from dispose() throws error',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
bool disposeCalled = false;
await tester.pumpWidget(
TestWidget((BuildContext context) {

View file

@ -151,7 +151,9 @@ void main() {
expect(tester.getRect(find.byKey(key)), const Rect.fromLTRB(0.0, 325.0, 800.0, 600.0));
});
testWidgets('Invalid snap targets throw assertion errors.', (WidgetTester tester) async {
testWidgets('Invalid snap targets throw assertion errors.',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
await tester.pumpWidget(boilerplateWidget(
null,
maxChildSize: .8,
@ -1231,7 +1233,9 @@ void main() {
expect(controller.pixels, closeTo(.4*screenHeight, precisionErrorTolerance));
});
testWidgets('Cannot attach a controller to multiple sheets', (WidgetTester tester) async {
testWidgets('Cannot attach a controller to multiple sheets',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
final DraggableScrollableController controller = DraggableScrollableController();
addTearDown(controller.dispose);
await tester.pumpWidget(Directionality(

View file

@ -11,6 +11,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../widgets/clipboard_utils.dart';
import 'editable_text_utils.dart';
@ -9748,7 +9749,9 @@ void main() {
expect(errorString, contains('Unbalanced call to endBatchEdit'));
});
testWidgets('catch unfinished batch edits on disposal', (WidgetTester tester) async {
testWidgets('catch unfinished batch edits on disposal',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
await tester.pumpWidget(buildWidget());
// Connect.
@ -15346,6 +15349,7 @@ void main() {
final EditableText editableText = tester.widget(find.byType(EditableText));
final BuildContext context = tester.firstElement(find.byType(EditableText));
final ValueNotifier<MagnifierInfo> magnifierInfo = ValueNotifier<MagnifierInfo>(MagnifierInfo.empty);
addTearDown(magnifierInfo.dispose);
expect(
editableText.magnifierConfiguration.magnifierBuilder(
context,

View file

@ -5,6 +5,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('ErrorWidget displays actual error when throwing during build', (WidgetTester tester) async {
@ -37,7 +38,9 @@ void main() {
expect(find.byKey(container), findsOneWidget);
});
testWidgets('when constructing an ErrorWidget due to a build failure throws an error, fail gracefully', (WidgetTester tester) async {
testWidgets('when constructing an ErrorWidget due to a build failure throws an error, fail gracefully',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
final Key container = UniqueKey();
await tester.pumpWidget(
Container(

View file

@ -448,7 +448,9 @@ void main() {
);
});
testWidgets('GlobalKey duplication 2 - splitting and changing type', (WidgetTester tester) async {
testWidgets('GlobalKey duplication 2 - splitting and changing type',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
@ -494,7 +496,9 @@ void main() {
);
});
testWidgets('GlobalKey duplication 3 - splitting and changing type', (WidgetTester tester) async {
testWidgets('GlobalKey duplication 3 - splitting and changing type',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
@ -521,7 +525,9 @@ void main() {
);
});
testWidgets('GlobalKey duplication 4 - splitting and half changing type', (WidgetTester tester) async {
testWidgets('GlobalKey duplication 4 - splitting and half changing type',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
@ -548,7 +554,9 @@ void main() {
);
});
testWidgets('GlobalKey duplication 5 - splitting and half changing type', (WidgetTester tester) async {
testWidgets('GlobalKey duplication 5 - splitting and half changing type',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
@ -566,7 +574,9 @@ void main() {
expect(tester.takeException(), isFlutterError);
});
testWidgets('GlobalKey duplication 6 - splitting and not changing type', (WidgetTester tester) async {
testWidgets('GlobalKey duplication 6 - splitting and not changing type',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
final Key key = GlobalKey(debugLabel: 'problematic');
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,
@ -724,7 +734,9 @@ void main() {
);
});
testWidgets('GlobalKey duplication 13 - all kinds of badness at once', (WidgetTester tester) async {
testWidgets('GlobalKey duplication 13 - all kinds of badness at once',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
final Key key1 = GlobalKey(debugLabel: 'problematic');
final Key key2 = GlobalKey(debugLabel: 'problematic'); // intentionally the same label
final Key key3 = GlobalKey(debugLabel: 'also problematic');
@ -1523,7 +1535,9 @@ void main() {
});
});
testWidgets('A widget whose element has an invalid visitChildren implementation triggers a useful error message', (WidgetTester tester) async {
testWidgets('A widget whose element has an invalid visitChildren implementation triggers a useful error message',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpWidget(_WidgetWithNoVisitChildren(_StatefulLeaf(key: key)));
(key.currentState! as _StatefulLeafState).markNeedsBuild();

View file

@ -5,6 +5,7 @@
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('Render and element tree stay in sync when keyed children move around', (WidgetTester tester) async {
@ -79,7 +80,9 @@ void main() {
);
});
testWidgets('Updating a MultiChildRenderObjectElement to have children with duplicated keys throws', (WidgetTester tester) async {
testWidgets('Updating a MultiChildRenderObjectElement to have children with duplicated keys throws',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/81541
const ValueKey<int> key1 = ValueKey<int>(1);

View file

@ -5,6 +5,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('Restoration Smoke Test', (WidgetTester tester) async {
@ -976,7 +977,9 @@ void main() {
expect(findRoute('p1', count: 0), findsOneWidget);
});
testWidgets('Helpful assert thrown all routes in onGenerateInitialRoutes are not restorable', (WidgetTester tester) async {
testWidgets('Helpful assert thrown all routes in onGenerateInitialRoutes are not restorable',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
restorationScopeId: 'material_app',

View file

@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart';
@ -311,7 +312,9 @@ void main() {
verifyTreeIsClean();
});
testWidgets('Throws when the same controller is attached to multiple OverlayPortal', (WidgetTester tester) async {
testWidgets('Throws when the same controller is attached to multiple OverlayPortal',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
final OverlayPortalController controller = OverlayPortalController(debugLabel: 'local controller');
late final OverlayEntry entry;
addTearDown(() { entry.remove(); entry.dispose(); });

View file

@ -1550,7 +1550,10 @@ void main() {
});
});
testWidgets('Overlay.wrap', (WidgetTester tester) async {
testWidgets('Overlay.wrap',
// TODO(ksokolovskyi): dispose OverlayEntry, https://github.com/flutter/flutter/issues/145687 [leaks-to-clean]
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(),
(WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1582,7 +1585,10 @@ void main() {
expect(tester.state(find.byType(Overlay)), same(overlayState));
});
testWidgets('Overlay.wrap is sized by child in an unconstrained environment', (WidgetTester tester) async {
testWidgets('Overlay.wrap is sized by child in an unconstrained environment',
// TODO(ksokolovskyi): dispose OverlayEntry, https://github.com/flutter/flutter/issues/145687 [leaks-to-clean]
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(),
(WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,

View file

@ -8,6 +8,7 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter/src/foundation/diagnostics.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
@ -110,7 +111,9 @@ void main() {
);
});
});
testWidgets('asserts when more than one has locked the delegate', (WidgetTester tester) async {
testWidgets('asserts when more than one has locked the delegate',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Material(

View file

@ -18,6 +18,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../impeller_test_helpers.dart';
import '../widgets/clipboard_utils.dart';
@ -220,7 +221,9 @@ void main() {
);
}
testWidgets('throw if no Overlay widget exists above', (WidgetTester tester) async {
testWidgets('throw if no Overlay widget exists above',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,

View file

@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../rendering/sliver_utils.dart';
@ -325,7 +326,9 @@ void main() {
expect(renderGroup.geometry!.scrollExtent, equals(300 * 20));
});
testWidgets('Assertion error when SliverExpanded is used outside of SliverCrossAxisGroup', (WidgetTester tester) async {
testWidgets('Assertion error when SliverExpanded is used outside of SliverCrossAxisGroup',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
final List<FlutterErrorDetails> errors = <FlutterErrorDetails>[];
final FlutterExceptionHandler? oldHandler = FlutterError.onError;
FlutterError.onError = (FlutterErrorDetails error) => errors.add(error);

View file

@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
const Color green = Color(0xFF00FF00);
const Color yellow = Color(0xFFFFFF00);
@ -186,7 +187,9 @@ void main() {
expect(widget2Element, same(tester.element(find.byWidget(widget2))));
});
testWidgets('duplicated key error message', (WidgetTester tester) async {
testWidgets('duplicated key error message',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
const Widget widget1 = SizedBox(key: ValueKey<String>('widget 1'), height: 10, width: 10);
const Widget widget2 = SizedBox(key: ValueKey<String>('widget 1'), height: 100, width: 100);
const Widget widget3 = SizedBox(key: ValueKey<String>('widget 1'), height: 50, width: 50);

View file

@ -5,6 +5,7 @@
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../rendering/rendering_tester.dart' show TestCallbackPainter;
@ -860,7 +861,9 @@ void main() {
expect(tester.getRect(find.byType(SizedBox).at(8)), const Rect.fromLTWH(0.0, 500.0, 100.0, 100.0));
});
testWidgets('Stack error messages', (WidgetTester tester) async {
testWidgets('Stack error messages',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
await tester.pumpWidget(
const Stack(),
);

View file

@ -9,6 +9,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart';
@ -96,7 +97,9 @@ void main() {
expect(largeSize.height, equals(26.0));
});
testWidgets("Text throws a nice error message if there's no Directionality", (WidgetTester tester) async {
testWidgets("Text throws a nice error message if there's no Directionality",
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
await tester.pumpWidget(const Text('Hello'));
final String message = tester.takeException().toString();
expect(message, contains('Directionality'));

View file

@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('TickerMode', (WidgetTester tester) async {
@ -66,7 +67,9 @@ void main() {
});
group('TickerProviderStateMixin assertion control test', () {
testWidgets('SingleTickerProviderStateMixin create multiple tickers', (WidgetTester tester) async {
testWidgets('SingleTickerProviderStateMixin create multiple tickers',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
const Widget widget = _SingleTickerCreateMultipleTicker();
await tester.pumpWidget(widget);
final dynamic exception = tester.takeException();

View file

@ -7,6 +7,7 @@ import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'multi_view_testing.dart';
@ -52,7 +53,9 @@ void main() {
));
});
testWidgets('A View cannot be a child of a render object widget', (WidgetTester tester) async {
testWidgets('A View cannot be a child of a render object widget',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
await tester.pumpWidget(Center(
child: View(
view: FakeView(tester.view),
@ -67,7 +70,9 @@ void main() {
));
});
testWidgets('The child of a ViewAnchor cannot be a View', (WidgetTester tester) async {
testWidgets('The child of a ViewAnchor cannot be a View',
experimentalLeakTesting: LeakTesting.settings.withIgnoredAll(), // leaking by design because of exception
(WidgetTester tester) async {
await tester.pumpWidget(
ViewAnchor(
child: View(