// 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.

// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])

import 'dart:async';
import 'dart:io';
import 'dart:math' as math;
import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

import '../image_data.dart';
import 'semantics_tester.dart';

void main() {
  late int originalCacheSize;
  late ui.Image image10x10;

  setUp(() async {
    originalCacheSize = imageCache.maximumSize;
    imageCache.clear();
    imageCache.clearLiveImages();
    image10x10 = await createTestImage(width: 10, height: 10);
  });

  tearDown(() {
    imageCache.maximumSize = originalCacheSize;
  });

  testWidgets('Verify Image resets its RenderImage when changing providers', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    final _TestImageProvider imageProvider1 = _TestImageProvider();
    await tester.pumpWidget(
      Container(
        key: key,
        child: Image(
          image: imageProvider1,
          excludeFromSemantics: true,
        ),
      ),
      null,
      EnginePhase.layout,
    );
    RenderImage renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNull);

    imageProvider1.complete(image10x10);
    await tester.idle(); // resolve the future from the image provider
    await tester.pump(null, EnginePhase.layout);

    renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNotNull);

    final _TestImageProvider imageProvider2 = _TestImageProvider();
    await tester.pumpWidget(
      Container(
        key: key,
        child: Image(
          image: imageProvider2,
          excludeFromSemantics: true,
        ),
      ),
      null,
      EnginePhase.layout,
    );

    renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNull);
  });

  testWidgets("Verify Image doesn't reset its RenderImage when changing providers if it has gaplessPlayback set", (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    final _TestImageProvider imageProvider1 = _TestImageProvider();
    await tester.pumpWidget(
      Container(
        key: key,
        child: Image(
          gaplessPlayback: true,
          image: imageProvider1,
          excludeFromSemantics: true,
        ),
      ),
      null,
      EnginePhase.layout,
    );
    RenderImage renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNull);

    imageProvider1.complete(image10x10);
    await tester.idle(); // resolve the future from the image provider
    await tester.pump(null, EnginePhase.layout);

    renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNotNull);

    final _TestImageProvider imageProvider2 = _TestImageProvider();
    await tester.pumpWidget(
      Container(
        key: key,
        child: Image(
          gaplessPlayback: true,
          image: imageProvider2,
          excludeFromSemantics: true,
        ),
      ),
      null,
      EnginePhase.layout,
    );

    renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNotNull);
  });

  testWidgets('Verify Image resets its RenderImage when changing providers if it has a key', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    final _TestImageProvider imageProvider1 = _TestImageProvider();
    await tester.pumpWidget(
      Image(
        key: key,
        image: imageProvider1,
        excludeFromSemantics: true,
      ),
      null,
      EnginePhase.layout,
    );
    RenderImage renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNull);

    imageProvider1.complete(image10x10);
    await tester.idle(); // resolve the future from the image provider
    await tester.pump(null, EnginePhase.layout);

    renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNotNull);

    final _TestImageProvider imageProvider2 = _TestImageProvider();
    await tester.pumpWidget(
      Image(
        key: key,
        image: imageProvider2,
        excludeFromSemantics: true,
      ),
      null,
      EnginePhase.layout,
    );

    renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNull);
  });

  testWidgets("Verify Image doesn't reset its RenderImage when changing providers if it has gaplessPlayback set", (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    final _TestImageProvider imageProvider1 = _TestImageProvider();
    await tester.pumpWidget(
      Image(
        key: key,
        gaplessPlayback: true,
        image: imageProvider1,
        excludeFromSemantics: true,
      ),
      null,
      EnginePhase.layout,
    );
    RenderImage renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNull);

    imageProvider1.complete(image10x10);
    await tester.idle(); // resolve the future from the image provider
    await tester.pump(null, EnginePhase.layout);

    renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNotNull);

    final _TestImageProvider imageProvider2 = _TestImageProvider();
    await tester.pumpWidget(
      Image(
        key: key,
        gaplessPlayback: true,
        excludeFromSemantics: true,
        image: imageProvider2,
      ),
      null,
      EnginePhase.layout,
    );

    renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNotNull);
  });

  testWidgets('Verify ImageProvider configuration inheritance', (WidgetTester tester) async {
    final GlobalKey mediaQueryKey1 = GlobalKey(debugLabel: 'mediaQueryKey1');
    final GlobalKey mediaQueryKey2 = GlobalKey(debugLabel: 'mediaQueryKey2');
    final GlobalKey imageKey = GlobalKey(debugLabel: 'image');
    final _ConfigurationKeyedTestImageProvider imageProvider = _ConfigurationKeyedTestImageProvider();
    final Set<Object> seenKeys = <Object>{};
    final _DebouncingImageProvider debouncingProvider = _DebouncingImageProvider(imageProvider, seenKeys);

    // Of the two nested MediaQuery objects, the innermost one,
    // mediaQuery2, should define the configuration of the imageProvider.
    await tester.pumpWidget(
      MediaQuery(
        key: mediaQueryKey1,
        data: const MediaQueryData(
          devicePixelRatio: 10.0,
        ),
        child: MediaQuery(
          key: mediaQueryKey2,
          data: const MediaQueryData(
            devicePixelRatio: 5.0,
          ),
          child: Image(
            excludeFromSemantics: true,
            key: imageKey,
            image: debouncingProvider,
          ),
        ),
      ),
    );

    expect(imageProvider._lastResolvedConfiguration.devicePixelRatio, 5.0);

    // This is the same widget hierarchy as before except that the
    // two MediaQuery objects have exchanged places. The imageProvider
    // should be resolved again, with the new innermost MediaQuery.
    await tester.pumpWidget(
      MediaQuery(
        key: mediaQueryKey2,
        data: const MediaQueryData(
          devicePixelRatio: 5.0,
        ),
        child: MediaQuery(
          key: mediaQueryKey1,
          data: const MediaQueryData(
            devicePixelRatio: 10.0,
          ),
          child: Image(
            excludeFromSemantics: true,
            key: imageKey,
            image: debouncingProvider,
          ),
        ),
      ),
    );

    expect(imageProvider._lastResolvedConfiguration.devicePixelRatio, 10.0);
  });

  testWidgets('Verify ImageProvider configuration inheritance again', (WidgetTester tester) async {
    final GlobalKey mediaQueryKey1 = GlobalKey(debugLabel: 'mediaQueryKey1');
    final GlobalKey mediaQueryKey2 = GlobalKey(debugLabel: 'mediaQueryKey2');
    final GlobalKey imageKey = GlobalKey(debugLabel: 'image');
    final _ConfigurationKeyedTestImageProvider imageProvider = _ConfigurationKeyedTestImageProvider();
    final Set<Object> seenKeys = <Object>{};
    final _DebouncingImageProvider debouncingProvider = _DebouncingImageProvider(imageProvider, seenKeys);

    // This is just a variation on the previous test. In this version the location
    // of the Image changes and the MediaQuery widgets do not.
    await tester.pumpWidget(
      Row(
        textDirection: TextDirection.ltr,
        children: <Widget> [
          MediaQuery(
            key: mediaQueryKey2,
            data: const MediaQueryData(
              devicePixelRatio: 5.0,
            ),
            child: Image(
              excludeFromSemantics: true,
              key: imageKey,
              image: debouncingProvider,
            ),
          ),
          MediaQuery(
            key: mediaQueryKey1,
            data: const MediaQueryData(
              devicePixelRatio: 10.0,
            ),
            child: Container(width: 100.0),
          ),
        ],
      ),
    );

    expect(imageProvider._lastResolvedConfiguration.devicePixelRatio, 5.0);

    await tester.pumpWidget(
      Row(
        textDirection: TextDirection.ltr,
        children: <Widget> [
          MediaQuery(
            key: mediaQueryKey2,
            data: const MediaQueryData(
              devicePixelRatio: 5.0,
            ),
            child: Container(width: 100.0),
          ),
          MediaQuery(
            key: mediaQueryKey1,
            data: const MediaQueryData(
              devicePixelRatio: 10.0,
            ),
            child: Image(
              excludeFromSemantics: true,
              key: imageKey,
              image: debouncingProvider,
            ),
          ),
        ],
      ),
    );

    expect(imageProvider._lastResolvedConfiguration.devicePixelRatio, 10.0);
  });

  testWidgets('Verify ImageProvider does not inherit configuration when it does not key to it', (WidgetTester tester) async {
    final GlobalKey mediaQueryKey1 = GlobalKey(debugLabel: 'mediaQueryKey1');
    final GlobalKey mediaQueryKey2 = GlobalKey(debugLabel: 'mediaQueryKey2');
    final GlobalKey imageKey = GlobalKey(debugLabel: 'image');
    final _TestImageProvider imageProvider = _TestImageProvider();
    final Set<Object> seenKeys = <Object>{};
    final _DebouncingImageProvider debouncingProvider = _DebouncingImageProvider(imageProvider, seenKeys);

    // Of the two nested MediaQuery objects, the innermost one,
    // mediaQuery2, should define the configuration of the imageProvider.
    await tester.pumpWidget(
      MediaQuery(
        key: mediaQueryKey1,
        data: const MediaQueryData(
          devicePixelRatio: 10.0,
        ),
        child: MediaQuery(
          key: mediaQueryKey2,
          data: const MediaQueryData(
            devicePixelRatio: 5.0,
          ),
          child: Image(
            excludeFromSemantics: true,
            key: imageKey,
            image: debouncingProvider,
          ),
        ),
      ),
    );

    expect(imageProvider._lastResolvedConfiguration.devicePixelRatio, 5.0);

    // This is the same widget hierarchy as before except that the
    // two MediaQuery objects have exchanged places. The imageProvider
    // should not be resolved again, because it does not key to configuration.
    await tester.pumpWidget(
      MediaQuery(
        key: mediaQueryKey2,
        data: const MediaQueryData(
          devicePixelRatio: 5.0,
        ),
        child: MediaQuery(
          key: mediaQueryKey1,
          data: const MediaQueryData(
            devicePixelRatio: 10.0,
          ),
          child: Image(
            excludeFromSemantics: true,
            key: imageKey,
            image: debouncingProvider,
          ),
        ),
      ),
    );

    expect(imageProvider._lastResolvedConfiguration.devicePixelRatio, 5.0);
  });

  testWidgets('Verify ImageProvider does not inherit configuration when it does not key to it again', (WidgetTester tester) async {
    final GlobalKey mediaQueryKey1 = GlobalKey(debugLabel: 'mediaQueryKey1');
    final GlobalKey mediaQueryKey2 = GlobalKey(debugLabel: 'mediaQueryKey2');
    final GlobalKey imageKey = GlobalKey(debugLabel: 'image');
    final _TestImageProvider imageProvider = _TestImageProvider();
    final Set<Object> seenKeys = <Object>{};
    final _DebouncingImageProvider debouncingProvider = _DebouncingImageProvider(imageProvider, seenKeys);

    // This is just a variation on the previous test. In this version the location
    // of the Image changes and the MediaQuery widgets do not.
    await tester.pumpWidget(
      Row(
        textDirection: TextDirection.ltr,
        children: <Widget> [
          MediaQuery(
            key: mediaQueryKey2,
            data: const MediaQueryData(
              devicePixelRatio: 5.0,
            ),
            child: Image(
              excludeFromSemantics: true,
              key: imageKey,
              image: debouncingProvider,
            ),
          ),
          MediaQuery(
            key: mediaQueryKey1,
            data: const MediaQueryData(
              devicePixelRatio: 10.0,
            ),
            child: Container(width: 100.0),
          ),
        ],
      ),
    );

    expect(imageProvider._lastResolvedConfiguration.devicePixelRatio, 5.0);

    await tester.pumpWidget(
      Row(
        textDirection: TextDirection.ltr,
        children: <Widget> [
          MediaQuery(
            key: mediaQueryKey2,
            data: const MediaQueryData(
              devicePixelRatio: 5.0,
            ),
            child: Container(width: 100.0),
          ),
          MediaQuery(
            key: mediaQueryKey1,
            data: const MediaQueryData(
              devicePixelRatio: 10.0,
            ),
            child: Image(
              excludeFromSemantics: true,
              key: imageKey,
              image: debouncingProvider,
            ),
          ),
        ],
      ),
    );

    expect(imageProvider._lastResolvedConfiguration.devicePixelRatio, 5.0);
  });

  testWidgets('Verify Image stops listening to ImageStream', (WidgetTester tester) async {
    final ui.Image image100x100 = (await tester.runAsync(() async => createTestImage(width: 100, height: 100)))!;
    // Web does not override the toString, whereas VM does
    final String imageString = image100x100.toString();

    final _TestImageProvider imageProvider = _TestImageProvider();
    await tester.pumpWidget(Image(image: imageProvider, excludeFromSemantics: true));
    final State<Image> image = tester.state/*State<Image>*/(find.byType(Image));
    expect(image.toString(), equalsIgnoringHashCodes('_ImageState#00000(stream: ImageStream#00000(OneFrameImageStreamCompleter#00000, unresolved, 2 listeners), pixels: null, loadingProgress: null, frameNumber: null, wasSynchronouslyLoaded: false)'));
    imageProvider.complete(image100x100);
    await tester.pump();
    expect(image.toString(), equalsIgnoringHashCodes('_ImageState#00000(stream: ImageStream#00000(OneFrameImageStreamCompleter#00000, $imageString @ 1.0x, 1 listener), pixels: $imageString @ 1.0x, loadingProgress: null, frameNumber: 0, wasSynchronouslyLoaded: false)'));
    await tester.pumpWidget(Container());
    expect(image.toString(), equalsIgnoringHashCodes('_ImageState#00000(lifecycle state: defunct, not mounted, stream: ImageStream#00000(OneFrameImageStreamCompleter#00000, $imageString @ 1.0x, 0 listeners), pixels: null, loadingProgress: null, frameNumber: 0, wasSynchronouslyLoaded: false)'));
  });

  testWidgets('Stream completer errors can be listened to by attaching before resolving', (WidgetTester tester) async {
    dynamic capturedException;
    StackTrace? capturedStackTrace;
    ImageInfo? capturedImage;
    void errorListener(dynamic exception, StackTrace? stackTrace) {
      capturedException = exception;
      capturedStackTrace = stackTrace;
    }
    void listener(ImageInfo info, bool synchronous) {
      capturedImage = info;
    }

    final Exception testException = Exception('cannot resolve host');
    final StackTrace testStack = StackTrace.current;
    final _TestImageProvider imageProvider = _TestImageProvider();
    imageProvider._streamCompleter.addListener(ImageStreamListener(listener, onError: errorListener));
    late ImageConfiguration configuration;
    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          configuration = createLocalImageConfiguration(context);
          return Container();
        },
      ),
    );
    imageProvider.resolve(configuration);
    imageProvider.fail(testException, testStack);

    expect(tester.binding.microtaskCount, 1);
    await tester.idle(); // Let the failed completer's future hit the stream completer.
    expect(tester.binding.microtaskCount, 0);

    expect(capturedImage, isNull); // The image stream listeners should never be called.
    // The image stream error handler should have the original exception.
    expect(capturedException, testException);
    expect(capturedStackTrace, testStack);
    // If there is an error listener, there should be no FlutterError reported.
    expect(tester.takeException(), isNull);
  });

  testWidgets('Stream completer errors can be listened to by attaching after resolving', (WidgetTester tester) async {
    dynamic capturedException;
    StackTrace? capturedStackTrace;
    dynamic reportedException;
    StackTrace? reportedStackTrace;
    ImageInfo? capturedImage;
    void errorListener(dynamic exception, StackTrace? stackTrace) {
      capturedException = exception;
      capturedStackTrace = stackTrace;
    }
    void listener(ImageInfo info, bool synchronous) {
      capturedImage = info;
    }
    FlutterError.onError = (FlutterErrorDetails flutterError) {
      reportedException = flutterError.exception;
      reportedStackTrace = flutterError.stack;
    };

    final Exception testException = Exception('cannot resolve host');
    final StackTrace testStack = StackTrace.current;
    final _TestImageProvider imageProvider = _TestImageProvider();
    late ImageConfiguration configuration;
    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          configuration = createLocalImageConfiguration(context);
          return Container();
        },
      ),
    );
    final ImageStream streamUnderTest = imageProvider.resolve(configuration);

    imageProvider.fail(testException, testStack);

    expect(tester.binding.microtaskCount, 1);
    await tester.idle(); // Let the failed completer's future hit the stream completer.
    expect(tester.binding.microtaskCount, 0);

    // Since there's no listeners attached yet, report error up via
    // FlutterError.
    expect(reportedException, testException);
    expect(reportedStackTrace, testStack);

    streamUnderTest.addListener(ImageStreamListener(listener, onError: errorListener));

    expect(capturedImage, isNull); // The image stream listeners should never be called.
    // The image stream error handler should have the original exception.
    expect(capturedException, testException);
    expect(capturedStackTrace, testStack);
  });

  testWidgets('Duplicate listener registration does not affect error listeners', (WidgetTester tester) async {
    dynamic capturedException;
    StackTrace? capturedStackTrace;
    ImageInfo? capturedImage;
    void errorListener(dynamic exception, StackTrace? stackTrace) {
      capturedException = exception;
      capturedStackTrace = stackTrace;
    }
    void listener(ImageInfo info, bool synchronous) {
      capturedImage = info;
    }

    final Exception testException = Exception('cannot resolve host');
    final StackTrace testStack = StackTrace.current;
    final _TestImageProvider imageProvider = _TestImageProvider();
    imageProvider._streamCompleter.addListener(ImageStreamListener(listener, onError: errorListener));
    // Add the exact same listener a second time without the errorListener.
    imageProvider._streamCompleter.addListener(ImageStreamListener(listener));
    late ImageConfiguration configuration;
    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          configuration = createLocalImageConfiguration(context);
          return Container();
        },
      ),
    );
    imageProvider.resolve(configuration);
    imageProvider.fail(testException, testStack);

    expect(tester.binding.microtaskCount, 1);
    await tester.idle(); // Let the failed completer's future hit the stream completer.
    expect(tester.binding.microtaskCount, 0);

    expect(capturedImage, isNull); // The image stream listeners should never be called.
    // The image stream error handler should have the original exception.
    expect(capturedException, testException);
    expect(capturedStackTrace, testStack);
    // If there is an error listener, there should be no FlutterError reported.
    expect(tester.takeException(), isNull);
  });

  testWidgets('Duplicate error listeners are all called', (WidgetTester tester) async {
    dynamic capturedException;
    StackTrace? capturedStackTrace;
    ImageInfo? capturedImage;
    int errorListenerCalled = 0;
    void errorListener(dynamic exception, StackTrace? stackTrace) {
      capturedException = exception;
      capturedStackTrace = stackTrace;
      errorListenerCalled++;
    }
    void listener(ImageInfo info, bool synchronous) {
      capturedImage = info;
    }

    final Exception testException = Exception('cannot resolve host');
    final StackTrace testStack = StackTrace.current;
    final _TestImageProvider imageProvider = _TestImageProvider();
    imageProvider._streamCompleter.addListener(ImageStreamListener(listener, onError: errorListener));
    // Add the exact same errorListener a second time.
    imageProvider._streamCompleter.addListener(ImageStreamListener(listener, onError: errorListener));
    late ImageConfiguration configuration;
    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          configuration = createLocalImageConfiguration(context);
          return Container();
        },
      ),
    );
    imageProvider.resolve(configuration);
    imageProvider.fail(testException, testStack);

    expect(tester.binding.microtaskCount, 1);
    await tester.idle(); // Let the failed completer's future hit the stream completer.
    expect(tester.binding.microtaskCount, 0);

    expect(capturedImage, isNull); // The image stream listeners should never be called.
    // The image stream error handler should have the original exception.
    expect(capturedException, testException);
    expect(capturedStackTrace, testStack);
    expect(errorListenerCalled, 2);
    // If there is an error listener, there should be no FlutterError reported.
    expect(tester.takeException(), isNull);
  });

  testWidgets('Listeners are only removed if callback tuple matches', (WidgetTester tester) async {
    bool errorListenerCalled = false;
    dynamic reportedException;
    StackTrace? reportedStackTrace;
    ImageInfo? capturedImage;
    void errorListener(dynamic exception, StackTrace? stackTrace) {
      errorListenerCalled = true;
      reportedException = exception;
      reportedStackTrace = stackTrace;
    }
    void listener(ImageInfo info, bool synchronous) {
      capturedImage = info;
    }

    final Exception testException = Exception('cannot resolve host');
    final StackTrace testStack = StackTrace.current;
    final _TestImageProvider imageProvider = _TestImageProvider();
    imageProvider._streamCompleter.addListener(ImageStreamListener(listener, onError: errorListener));
    // Now remove the listener the error listener is attached to.
    // Don't explicitly remove the error listener.
    imageProvider._streamCompleter.removeListener(ImageStreamListener(listener));
    late ImageConfiguration configuration;
    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          configuration = createLocalImageConfiguration(context);
          return Container();
        },
      ),
    );
    imageProvider.resolve(configuration);

    imageProvider.fail(testException, testStack);

    expect(tester.binding.microtaskCount, 1);
    await tester.idle(); // Let the failed completer's future hit the stream completer.
    expect(tester.binding.microtaskCount, 0);

    expect(errorListenerCalled, true);
    expect(reportedException, testException);
    expect(reportedStackTrace, testStack);
    expect(capturedImage, isNull); // The image stream listeners should never be called.
  });

  testWidgets('Removing listener removes one listener and error listener', (WidgetTester tester) async {
    int errorListenerCalled = 0;
    ImageInfo? capturedImage;
    void errorListener(dynamic exception, StackTrace? stackTrace) {
      errorListenerCalled++;
    }
    void listener(ImageInfo info, bool synchronous) {
      capturedImage = info;
    }

    final Exception testException = Exception('cannot resolve host');
    final StackTrace testStack = StackTrace.current;
    final _TestImageProvider imageProvider = _TestImageProvider();
    imageProvider._streamCompleter.addListener(ImageStreamListener(listener, onError: errorListener));
    // Duplicates the same set of listener and errorListener.
    imageProvider._streamCompleter.addListener(ImageStreamListener(listener, onError: errorListener));
    // Now remove one entry of the specified listener and associated error listener.
    // Don't explicitly remove the error listener.
    imageProvider._streamCompleter.removeListener(ImageStreamListener(listener, onError: errorListener));
    late ImageConfiguration configuration;
    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          configuration = createLocalImageConfiguration(context);
          return Container();
        },
      ),
    );
    imageProvider.resolve(configuration);

    imageProvider.fail(testException, testStack);

    expect(tester.binding.microtaskCount, 1);
    await tester.idle(); // Let the failed completer's future hit the stream completer.
    expect(tester.binding.microtaskCount, 0);

    expect(errorListenerCalled, 1);
    expect(capturedImage, isNull); // The image stream listeners should never be called.
  });

  testWidgets('Image.memory control test', (WidgetTester tester) async {
    await tester.pumpWidget(Image.memory(Uint8List.fromList(kTransparentImage), excludeFromSemantics: true));
  });

  testWidgets('Image color and colorBlend parameters', (WidgetTester tester) async {
    await tester.pumpWidget(
      Image(
        excludeFromSemantics: true,
        image: _TestImageProvider(),
        color: const Color(0xFF00FF00),
        colorBlendMode: BlendMode.clear,
      ),
    );
    final RenderImage renderer = tester.renderObject<RenderImage>(find.byType(Image));
    expect(renderer.color, const Color(0xFF00FF00));
    expect(renderer.colorBlendMode, BlendMode.clear);
  });

  testWidgets('Image opacity parameter', (WidgetTester tester) async {
    const Animation<double> opacity = AlwaysStoppedAnimation<double>(0.5);
    await tester.pumpWidget(
      Image(
        excludeFromSemantics: true,
        image: _TestImageProvider(),
        opacity: opacity,
      ),
    );
    final RenderImage renderer = tester.renderObject<RenderImage>(find.byType(Image));
    expect(renderer.opacity, opacity);
  });

  testWidgets('Precache', (WidgetTester tester) async {
    final _TestImageProvider provider = _TestImageProvider();
    late Future<void> precache;
    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          precache = precacheImage(provider, context);
          return Container();
        },
      ),
    );
    provider.complete(image10x10);
    await precache;
    expect(provider._lastResolvedConfiguration, isNotNull);

    // Check that a second resolve of the same image is synchronous.
    final ImageStream stream = provider.resolve(provider._lastResolvedConfiguration);
    late bool isSync;
    stream.addListener(ImageStreamListener((ImageInfo image, bool sync) { isSync = sync; }));
    expect(isSync, isTrue);
  });

  testWidgets('Precache removes original listener immediately after future completes, does not crash on successive calls #25143', (WidgetTester tester) async {
    final _TestImageStreamCompleter imageStreamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider provider = _TestImageProvider(streamCompleter: imageStreamCompleter);

    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          precacheImage(provider, context);
          return Container();
        },
      ),
    );

    // Two listeners - one is the listener added by precacheImage, the other by the ImageCache.
    final List<ImageStreamListener> listeners = imageStreamCompleter.listeners.toList();
    expect(listeners.length, 2);

    // Make sure the first listener can be called re-entrantly
    final ImageInfo imageInfo = ImageInfo(image: image10x10);
    listeners[1].onImage(imageInfo.clone(), false);
    listeners[1].onImage(imageInfo.clone(), false);

    // Make sure the second listener can be called re-entrantly.
    listeners[0].onImage(imageInfo.clone(), false);
    listeners[0].onImage(imageInfo.clone(), false);
  });

  testWidgets('Precache completes with onError on error', (WidgetTester tester) async {
    dynamic capturedException;
    StackTrace? capturedStackTrace;
    void errorListener(dynamic exception, StackTrace? stackTrace) {
      capturedException = exception;
      capturedStackTrace = stackTrace;
    }

    final Exception testException = Exception('cannot resolve host');
    final StackTrace testStack = StackTrace.current;
    final _TestImageProvider imageProvider = _TestImageProvider();
    late Future<void> precache;
    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          precache = precacheImage(imageProvider, context, onError: errorListener);
          return Container();
        },
      ),
    );
    imageProvider.fail(testException, testStack);
    await precache;

    // The image stream error handler should have the original exception.
    expect(capturedException, testException);
    expect(capturedStackTrace, testStack);
    // If there is an error listener, there should be no FlutterError reported.
    expect(tester.takeException(), isNull);
  });

  testWidgets('TickerMode controls stream registration', (WidgetTester tester) async {
    final _TestImageStreamCompleter imageStreamCompleter = _TestImageStreamCompleter();
    final Image image = Image(
      excludeFromSemantics: true,
      image: _TestImageProvider(streamCompleter: imageStreamCompleter),
    );
    await tester.pumpWidget(
      TickerMode(
        enabled: true,
        child: image,
      ),
    );
    expect(imageStreamCompleter.listeners.length, 2);
    await tester.pumpWidget(
      TickerMode(
        enabled: false,
        child: image,
      ),
    );
    expect(imageStreamCompleter.listeners.length, 1);
  });

  testWidgets('Verify Image shows correct RenderImage when changing to an already completed provider', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();

    final _TestImageProvider imageProvider1 = _TestImageProvider();
    final _TestImageProvider imageProvider2 = _TestImageProvider();
    final ui.Image image100x100 = (await tester.runAsync(() async => createTestImage(width: 100, height: 100)))!;

    await tester.pumpWidget(
        Container(
            key: key,
            child: Image(
                excludeFromSemantics: true,
                image: imageProvider1,
            ),
        ),
        null,
        EnginePhase.layout,
    );
    RenderImage renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNull);

    imageProvider1.complete(image10x10);
    imageProvider2.complete(image100x100);
    await tester.idle(); // resolve the future from the image provider
    await tester.pump(null, EnginePhase.layout);

    renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNotNull);

    final ui.Image oldImage = renderImage.image!;

    await tester.pumpWidget(
        Container(
            key: key,
            child: Image(
              excludeFromSemantics: true,
              image: imageProvider2,
            ),
        ),
        null,
        EnginePhase.layout,
    );

    renderImage = key.currentContext!.findRenderObject()! as RenderImage;
    expect(renderImage.image, isNotNull);
    expect(renderImage.image, isNot(equals(oldImage)));
  });

  testWidgets('Image State can be reconfigured to use another image', (WidgetTester tester) async {
    final Image image1 = Image(image: _TestImageProvider()..complete(image10x10.clone()), width: 10.0, excludeFromSemantics: true);
    final Image image2 = Image(image: _TestImageProvider()..complete(image10x10.clone()), width: 20.0, excludeFromSemantics: true);

    final Column column = Column(children: <Widget>[image1, image2]);
    await tester.pumpWidget(column, null, EnginePhase.layout);

    final Column columnSwapped = Column(children: <Widget>[image2, image1]);
    await tester.pumpWidget(columnSwapped, null, EnginePhase.layout);

    final List<RenderImage> renderObjects = tester.renderObjectList<RenderImage>(find.byType(Image)).toList();
    expect(renderObjects, hasLength(2));
    expect(renderObjects[0].image, isNotNull);
    expect(renderObjects[0].width, 20.0);
    expect(renderObjects[1].image, isNotNull);
    expect(renderObjects[1].width, 10.0);
  });

  testWidgets('Image contributes semantics', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Row(
          children: <Widget>[
            Image(
              image: _TestImageProvider(),
              width: 100.0,
              height: 100.0,
              semanticLabel: 'test',
            ),
          ],
        ),
      ),
    );

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: 1,
          label: 'test',
          rect: const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0),
          textDirection: TextDirection.ltr,
          flags: <SemanticsFlag>[SemanticsFlag.isImage],
        ),
      ],
    ), ignoreTransform: true));
    semantics.dispose();
  });

  testWidgets('Image can exclude semantics', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Image(
          image: _TestImageProvider(),
          width: 100.0,
          height: 100.0,
          excludeFromSemantics: true,
        ),
      ),
    );

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[],
    )));
    semantics.dispose();
  });

  testWidgets('Image invokes frameBuilder with correct frameNumber argument', (WidgetTester tester) async {
    final ui.Codec codec = (await tester.runAsync(() {
      return ui.instantiateImageCodec(Uint8List.fromList(kAnimatedGif));
    }))!;

    Future<ui.Image> nextFrame() async {
      final ui.FrameInfo frameInfo = (await tester.runAsync(codec.getNextFrame))!;
      return frameInfo.image;
    }

    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);
    int? lastFrame;

    await tester.pumpWidget(
      Image(
        image: imageProvider,
        frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
          lastFrame = frame;
          return Center(child: child);
        },
      ),
    );

    expect(lastFrame, isNull);
    expect(find.byType(Center), findsOneWidget);
    expect(find.byType(RawImage), findsOneWidget);
    streamCompleter.setData(imageInfo: ImageInfo(image: await nextFrame()));
    await tester.pump();
    expect(lastFrame, 0);
    expect(find.byType(Center), findsOneWidget);
    expect(find.byType(RawImage), findsOneWidget);
    streamCompleter.setData(imageInfo: ImageInfo(image: await nextFrame()));
    await tester.pump();
    expect(lastFrame, 1);
    expect(find.byType(Center), findsOneWidget);
    expect(find.byType(RawImage), findsOneWidget);
  });

  testWidgets('Image invokes frameBuilder with correct wasSynchronouslyLoaded=false', (WidgetTester tester) async {
    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);
    int? lastFrame;
    late bool lastFrameWasSync;

    await tester.pumpWidget(
      Image(
        image: imageProvider,
        frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
          lastFrame = frame;
          lastFrameWasSync = wasSynchronouslyLoaded;
          return child;
        },
      ),
    );

    expect(lastFrame, isNull);
    expect(lastFrameWasSync, isFalse);
    expect(find.byType(RawImage), findsOneWidget);
    streamCompleter.setData(imageInfo: ImageInfo(image: image10x10));
    await tester.pump();
    expect(lastFrame, 0);
    expect(lastFrameWasSync, isFalse);
  });

  testWidgets('Image invokes frameBuilder with correct wasSynchronouslyLoaded=true', (WidgetTester tester) async {
    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter(ImageInfo(image: image10x10.clone()));
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);
    int? lastFrame;
    late bool lastFrameWasSync;

    await tester.pumpWidget(
      Image(
        image: imageProvider,
        frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
          lastFrame = frame;
          lastFrameWasSync = wasSynchronouslyLoaded;
          return child;
        },
      ),
    );

    expect(lastFrame, 0);
    expect(lastFrameWasSync, isTrue);
    expect(find.byType(RawImage), findsOneWidget);
    streamCompleter.setData(imageInfo: ImageInfo(image: image10x10.clone()));
    await tester.pump();
    expect(lastFrame, 1);
    expect(lastFrameWasSync, isTrue);
  });

  testWidgets('Image state handles frameBuilder update', (WidgetTester tester) async {
    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);

    await tester.pumpWidget(
      Image(
        image: imageProvider,
        frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
          return Center(child: child);
        },
      ),
    );

    expect(find.byType(Center), findsOneWidget);
    expect(find.byType(RawImage), findsOneWidget);
    final State<Image> state = tester.state(find.byType(Image));

    await tester.pumpWidget(
      Image(
        image: imageProvider,
        frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
          return Padding(padding: const EdgeInsets.all(1), child: child);
        },
      ),
    );

    expect(find.byType(Center), findsNothing);
    expect(find.byType(Padding), findsOneWidget);
    expect(find.byType(RawImage), findsOneWidget);
    expect(tester.state(find.byType(Image)), same(state));
  });

  testWidgets('Image state handles enabling and disabling of tickers', (WidgetTester tester) async {
    final ui.Codec codec = (await tester.runAsync(() {
      return ui.instantiateImageCodec(Uint8List.fromList(kAnimatedGif));
    }))!;

    Future<ui.Image> nextFrame() async {
      final ui.FrameInfo frameInfo = (await tester.runAsync(codec.getNextFrame))!;
      return frameInfo.image;
    }

    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);
    int? lastFrame;
    int buildCount = 0;

    Widget buildFrame(BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
      lastFrame = frame;
      buildCount++;
      return child;
    }

    await tester.pumpWidget(
      TickerMode(
        enabled: true,
        child: Image(
          image: imageProvider,
          frameBuilder: buildFrame,
        ),
      ),
    );

    final State<Image> state = tester.state(find.byType(Image));
    expect(lastFrame, isNull);
    expect(buildCount, 1);
    streamCompleter.setData(imageInfo: ImageInfo(image: await nextFrame()));
    await tester.pump();
    expect(lastFrame, 0);
    expect(buildCount, 2);

    await tester.pumpWidget(
      TickerMode(
        enabled: false,
        child: Image(
          image: imageProvider,
          frameBuilder: buildFrame,
        ),
      ),
    );

    expect(tester.state(find.byType(Image)), same(state));
    expect(lastFrame, 0);
    expect(buildCount, 3);
    streamCompleter.setData(imageInfo: ImageInfo(image: await nextFrame()));
    streamCompleter.setData(imageInfo: ImageInfo(image: await nextFrame()));
    await tester.pump();
    expect(lastFrame, 0);
    expect(buildCount, 3);

    await tester.pumpWidget(
      TickerMode(
        enabled: true,
        child: Image(
          image: imageProvider,
          frameBuilder: buildFrame,
        ),
      ),
    );

    expect(tester.state(find.byType(Image)), same(state));
    expect(lastFrame, 1); // missed a frame because we weren't animating at the time
    expect(buildCount, 4);
  });

  testWidgets('Image invokes loadingBuilder on chunk event notification', (WidgetTester tester) async {
    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);
    final List<ImageChunkEvent?> chunkEvents = <ImageChunkEvent?>[];

    await tester.pumpWidget(
      Image(
        image: imageProvider,
        loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
          chunkEvents.add(loadingProgress);
          if (loadingProgress == null)
            return child;
          return Directionality(
            textDirection: TextDirection.ltr,
            child: Text('loading ${loadingProgress.cumulativeBytesLoaded} / ${loadingProgress.expectedTotalBytes}'),
          );
        },
      ),
    );

    expect(chunkEvents.length, 1);
    expect(chunkEvents.first, isNull);
    expect(tester.binding.hasScheduledFrame, isFalse);
    streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
    expect(tester.binding.hasScheduledFrame, isTrue);
    await tester.pump();
    expect(chunkEvents.length, 2);
    expect(find.text('loading 10 / 100'), findsOneWidget);
    expect(find.byType(RawImage), findsNothing);
    streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 30, expectedTotalBytes: 100));
    expect(tester.binding.hasScheduledFrame, isTrue);
    await tester.pump();
    expect(chunkEvents.length, 3);
    expect(find.text('loading 30 / 100'), findsOneWidget);
    expect(find.byType(RawImage), findsNothing);
    streamCompleter.setData(imageInfo: ImageInfo(image: image10x10));
    await tester.pump();
    expect(chunkEvents.length, 4);
    expect(find.byType(Text), findsNothing);
    expect(find.byType(RawImage), findsOneWidget);
  });

  testWidgets("Image doesn't rebuild on chunk events if loadingBuilder is null", (WidgetTester tester) async {
    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);

    await tester.pumpWidget(
      Image(
        image: imageProvider,
        excludeFromSemantics: true,
      ),
    );

    expect(tester.binding.hasScheduledFrame, isFalse);
    streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
    expect(tester.binding.hasScheduledFrame, isFalse);
    streamCompleter.setData(imageInfo: ImageInfo(image: image10x10));
    expect(tester.binding.hasScheduledFrame, isTrue);
    await tester.pump();
    streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
    expect(tester.binding.hasScheduledFrame, isFalse);
    expect(find.byType(RawImage), findsOneWidget);
  });

  testWidgets('Image chains the results of frameBuilder and loadingBuilder', (WidgetTester tester) async {
    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);

    await tester.pumpWidget(
      Image(
        image: imageProvider,
        excludeFromSemantics: true,
        frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
          return Padding(padding: const EdgeInsets.all(1), child: child);
        },
        loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
          return Center(child: child);
        },
      ),
    );

    expect(find.byType(Center), findsOneWidget);
    expect(find.byType(Padding), findsOneWidget);
    expect(find.byType(RawImage), findsOneWidget);
    expect(tester.widget<Padding>(find.byType(Padding)).child, isA<RawImage>());
    streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
    await tester.pump();
    expect(find.byType(Center), findsOneWidget);
    expect(find.byType(Padding), findsOneWidget);
    expect(find.byType(RawImage), findsOneWidget);
    expect(tester.widget<Center>(find.byType(Center)).child, isA<Padding>());
    expect(tester.widget<Padding>(find.byType(Padding)).child, isA<RawImage>());
  });

  testWidgets('Image state handles loadingBuilder update from null to non-null', (WidgetTester tester) async {
    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);

    await tester.pumpWidget(
      Image(image: imageProvider),
    );

    expect(find.byType(RawImage), findsOneWidget);
    streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
    expect(tester.binding.hasScheduledFrame, isFalse);
    final State<Image> state = tester.state(find.byType(Image));

    await tester.pumpWidget(
      Image(
        image: imageProvider,
        loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
          return Center(child: child);
        },
      ),
    );

    expect(find.byType(Center), findsOneWidget);
    expect(find.byType(RawImage), findsOneWidget);
    expect(tester.state(find.byType(Image)), same(state));
    streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
    expect(tester.binding.hasScheduledFrame, isTrue);
    await tester.pump();
    expect(find.byType(Center), findsOneWidget);
    expect(find.byType(RawImage), findsOneWidget);
  });

  testWidgets('Image state handles loadingBuilder update from non-null to null', (WidgetTester tester) async {
    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);

    await tester.pumpWidget(
      Image(
        image: imageProvider,
        loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
          return Center(child: child);
        },
      ),
    );

    expect(find.byType(Center), findsOneWidget);
    expect(find.byType(RawImage), findsOneWidget);
    streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
    expect(tester.binding.hasScheduledFrame, isTrue);
    await tester.pump();
    expect(find.byType(Center), findsOneWidget);
    expect(find.byType(RawImage), findsOneWidget);
    final State<Image> state = tester.state(find.byType(Image));

    await tester.pumpWidget(
      Image(image: imageProvider),
    );

    expect(find.byType(Center), findsNothing);
    expect(find.byType(RawImage), findsOneWidget);
    expect(tester.state(find.byType(Image)), same(state));
    streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
    expect(tester.binding.hasScheduledFrame, isFalse);
  });

  testWidgets('Verify Image resets its ImageListeners', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    final _TestImageStreamCompleter imageStreamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider1 = _TestImageProvider(streamCompleter: imageStreamCompleter);
    await tester.pumpWidget(
      Container(
        key: key,
        child: Image(
          image: imageProvider1,
        ),
      ),
    );
    // listener from resolveStreamForKey is always added.
    expect(imageStreamCompleter.listeners.length, 2);


    final _TestImageProvider imageProvider2 = _TestImageProvider();
    await tester.pumpWidget(
      Container(
        key: key,
        child: Image(
          image: imageProvider2,
          excludeFromSemantics: true,
        ),
      ),
      null,
      EnginePhase.layout,
    );

    // only listener from resolveStreamForKey is left.
    expect(imageStreamCompleter.listeners.length, 1);
  });

  testWidgets('Verify Image resets its ErrorListeners', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    final _TestImageStreamCompleter imageStreamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider1 = _TestImageProvider(streamCompleter: imageStreamCompleter);
    await tester.pumpWidget(
      Container(
        key: key,
        child: Image(
          image: imageProvider1,
          errorBuilder: (_,__,___) => Container(),
        ),
      ),
    );
    // listener from resolveStreamForKey is always added.
    expect(imageStreamCompleter.listeners.length, 2);


    final _TestImageProvider imageProvider2 = _TestImageProvider();
    await tester.pumpWidget(
      Container(
        key: key,
        child: Image(
          image: imageProvider2,
          excludeFromSemantics: true,
        ),
      ),
      null,
      EnginePhase.layout,
    );

    // only listener from resolveStreamForKey is left.
    expect(imageStreamCompleter.listeners.length, 1);
  });

  testWidgets('Image defers loading while fast scrolling', (WidgetTester tester) async {
    const int gridCells = 1000;
    final List<_TestImageProvider> imageProviders = <_TestImageProvider>[];
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(Directionality(
      textDirection: TextDirection.ltr,
      child: GridView.builder(
        controller: controller,
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
        itemCount: gridCells,
        itemBuilder: (_, int index) {
          final _TestImageProvider provider = _TestImageProvider();
          imageProviders.add(provider);
          return SizedBox(
            height: 250,
            width: 250,
            child: Image(
              image: provider,
              semanticLabel: index.toString(),
            ),
          );
        },
      ),
    ));

    bool loadCalled(_TestImageProvider provider) => provider.loadCalled;
    bool loadNotCalled(_TestImageProvider provider) => !provider.loadCalled;

    expect(find.bySemanticsLabel('5'), findsOneWidget);
    expect(imageProviders.length, 12);
    expect(imageProviders.every(loadCalled), true);

    imageProviders.clear();

    // Simulate a very fast fling.
    controller.animateTo(
      30000,
      duration: const Duration(seconds: 2),
      curve: Curves.linear,
    );
    await tester.pumpAndSettle();
    // The last 15 images on screen have loaded because the scrolling settled there.
    // The rest have not loaded.
    expect(imageProviders.length, 309);
    expect(imageProviders.skip(309 - 15).every(loadCalled), true);
    expect(imageProviders.take(309 - 15).every(loadNotCalled), true);
  });

  testWidgets('Same image provider in multiple parts of the tree, no cache room left', (WidgetTester tester) async {
    imageCache.maximumSize = 0;

    final _TestImageProvider provider1 = _TestImageProvider();
    final _TestImageProvider provider2 = _TestImageProvider();

    expect(provider1.loadCallCount, 0);
    expect(provider2.loadCallCount, 0);
    expect(imageCache.liveImageCount, 0);

    await tester.pumpWidget(Column(
      children: <Widget>[
        Image(image: provider1),
        Image(image: provider2),
        Image(image: provider1),
        Image(image: provider1),
        Image(image: provider2),
      ],
    ));

    expect(imageCache.liveImageCount, 2);
    expect(imageCache.statusForKey(provider1).live, true);
    expect(imageCache.statusForKey(provider1).pending, false);
    expect(imageCache.statusForKey(provider1).keepAlive, false);
    expect(imageCache.statusForKey(provider2).live, true);
    expect(imageCache.statusForKey(provider2).pending, false);
    expect(imageCache.statusForKey(provider2).keepAlive, false);

    expect(provider1.loadCallCount, 1);
    expect(provider2.loadCallCount, 1);

    provider1.complete(image10x10.clone());
    await tester.idle();

    provider2.complete(image10x10.clone());
    await tester.idle();

    expect(imageCache.liveImageCount, 2);
    expect(imageCache.currentSize, 0);

    await tester.pumpWidget(Image(image: provider2));
    await tester.idle();
    expect(imageCache.statusForKey(provider1).untracked, true);
    expect(imageCache.statusForKey(provider2).live, true);
    expect(imageCache.statusForKey(provider2).pending, false);
    expect(imageCache.statusForKey(provider2).keepAlive, false);
    expect(imageCache.liveImageCount, 1);

    await tester.pumpWidget(const SizedBox());
    await tester.idle();
    expect(provider1.loadCallCount, 1);
    expect(provider2.loadCallCount, 1);
    expect(imageCache.liveImageCount, 0);
  });

  testWidgets('precacheImage does not hold weak ref for more than a frame', (WidgetTester tester) async {
    imageCache.maximumSize = 0;
    final _TestImageProvider provider = _TestImageProvider();
    late Future<void> precache;
    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          precache = precacheImage(provider, context);
          return Container();
        },
      ),
    );
    provider.complete(image10x10);
    await precache;

    // Should have ended up with only a weak ref, not in cache because cache size is 0
    expect(imageCache.liveImageCount, 1);
    expect(imageCache.containsKey(provider), false);

    final ImageCacheStatus providerLocation = (await provider.obtainCacheStatus(configuration: ImageConfiguration.empty))!;

    expect(providerLocation, isNotNull);
    expect(providerLocation.live, true);
    expect(providerLocation.keepAlive, false);
    expect(providerLocation.pending, false);

    // Check that a second resolve of the same image is synchronous.
    expect(provider._lastResolvedConfiguration, isNotNull);
    final ImageStream stream = provider.resolve(provider._lastResolvedConfiguration);
    late bool isSync;
    final ImageStreamListener listener = ImageStreamListener((ImageInfo image, bool syncCall) { isSync = syncCall; });

    // Still have live ref because frame has not pumped yet.
    await tester.pump();
    expect(imageCache.liveImageCount, 1);

    SchedulerBinding.instance.scheduleFrame();
    await tester.pump();
    // Live ref should be gone - we didn't listen to the stream.
    expect(imageCache.liveImageCount, 0);
    expect(imageCache.currentSize, 0);

    stream.addListener(listener);
    expect(isSync, true); // because the stream still has the image.

    expect(imageCache.liveImageCount, 0);
    expect(imageCache.currentSize, 0);

    expect(provider.loadCallCount, 1);
  });

  testWidgets('precacheImage allows time to take over weak reference', (WidgetTester tester) async {
    final _TestImageProvider provider = _TestImageProvider();
    late Future<void> precache;
    await tester.pumpWidget(
      Builder(
        builder: (BuildContext context) {
          precache = precacheImage(provider, context);
          return Container();
        },
      ),
    );
    provider.complete(image10x10);
    await precache;

    // Should have ended up in the cache and have a weak reference.
    expect(imageCache.liveImageCount, 1);
    expect(imageCache.currentSize, 1);
    expect(imageCache.containsKey(provider), true);

    // Check that a second resolve of the same image is synchronous.
    expect(provider._lastResolvedConfiguration, isNotNull);
    final ImageStream stream = provider.resolve(provider._lastResolvedConfiguration);
    late bool isSync;
    final ImageStreamListener listener = ImageStreamListener((ImageInfo image, bool syncCall) { isSync = syncCall; });

    // Should have ended up in the cache and still have a weak reference.
    expect(imageCache.liveImageCount, 1);
    expect(imageCache.currentSize, 1);
    expect(imageCache.containsKey(provider), true);

    stream.addListener(listener);
    expect(isSync, true);

    expect(imageCache.liveImageCount, 1);
    expect(imageCache.currentSize, 1);
    expect(imageCache.containsKey(provider), true);

    SchedulerBinding.instance.scheduleFrame();
    await tester.pump();

    expect(imageCache.liveImageCount, 1);
    expect(imageCache.currentSize, 1);
    expect(imageCache.containsKey(provider), true);
    stream.removeListener(listener);

    expect(imageCache.liveImageCount, 0);
    expect(imageCache.currentSize, 1);
    expect(imageCache.containsKey(provider), true);
    expect(provider.loadCallCount, 1);
  });

  testWidgets('evict an image during precache', (WidgetTester tester) async {
    // This test checks that the live image tracking does not hold on to a
    // pending image that will never complete because it has been evicted from
    // the cache.
    // The scenario may arise in a test harness that is trying to load real
    // images using `tester.runAsync()`, and wants to make sure that widgets
    // under test have not also tried to resolve the image in a FakeAsync zone.
    // The image loaded in the FakeAsync zone will never complete, and the
    // runAsync call wants to make sure it gets a load attempt from the correct
    // zone.
    final Uint8List bytes = Uint8List.fromList(kTransparentImage);
    final MemoryImage provider = MemoryImage(bytes);

    await tester.runAsync(() async {
      final List<Future<void>> futures = <Future<void>>[];
      await tester.pumpWidget(Builder(builder: (BuildContext context) {
        futures.add(precacheImage(provider, context));
        imageCache.evict(provider);
        futures.add(precacheImage(provider, context));
        return const SizedBox.expand();
      }));
      await Future.wait<void>(futures);
      expect(imageCache.statusForKey(provider).keepAlive, true);
      expect(imageCache.statusForKey(provider).live, true);

      // Schedule a frame to get precacheImage to stop listening.
      SchedulerBinding.instance.scheduleFrame();
      await tester.pump();
      expect(imageCache.statusForKey(provider).keepAlive, true);
      expect(imageCache.statusForKey(provider).live, false);
    });
  });

  testWidgets('errorBuilder - fails on key', (WidgetTester tester) async {
    final UniqueKey errorKey = UniqueKey();
    late Object caughtException;
    await tester.pumpWidget(
      Image(
        image: _FailingImageProvider(failOnObtainKey: true, throws: 'threw', image: image10x10),
        errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) {
          caughtException = error;
          return SizedBox.expand(key: errorKey);
        },
      ),
    );

    await tester.pump();

    expect(find.byKey(errorKey), findsOneWidget);
    expect(caughtException.toString(), 'threw');
    expect(tester.takeException(), isNull);
  });

  testWidgets('errorBuilder - fails on load', (WidgetTester tester) async {
    final UniqueKey errorKey = UniqueKey();
    late Object caughtException;
    await tester.pumpWidget(
      Image(
        image: _FailingImageProvider(failOnLoad: true, throws: 'threw', image: image10x10),
        errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) {
          caughtException = error;
          return SizedBox.expand(key: errorKey);
        },
      ),
    );

    await tester.pump();

    expect(find.byKey(errorKey), findsOneWidget);
    expect(caughtException.toString(), 'threw');
    expect(tester.takeException(), isNull);
  });

  testWidgets('no errorBuilder - failure reported to FlutterError', (WidgetTester tester) async {
    await tester.pumpWidget(
      Image(
        image: _FailingImageProvider(failOnLoad: true, throws: 'threw', image: image10x10),
      ),
    );

    await tester.pump();

    expect(tester.takeException(), 'threw');
  });

  Future<void> _testRotatedImage(WidgetTester tester, bool isAntiAlias) async {
    final Key key = UniqueKey();
    await tester.pumpWidget(RepaintBoundary(
      key: key,
      child: Transform.rotate(
        angle: math.pi / 180,
        child: Image.memory(Uint8List.fromList(kBlueRectPng), isAntiAlias: isAntiAlias),
      ),
    ));

    // precacheImage is needed, or the image in the golden file will be empty.
    if (!kIsWeb) {
      final Finder allImages = find.byType(Image);
      for (final Element e in allImages.evaluate()) {
        await tester.runAsync(() async {
          final Image image = e.widget as Image;
          await precacheImage(image.image, e);
        });
      }
      await tester.pumpAndSettle();
    }

    await expectLater(
      find.byKey(key),
      matchesGoldenFile('rotated_image_${isAntiAlias ? 'aa' : 'noaa'}.png'),
    );
  }

  testWidgets(
    'Rotated images',
    (WidgetTester tester) async {
      await _testRotatedImage(tester, true);
      await _testRotatedImage(tester, false);
    },
    skip: kIsWeb, // https://github.com/flutter/flutter/issues/87933.
  );

  testWidgets(
    'Image opacity',
    (WidgetTester tester) async {
      final Key key = UniqueKey();
      await tester.pumpWidget(RepaintBoundary(
        key: key,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          textDirection: TextDirection.ltr,
          children: <Widget>[
            Image.memory(
              Uint8List.fromList(kBlueRectPng),
              opacity: const AlwaysStoppedAnimation<double>(0.25),
            ),
            Image.memory(
              Uint8List.fromList(kBlueRectPng),
              opacity: const AlwaysStoppedAnimation<double>(0.5),
            ),
            Image.memory(
              Uint8List.fromList(kBlueRectPng),
              opacity: const AlwaysStoppedAnimation<double>(0.75),
            ),
            Image.memory(
              Uint8List.fromList(kBlueRectPng),
              opacity: const AlwaysStoppedAnimation<double>(1.0),
            ),
          ],
        ),
      ));

      // precacheImage is needed, or the image in the golden file will be empty.
      if (!kIsWeb) {
        final Finder allImages = find.byType(Image);
        for (final Element e in allImages.evaluate()) {
          await tester.runAsync(() async {
            final Image image = e.widget as Image;
            await precacheImage(image.image, e);
          });
        }
        await tester.pumpAndSettle();
      }

      await expectLater(
        find.byKey(key),
        matchesGoldenFile('transparent_image.png'),
      );
    },
    skip: kIsWeb, // https://github.com/flutter/flutter/issues/87933.
  );

  testWidgets('Reports image size when painted', (WidgetTester tester) async {
    late ImageSizeInfo imageSizeInfo;
    int count = 0;
    debugOnPaintImage = (ImageSizeInfo info) {
      count += 1;
      imageSizeInfo = info;
    };

    final ui.Image image = (await tester.runAsync(() => createTestImage(width: 100, height: 100)))!;
    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter(
      ImageInfo(
        image: image,
        debugLabel: 'test.png',
      ),
    );
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          height: 50,
          width: 50,
          child: Image(image: imageProvider),
        ),
      ),
    );

    expect(count, 1);
    expect(
      imageSizeInfo,
      const ImageSizeInfo(
        source: 'test.png',
        imageSize: Size(100, 100),
        displaySize: Size(150, 150),
      ),
    );

    debugOnPaintImage = null;
  });

  testWidgets('Disposes image handle when disposed', (WidgetTester tester) async {
    final ui.Image image = (await tester.runAsync(() => createTestImage(cache: false)))!;

    expect(image.debugGetOpenHandleStackTraces()!.length, 1);

    final ImageProvider provider = _TestImageProvider(
      streamCompleter: OneFrameImageStreamCompleter(
        Future<ImageInfo>.value(
          ImageInfo(
            image: image,
            debugLabel: '_TestImage',
          ),
        ),
      ),
    );

    // creating the provider should not have changed anything, and the provider
    // now owns the handle.
    expect(image.debugGetOpenHandleStackTraces()!.length, 1);

    await tester.pumpWidget(Image(image: provider));

    // Image widget + 1, render object + 1
    expect(image.debugGetOpenHandleStackTraces()!.length, 3);

    await tester.pumpWidget(const SizedBox());

    // Image widget and render object go away
    expect(image.debugGetOpenHandleStackTraces()!.length, 1);

    await provider.evict();

    tester.binding.scheduleFrame();
    await tester.pump();

    // Image cache listener go away and Image stream listeners go away.
    // Image is now at zero.
    expect(image.debugGetOpenHandleStackTraces()!.length, 0);
  }, skip: kIsWeb); // https://github.com/flutter/flutter/issues/87442

  testWidgets('Keeps stream alive when ticker mode is disabled',  (WidgetTester tester) async {
    imageCache.maximumSize = 0;
    final ui.Image image = (await tester.runAsync(() => createTestImage(cache: false)))!;
    final _TestImageProvider provider = _TestImageProvider();
    provider.complete(image);

    await tester.pumpWidget(
      TickerMode(
        enabled: true,
        child: Image(image: provider),
      ),
    );
    expect(find.byType(Image), findsOneWidget);

    await tester.pumpWidget(TickerMode(
        enabled: false,
        child: Image(image: provider),
      ),
    );
    expect(find.byType(Image), findsOneWidget);

    await tester.pumpWidget(TickerMode(
        enabled: true,
        child: Image(image: provider),
      ),
    );
    expect(find.byType(Image), findsOneWidget);
  });

  testWidgets('Load a good image after a bad image was loaded should not call errorBuilder', (WidgetTester tester) async {
    final UniqueKey errorKey = UniqueKey();
    final ui.Image image = (await tester.runAsync(() => createTestImage()))!;
    final _TestImageStreamCompleter streamCompleter = _TestImageStreamCompleter();
    final _TestImageProvider imageProvider = _TestImageProvider(streamCompleter: streamCompleter);

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          height: 50,
          width: 50,
          child: Image(
            image: imageProvider,
            excludeFromSemantics: true,
            errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) {
              return Container(key: errorKey);
            },
            frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) {
              return Padding(padding: const EdgeInsets.all(1), child: child);
            },
          ),
        ),
      ),
    );

    // No error widget before loading a invalid image.
    expect(find.byKey(errorKey), findsNothing);

    // Loading good image succeed
    streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
    await tester.pump();
    expect(find.byType(Padding), findsOneWidget);

    // Loading bad image shows the error widget.
    streamCompleter.setError(exception: 'thrown');
    await tester.pump();
    expect(find.byKey(errorKey), findsOneWidget);

    // Loading good image shows the image widget instead of the error widget.
    streamCompleter.setData(imageInfo: ImageInfo(image: image));
    await tester.pump();
    expect(find.byType(Padding), findsOneWidget);
    expect(tester.widget<Padding>(find.byType(Padding)).child, isA<RawImage>());
    expect(find.byKey(errorKey), findsNothing);
  });

  testWidgets('Failed image loads in debug mode', (WidgetTester tester) async {
    final Key key = UniqueKey();
    await tester.pumpWidget(Center(
      child: RepaintBoundary(
        key: key,
        child: Container(
          width: 150.0,
          height: 50.0,
          decoration: BoxDecoration(
            border: Border.all(
              width: 2.0,
              color: const Color(0xFF00FF99),
            ),
          ),
          child: Image.asset('missing-asset'),
        ),
      ),
    ));
    await expectLater(
      find.byKey(key),
      matchesGoldenFile('image_test.missing.1.png'),
    );
    expect(tester.takeException().toString(), startsWith('Unable to load asset: '));
    await tester.pump();
    await expectLater(
      find.byKey(key),
      matchesGoldenFile('image_test.missing.2.png'),
    );
  }, skip: kIsWeb); // https://github.com/flutter/flutter/issues/74935 (broken assets not being reported on web)

  testWidgets('Image.file throws a non-implemented error on web', (WidgetTester tester) async {
    const String expectedError =
      'Image.file is not supported on Flutter Web. '
      'Consider using either Image.asset or Image.network instead.';
    final Uri uri = Uri.parse('/home/flutter/dash.png');
    final File file = File.fromUri(uri);
    expect(
      () => Image.file(file),
      kIsWeb
        // Web does not support file access, expect AssertionError
        ? throwsA(predicate((AssertionError e) => e.message == expectedError))
        // AOT supports file access, expect constructor to succeed
        : isNot(throwsA(anything)),
    );
  });
}

