// 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 'dart:ui' as ui; import 'package:flutter/foundation.dart'; import 'package:flutter/painting.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; Future<void> main() async { final ui.Image image = await createTestImage(); testWidgets('didHaveMemoryPressure clears imageCache', (WidgetTester tester) async { imageCache.putIfAbsent(1, () => OneFrameImageStreamCompleter( Future<ImageInfo>.value(ImageInfo( image: image, )), )); await tester.idle(); expect(imageCache.currentSize, 1); final ByteData message = const JSONMessageCodec().encodeMessage(<String, dynamic>{'type': 'memoryPressure'})!; await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/system', message, (_) { }); expect(imageCache.currentSize, 0); }); test('evict clears live references', () async { final TestPaintingBinding binding = TestPaintingBinding(); expect(binding.imageCache.clearCount, 0); expect(binding.imageCache.liveClearCount, 0); binding.evict('/path/to/asset.png'); expect(binding.imageCache.clearCount, 1); expect(binding.imageCache.liveClearCount, 1); }); test('ShaderWarmUp is null by default', () { expect(PaintingBinding.shaderWarmUp, null); }); } class TestBindingBase implements BindingBase { @override void initInstances() {} @override bool debugCheckZone(String entryPoint) { return true; } @override void initServiceExtensions() {} @override Future<void> lockEvents(Future<void> Function() callback) async {} @override bool get locked => throw UnimplementedError(); @override Future<void> performReassemble() { throw UnimplementedError(); } @override void postEvent(String eventKind, Map<String, dynamic> eventData) {} @override Future<void> reassembleApplication() { throw UnimplementedError(); } @override void registerBoolServiceExtension({required String name, required AsyncValueGetter<bool> getter, required AsyncValueSetter<bool> setter}) {} @override void registerNumericServiceExtension({required String name, required AsyncValueGetter<double> getter, required AsyncValueSetter<double> setter}) {} @override void registerServiceExtension({required String name, required ServiceExtensionCallback callback}) {} @override void registerSignalServiceExtension({required String name, required AsyncCallback callback}) {} @override void registerStringServiceExtension({required String name, required AsyncValueGetter<String> getter, required AsyncValueSetter<String> setter}) {} @override void unlocked() {} @override ui.SingletonFlutterWindow get window => throw UnimplementedError(); // ignore: deprecated_member_use @override ui.PlatformDispatcher get platformDispatcher => throw UnimplementedError(); } class TestPaintingBinding extends TestBindingBase with SchedulerBinding, ServicesBinding, PaintingBinding { @override final FakeImageCache imageCache = FakeImageCache(); @override ImageCache createImageCache() => imageCache; } class FakeImageCache extends ImageCache { int clearCount = 0; int liveClearCount = 0; @override void clear() { clearCount += 1; super.clear(); } @override void clearLiveImages() { liveClearCount += 1; super.clearLiveImages(); } }