image_provider_test.dart 6.37 KB
Newer Older
1 2 3 4
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'dart:async';
6
import 'dart:io';
7 8
import 'dart:typed_data';

9
import 'package:flutter/foundation.dart';
10
import 'package:flutter/painting.dart';
11
import 'package:flutter_test/flutter_test.dart';
12
import 'package:mockito/mockito.dart';
13

14 15
import '../rendering/rendering_tester.dart';
import 'image_data.dart';
16
import 'mocks_for_image_cache.dart';
17

18
void main() {
19
  TestRenderingFlutterBinding(); // initializes the imageCache
20 21 22 23 24 25 26
  group(ImageProvider, () {
    tearDown(() {
      imageCache.clear();
    });

    test('NetworkImage non-null url test', () {
      expect(() {
27
        NetworkImage(nonconst(null));
28 29 30 31
      }, throwsAssertionError);
    });

    test('ImageProvider can evict images', () async {
32 33
      final Uint8List bytes = Uint8List.fromList(kTransparentImage);
      final MemoryImage imageProvider = MemoryImage(bytes);
34
      final ImageStream stream = imageProvider.resolve(ImageConfiguration.empty);
35
      final Completer<void> completer = Completer<void>();
36 37 38 39
      stream.addListener((ImageInfo info, bool syncCall) => completer.complete());
      await completer.future;

      expect(imageCache.currentSize, 1);
40
      expect(await MemoryImage(bytes).evict(), true);
41 42 43 44
      expect(imageCache.currentSize, 0);
    });

    test('ImageProvider.evict respects the provided ImageCache', () async {
45 46 47
      final ImageCache otherCache = ImageCache();
      final Uint8List bytes = Uint8List.fromList(kTransparentImage);
      final MemoryImage imageProvider = MemoryImage(bytes);
48 49
      otherCache.putIfAbsent(imageProvider, () => imageProvider.load(imageProvider));
      final ImageStream stream = imageProvider.resolve(ImageConfiguration.empty);
50
      final Completer<void> completer = Completer<void>();
51 52 53 54 55 56 57 58 59
      stream.addListener((ImageInfo info, bool syncCall) => completer.complete());
      await completer.future;

      expect(otherCache.currentSize, 1);
      expect(imageCache.currentSize, 1);
      expect(await imageProvider.evict(cache: otherCache), true);
      expect(otherCache.currentSize, 0);
      expect(imageCache.currentSize, 1);
    });
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

    test('ImageProvider errors can always be caught', () async {
      final ErrorImageProvider imageProvider = ErrorImageProvider();
      final Completer<bool> caughtError = Completer<bool>();
      FlutterError.onError = (FlutterErrorDetails details) {
        caughtError.complete(false);
      };
      final ImageStream stream = imageProvider.resolve(ImageConfiguration.empty);
      stream.addListener((ImageInfo info, bool syncCall) {
        caughtError.complete(false);
      }, onError: (dynamic error, StackTrace stackTrace) {
        caughtError.complete(true);
      });
      expect(await caughtError.future, true);
    });
75
  });
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90

  test('ImageProvide.obtainKey errors will be caught', () async {
    final ImageProvider imageProvider = ObtainKeyErrorImageProvider();
    final Completer<bool> caughtError = Completer<bool>();
    FlutterError.onError = (FlutterErrorDetails details) {
      caughtError.complete(false);
    };
    final ImageStream stream = imageProvider.resolve(ImageConfiguration.empty);
    stream.addListener((ImageInfo info, bool syncCall) {
      caughtError.complete(false);
    }, onError: (dynamic error, StackTrace stackTrace) {
      caughtError.complete(true);
    });
    expect(await caughtError.future, true);
  });
91 92

  test('ImageProvider.resolve sync errors will be caught', () async {
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
    bool uncaught = false;
    final Zone testZone = Zone.current.fork(specification: ZoneSpecification(
      handleUncaughtError: (Zone zone, ZoneDelegate zoneDelegate, Zone parent, Object error, StackTrace stackTrace) {
        uncaught = true;
      }
    ));
    await testZone.run(() async {
      final ImageProvider imageProvider = LoadErrorImageProvider();
      final Completer<bool> caughtError = Completer<bool>();
      FlutterError.onError = (FlutterErrorDetails details) {
        throw Error();
      };
      final ImageStream result = imageProvider.resolve(ImageConfiguration.empty);
      result.addListener((ImageInfo info, bool syncCall) {
      }, onError: (dynamic error, StackTrace stackTrace) {
        caughtError.complete(true);
      });
      expect(await caughtError.future, true);
111
    });
112
    expect(uncaught, false);
113 114 115
  });

   test('ImageProvider.resolve errors in the completer will be caught', () async {
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
    bool uncaught = false;
    final Zone testZone = Zone.current.fork(specification: ZoneSpecification(
      handleUncaughtError: (Zone zone, ZoneDelegate zoneDelegate, Zone parent, Object error, StackTrace stackTrace) {
        uncaught = true;
      }
    ));
    await testZone.run(() async {
      final ImageProvider imageProvider = LoadErrorCompleterImageProvider();
      final Completer<bool> caughtError = Completer<bool>();
      FlutterError.onError = (FlutterErrorDetails details) {
        throw Error();
      };
      final ImageStream result = imageProvider.resolve(ImageConfiguration.empty);
      result.addListener((ImageInfo info, bool syncCall) {
      }, onError: (dynamic error, StackTrace stackTrace) {
        caughtError.complete(true);
      });
      expect(await caughtError.future, true);
134
    });
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
    expect(uncaught, false);
  });

  test('ImageProvider.resolve errors in the http client will be caught', () async {
    bool uncaught = false;
    final HttpClientMock httpClientMock = HttpClientMock();
    when(httpClientMock.getUrl(any)).thenThrow(Error());

    await HttpOverrides.runZoned(() async {
      const ImageProvider imageProvider = NetworkImage('asdasdasdas');
      final Completer<bool> caughtError = Completer<bool>();
      FlutterError.onError = (FlutterErrorDetails details) {
        throw Error();
      };
      final ImageStream result = imageProvider.resolve(ImageConfiguration.empty);
      result.addListener((ImageInfo info, bool syncCall) {
      }, onError: (dynamic error, StackTrace stackTrace) {
        caughtError.complete(true);
      });
      expect(await caughtError.future, true);
    }, createHttpClient: (SecurityContext context) => httpClientMock, zoneSpecification: ZoneSpecification(
      handleUncaughtError: (Zone zone, ZoneDelegate zoneDelegate, Zone parent, Object error, StackTrace stackTrace) {
        uncaught = true;
      }
    ));
    expect(uncaught, false);
161
  });
162
}
163 164

class HttpClientMock extends Mock implements HttpClient {}