@immutable
class _ConfigurationAwareKey {
  const _ConfigurationAwareKey(this.provider, this.configuration)
    : assert(provider != null),
      assert(configuration != null);

  final ImageProvider provider;
  final ImageConfiguration configuration;

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is _ConfigurationAwareKey
        && other.provider == provider
        && other.configuration == configuration;
  }

  @override
  int get hashCode => Object.hash(provider, configuration);
}

class _ConfigurationKeyedTestImageProvider extends _TestImageProvider {
  @override
  Future<_ConfigurationAwareKey> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<_ConfigurationAwareKey>(_ConfigurationAwareKey(this, configuration));
  }
}

class _TestImageProvider extends ImageProvider<Object> {
  _TestImageProvider({ImageStreamCompleter? streamCompleter}) {
    _streamCompleter = streamCompleter
      ?? OneFrameImageStreamCompleter(_completer.future);
  }

  final Completer<ImageInfo> _completer = Completer<ImageInfo>();
  late ImageStreamCompleter _streamCompleter;
  late ImageConfiguration _lastResolvedConfiguration;

  bool get loadCalled => _loadCallCount > 0;
  int get loadCallCount => _loadCallCount;
  int _loadCallCount = 0;

  @override
  Future<Object> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<_TestImageProvider>(this);
  }

  @override
  void resolveStreamForKey(ImageConfiguration configuration, ImageStream stream, Object key, ImageErrorListener handleError) {
    _lastResolvedConfiguration = configuration;
    super.resolveStreamForKey(configuration, stream, key, handleError);
  }

  @override
  ImageStreamCompleter load(Object key, DecoderCallback decode) {
    _loadCallCount += 1;
    return _streamCompleter;
  }

  void complete(ui.Image image) {
    _completer.complete(ImageInfo(image: image));
  }

  void fail(Object exception, StackTrace? stackTrace) {
    _completer.completeError(exception, stackTrace);
  }

  @override
  String toString() => '${describeIdentity(this)}()';
}

