@@ -41,10 +41,16 @@ class MockCodec implements Codec {
41
41
42
42
int numFramesAsked = 0 ;
43
43
44
+ bool disposed = false ;
45
+
44
46
Completer <FrameInfo > _nextFrameCompleter = Completer <FrameInfo >();
45
47
46
48
@override
47
49
Future <FrameInfo > getNextFrame () {
50
+ if (disposed) {
51
+ throw StateError ('Codec is disposed' );
52
+ }
53
+
48
54
numFramesAsked += 1 ;
49
55
return _nextFrameCompleter.future;
50
56
}
@@ -59,7 +65,13 @@ class MockCodec implements Codec {
59
65
}
60
66
61
67
@override
62
- void dispose () {}
68
+ void dispose () {
69
+ if (disposed) {
70
+ throw StateError ('Codec is already disposed' );
71
+ }
72
+
73
+ disposed = true ;
74
+ }
63
75
}
64
76
65
77
class FakeEventReportingImageStreamCompleter extends ImageStreamCompleter {
@@ -106,6 +118,7 @@ void main() {
106
118
imageStream.addListener (ImageStreamListener (listener));
107
119
await tester.idle ();
108
120
expect (mockCodec.numFramesAsked, 1 );
121
+ expect (mockCodec.disposed, false );
109
122
});
110
123
111
124
testWidgets ('Decoding starts when a codec is ready after a listener is added' , (
@@ -130,6 +143,7 @@ void main() {
130
143
completer.complete (mockCodec);
131
144
await tester.idle ();
132
145
expect (mockCodec.numFramesAsked, 1 );
146
+ expect (mockCodec.disposed, false );
133
147
});
134
148
135
149
testWidgets ('Decoding does not crash when disposed' , (WidgetTester tester) async {
@@ -156,7 +170,9 @@ void main() {
156
170
157
171
final FrameInfo frame = FakeFrameInfo (const Duration (milliseconds: 200 ), image20x10);
158
172
mockCodec.completeNextFrame (frame);
173
+ expect (mockCodec.disposed, false );
159
174
imageStream.removeListener (streamListener);
175
+ expect (mockCodec.disposed, true );
160
176
await tester.idle ();
161
177
});
162
178
@@ -334,6 +350,7 @@ void main() {
334
350
await tester.idle ();
335
351
336
352
expect (tester.takeException (), 'frame completion error' );
353
+ expect (mockCodec.disposed, false );
337
354
});
338
355
339
356
testWidgets ('ImageStream emits frame (static image)' , (WidgetTester tester) async {
@@ -362,7 +379,9 @@ void main() {
362
379
363
380
final FrameInfo frame = FakeFrameInfo (const Duration (milliseconds: 200 ), image20x10);
364
381
mockCodec.completeNextFrame (frame);
382
+ expect (mockCodec.disposed, false );
365
383
await tester.idle ();
384
+ expect (mockCodec.disposed, true );
366
385
367
386
expect (emittedImages.every ((ImageInfo info) => info.image.isCloneOf (frame.image)), true );
368
387
@@ -420,7 +439,9 @@ void main() {
420
439
// quit the test without pending timers.
421
440
await tester.pump (const Duration (milliseconds: 400 ));
422
441
442
+ expect (mockCodec.disposed, false );
423
443
imageStream.removeListener (listener);
444
+ expect (mockCodec.disposed, true );
424
445
imageCache.clear ();
425
446
});
426
447
@@ -469,7 +490,9 @@ void main() {
469
490
// quit the test without pending timers.
470
491
await tester.pump (const Duration (milliseconds: 200 ));
471
492
493
+ expect (mockCodec.disposed, false );
472
494
imageStream.removeListener (listener);
495
+ expect (mockCodec.disposed, true );
473
496
imageCache.clear ();
474
497
});
475
498
@@ -505,7 +528,9 @@ void main() {
505
528
await tester.pump (); // first animation frame shows on first app frame.
506
529
mockCodec.completeNextFrame (frame2);
507
530
await tester.idle (); // let nextFrameFuture complete
531
+ expect (mockCodec.disposed, false );
508
532
await tester.pump (const Duration (milliseconds: 200 )); // emit 2nd frame.
533
+ expect (mockCodec.disposed, true );
509
534
mockCodec.completeNextFrame (frame1);
510
535
// allow another frame to complete (but we shouldn't be asking for it as
511
536
// this animation should not repeat.
@@ -562,7 +587,9 @@ void main() {
562
587
expect (mockCodec.numFramesAsked, 3 );
563
588
564
589
handle.dispose ();
590
+ expect (mockCodec.disposed, false );
565
591
imageStream.removeListener (listener);
592
+ expect (mockCodec.disposed, true );
566
593
imageCache.clear ();
567
594
});
568
595
@@ -619,7 +646,9 @@ void main() {
619
646
expect (emittedImages2[0 ].image.isCloneOf (frame1.image), true );
620
647
expect (emittedImages2[1 ].image.isCloneOf (frame2.image), true );
621
648
649
+ expect (mockCodec.disposed, false );
622
650
imageStream.removeListener (listener2);
651
+ expect (mockCodec.disposed, true );
623
652
});
624
653
625
654
testWidgets ('timer is canceled when listeners are removed' , (WidgetTester tester) async {
@@ -653,7 +682,9 @@ void main() {
653
682
await tester.idle (); // let nextFrameFuture complete
654
683
await tester.pump ();
655
684
685
+ expect (mockCodec.disposed, false );
656
686
imageStream.removeListener (ImageStreamListener (listener));
687
+ expect (mockCodec.disposed, true );
657
688
// The test framework will fail this if there are pending timers at this
658
689
// point.
659
690
});
@@ -699,7 +730,9 @@ void main() {
699
730
expect (mockCodec.numFramesAsked, 3 );
700
731
timeDilation = 1.0 ; // restore time dilation, or it will affect other tests
701
732
733
+ expect (mockCodec.disposed, false );
702
734
imageStream.removeListener (listener);
735
+ expect (mockCodec.disposed, true );
703
736
});
704
737
705
738
testWidgets ('error handlers can intercept errors' , (WidgetTester tester) async {
@@ -734,6 +767,7 @@ void main() {
734
767
// No exception is passed up.
735
768
expect (tester.takeException (), isNull);
736
769
expect (capturedException, 'frame completion error' );
770
+ expect (mockCodec.disposed, false );
737
771
});
738
772
739
773
testWidgets (
@@ -772,6 +806,7 @@ void main() {
772
806
await tester.pump (); // first animation frame shows on first app frame.
773
807
774
808
await tester.pump (const Duration (milliseconds: 200 )); // emit 2nd frame.
809
+ expect (mockCodec.disposed, false );
775
810
},
776
811
);
777
812
@@ -918,7 +953,9 @@ void main() {
918
953
919
954
expect (onImageCount, 1 );
920
955
956
+ expect (mockCodec.disposed, false );
921
957
handle.dispose ();
958
+ expect (mockCodec.disposed, true );
922
959
});
923
960
924
961
test ('MultiFrameImageStreamCompleter - one frame image should only be decoded once' , () async {
0 commit comments