// 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:convert'; import 'package:flutter/painting.dart'; import 'package:flutter_test/flutter_test.dart'; import 'common.dart'; void main() { initTimelineTests(); TestWidgetsFlutterBinding.ensureInitialized(); test('Image cache tracing', () async { final TestImageStreamCompleter completer1 = TestImageStreamCompleter(); final TestImageStreamCompleter completer2 = TestImageStreamCompleter(); PaintingBinding.instance.imageCache.putIfAbsent( 'Test', () => completer1, ); PaintingBinding.instance.imageCache.clear(); completer2.testSetImage(ImageInfo(image: await createTestImage())); PaintingBinding.instance.imageCache.putIfAbsent( 'Test2', () => completer2, ); PaintingBinding.instance.imageCache.evict('Test2'); _expectTimelineEvents( await fetchTimelineEvents(), <Map<String, dynamic>>[ <String, dynamic>{ 'name': 'ImageCache.putIfAbsent', 'args': <String, dynamic>{'key': 'Test', 'isolateId': isolateId}, }, <String, dynamic>{ 'name': 'listener', 'args': <String, dynamic>{'isolateId': isolateId}, }, <String, dynamic>{ 'name': 'ImageCache.clear', 'args': <String, dynamic>{ 'pendingImages': 1, 'keepAliveImages': 0, 'liveImages': 1, 'currentSizeInBytes': 0, 'isolateId': isolateId, }, }, <String, dynamic>{ 'name': 'ImageCache.putIfAbsent', 'args': <String, dynamic>{'key': 'Test2', 'isolateId': isolateId}, }, <String, dynamic>{ 'name': 'ImageCache.evict', 'args': <String, dynamic>{'sizeInBytes': 4, 'isolateId': isolateId}, }, ], ); }, skip: isBrowser); // [intended] uses dart:isolate and io. } void _expectTimelineEvents(List<TimelineEvent> events, List<Map<String, dynamic>> expected) { for (final TimelineEvent event in events) { for (int index = 0; index < expected.length; index += 1) { if (expected[index]['name'] == event.json!['name']) { final Map<String, dynamic> expectedArgs = expected[index]['args'] as Map<String, dynamic>; final Map<String, dynamic> args = event.json!['args'] as Map<String, dynamic>; if (_mapsEqual(expectedArgs, args)) { expected.removeAt(index); } } } } if (expected.isNotEmpty) { final String encodedEvents = jsonEncode(events); fail('Timeline did not contain expected events: $expected\nactual: $encodedEvents'); } } bool _mapsEqual(Map<String, dynamic> expectedArgs, Map<String, dynamic> args) { for (final String key in expectedArgs.keys) { if (expectedArgs[key] != args[key]) { return false; } } return true; } class TestImageStreamCompleter extends ImageStreamCompleter { void testSetImage(ImageInfo image) { setImage(image); } }