class _TestImageStreamCompleter extends ImageStreamCompleter {
  _TestImageStreamCompleter([this._currentImage]);

  ImageInfo? _currentImage;
  final Set<ImageStreamListener> listeners = <ImageStreamListener>{};

  @override
  void addListener(ImageStreamListener listener) {
    listeners.add(listener);
    if (_currentImage != null) {
      listener.onImage(_currentImage!.clone(), true);
    }
  }

  @override
  void removeListener(ImageStreamListener listener) {
    listeners.remove(listener);
  }

  void setData({
    ImageInfo? imageInfo,
    ImageChunkEvent? chunkEvent,
  }) {
    if (imageInfo != null) {
      _currentImage?.dispose();
      _currentImage = imageInfo;
    }
    final List<ImageStreamListener> localListeners = listeners.toList();
    for (final ImageStreamListener listener in localListeners) {
      if (imageInfo != null) {
        listener.onImage(imageInfo.clone(), false);
      }
      if (chunkEvent != null && listener.onChunk != null) {
        listener.onChunk!(chunkEvent);
      }
    }
  }

  void setError({
    required Object exception,
    StackTrace? stackTrace,
  }) {
    final List<ImageStreamListener> localListeners = listeners.toList();
    for (final ImageStreamListener listener in localListeners) {
      listener.onError?.call(exception, stackTrace);
    }
  }
}

