image_provider_test.dart 5.05 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// 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 'package:file/memory.dart';
9
import 'package:flutter/foundation.dart';
10
import 'package:flutter/painting.dart';
11 12
import 'package:flutter_test/flutter_test.dart';

13
import '../rendering/rendering_tester.dart';
14
import 'mocks_for_image_cache.dart';
15

16
void main() {
17
  TestRenderingFlutterBinding();
18

19 20 21 22 23 24 25
  FlutterExceptionHandler oldError;
  setUp(() {
    oldError = FlutterError.onError;
  });

  tearDown(() {
    FlutterError.onError = oldError;
26
    PaintingBinding.instance.imageCache.clear();
Dan Field's avatar
Dan Field committed
27
    PaintingBinding.instance.imageCache.clearLiveImages();
28 29
  });

30 31 32 33 34 35 36 37 38 39 40 41 42 43
  test('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(ImageStreamListener((ImageInfo info, bool syncCall) {
      caughtError.complete(false);
    }, onError: (dynamic error, StackTrace stackTrace) {
      caughtError.complete(true);
    }));
    expect(await caughtError.future, true);
  });
44

45 46 47 48 49 50 51
  test('obtainKey errors will be caught - check location', () async {
    final ImageProvider imageProvider = ObtainKeyErrorImageProvider();
    final Completer<bool> caughtError = Completer<bool>();
    FlutterError.onError = (FlutterErrorDetails details) {
      caughtError.complete(true);
    };
    await imageProvider.obtainCacheStatus(configuration: ImageConfiguration.empty);
52

53 54
    expect(await caughtError.future, true);
  });
55

56 57 58 59 60 61 62 63 64
  test('resolve sync errors will be caught', () async {
    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();
65 66
      final Completer<bool> caughtError = Completer<bool>();
      FlutterError.onError = (FlutterErrorDetails details) {
67
        throw Error();
68
      };
69 70
      final ImageStream result = imageProvider.resolve(ImageConfiguration.empty);
      result.addListener(ImageStreamListener((ImageInfo info, bool syncCall) {
71 72
      }, onError: (dynamic error, StackTrace stackTrace) {
        caughtError.complete(true);
73
      }));
74 75
      expect(await caughtError.future, true);
    });
76 77
    expect(uncaught, false);
  });
78

79 80 81 82 83 84 85 86 87
  test('resolve errors in the completer will be caught', () async {
    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();
Dan Field's avatar
Dan Field committed
88 89
      final Completer<bool> caughtError = Completer<bool>();
      FlutterError.onError = (FlutterErrorDetails details) {
90
        throw Error();
Dan Field's avatar
Dan Field committed
91
      };
92 93 94 95 96
      final ImageStream result = imageProvider.resolve(ImageConfiguration.empty);
      result.addListener(ImageStreamListener((ImageInfo info, bool syncCall) {
      }, onError: (dynamic error, StackTrace stackTrace) {
        caughtError.complete(true);
      }));
Dan Field's avatar
Dan Field committed
97 98
      expect(await caughtError.future, true);
    });
99
    expect(uncaught, false);
100
  });
101

102 103 104 105
  test('File image with empty file throws expected error and evicts from cache', () async {
    final Completer<StateError> error = Completer<StateError>();
    FlutterError.onError = (FlutterErrorDetails details) {
      error.complete(details.exception as StateError);
106
    };
107 108 109
    final MemoryFileSystem fs = MemoryFileSystem();
    final File file = fs.file('/empty.png')..createSync(recursive: true);
    final FileImage provider = FileImage(file);
110

111 112
    expect(imageCache.statusForKey(provider).untracked, true);
    expect(imageCache.pendingImageCount, 0);
113

114
    provider.resolve(ImageConfiguration.empty);
115

116 117
    expect(imageCache.statusForKey(provider).pending, true);
    expect(imageCache.pendingImageCount, 1);
118

119 120 121
    expect(await error.future, isStateError);
    expect(imageCache.statusForKey(provider).untracked, true);
    expect(imageCache.pendingImageCount, 0);
122 123
  });

124 125 126 127 128 129 130 131 132 133 134 135 136
  test('File image with empty file throws expected error (load)', () async {
    final Completer<StateError> error = Completer<StateError>();
    FlutterError.onError = (FlutterErrorDetails details) {
      error.complete(details.exception as StateError);
    };
    final MemoryFileSystem fs = MemoryFileSystem();
    final File file = fs.file('/empty.png')..createSync(recursive: true);
    final FileImage provider = FileImage(file);

    expect(provider.load(provider, null), isA<MultiFrameImageStreamCompleter>());

    expect(await error.future, isStateError);
  });
137
}