class _DebouncingImageProvider extends ImageProvider<Object> {
  _DebouncingImageProvider(this.imageProvider, this.seenKeys);

  /// A set of keys that will only get resolved the _first_ time they are seen.
  ///
  /// If an ImageProvider produces the same key for two different image
  /// configurations, it should only actually resolve once using this provider.
  /// However, if it does care about image configuration, it should make the
  /// property or properties it cares about part of the key material it
  /// produces.
  final Set<Object> seenKeys;
  final ImageProvider<Object> imageProvider;

  @override
  void resolveStreamForKey(ImageConfiguration configuration, ImageStream stream, Object key, ImageErrorListener handleError) {
    if (seenKeys.add(key)) {
      imageProvider.resolveStreamForKey(configuration, stream, key, handleError);
    }
  }

  @override
  Future<Object> obtainKey(ImageConfiguration configuration) => imageProvider.obtainKey(configuration);

  @override
  ImageStreamCompleter load(Object key, DecoderCallback decode) => imageProvider.load(key, decode);
}

class _FailingImageProvider extends ImageProvider<int> {
  const _FailingImageProvider({
    this.failOnObtainKey = false,
    this.failOnLoad = false,
    required this.throws,
    required this.image,
  }) : assert(failOnLoad != null),
       assert(failOnObtainKey != null),
       assert(failOnLoad == true || failOnObtainKey == true),
       assert(throws != null),
       assert(image != null);

  final bool failOnObtainKey;
  final bool failOnLoad;
  final Object throws;
  final ui.Image image;

  @override
  Future<int> obtainKey(ImageConfiguration configuration) {
    if (failOnObtainKey) {
      throw throws;
    }
    return SynchronousFuture<int>(hashCode);
  }

  @override
  ImageStreamCompleter load(int key, DecoderCallback decode) {
    if (failOnLoad) {
      throw throws;
    }
    return OneFrameImageStreamCompleter(
      Future<ImageInfo>.value(
        ImageInfo(
          image: image,
          scale: 0,
        ),
      ),
    );
  }
}
