Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/image/test/gtest/TestAnimationFrameBuffer.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2
 * This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#include "gtest/gtest.h"
7
8
#include "mozilla/Move.h"
9
#include "AnimationFrameBuffer.h"
10
11
using namespace mozilla;
12
using namespace mozilla::image;
13
14
static RawAccessFrameRef
15
CreateEmptyFrame()
16
0
{
17
0
  RefPtr<imgFrame> frame = new imgFrame();
18
0
  nsresult rv = frame->InitForAnimator(nsIntSize(1, 1), SurfaceFormat::B8G8R8A8);
19
0
  EXPECT_TRUE(NS_SUCCEEDED(rv));
20
0
  RawAccessFrameRef frameRef = frame->RawAccessRef();
21
0
  frame->Finish();
22
0
  return frameRef;
23
0
}
24
25
static bool
26
Fill(AnimationFrameBuffer& buffer, size_t aLength)
27
0
{
28
0
  bool keepDecoding = false;
29
0
  for (size_t i = 0; i < aLength; ++i) {
30
0
    RawAccessFrameRef frame = CreateEmptyFrame();
31
0
    keepDecoding = buffer.Insert(frame->RawAccessRef());
32
0
  }
33
0
  return keepDecoding;
34
0
}
35
36
static void
37
CheckFrames(const AnimationFrameBuffer& buffer, size_t aStart, size_t aEnd, bool aExpected)
38
0
{
39
0
  for (size_t i = aStart; i < aEnd; ++i) {
40
0
    EXPECT_EQ(aExpected, !!buffer.Frames()[i]);
41
0
  }
42
0
}
43
44
static void
45
CheckRemoved(const AnimationFrameBuffer& buffer, size_t aStart, size_t aEnd)
46
0
{
47
0
  CheckFrames(buffer, aStart, aEnd, false);
48
0
}
49
50
static void
51
CheckRetained(const AnimationFrameBuffer& buffer, size_t aStart, size_t aEnd)
52
0
{
53
0
  CheckFrames(buffer, aStart, aEnd, true);
54
0
}
55
56
class ImageAnimationFrameBuffer : public ::testing::Test
57
{
58
public:
59
  ImageAnimationFrameBuffer()
60
0
  { }
61
62
private:
63
  AutoInitializeImageLib mInit;
64
};
65
66
TEST_F(ImageAnimationFrameBuffer, InitialState)
67
0
{
68
0
  const size_t kThreshold = 800;
69
0
  const size_t kBatch = 100;
70
0
  AnimationFrameBuffer buffer;
71
0
  buffer.Initialize(kThreshold, kBatch, 0);
72
0
73
0
  EXPECT_EQ(kThreshold, buffer.Threshold());
74
0
  EXPECT_EQ(kBatch, buffer.Batch());
75
0
  EXPECT_EQ(size_t(0), buffer.Displayed());
76
0
  EXPECT_EQ(kBatch * 2, buffer.PendingDecode());
77
0
  EXPECT_EQ(size_t(0), buffer.PendingAdvance());
78
0
  EXPECT_FALSE(buffer.MayDiscard());
79
0
  EXPECT_FALSE(buffer.SizeKnown());
80
0
  EXPECT_TRUE(buffer.Frames().IsEmpty());
81
0
}
82
83
TEST_F(ImageAnimationFrameBuffer, ThresholdTooSmall)
84
0
{
85
0
  const size_t kThreshold = 0;
86
0
  const size_t kBatch = 10;
87
0
  AnimationFrameBuffer buffer;
88
0
  buffer.Initialize(kThreshold, kBatch, 0);
89
0
90
0
  EXPECT_EQ(kBatch * 2 + 1, buffer.Threshold());
91
0
  EXPECT_EQ(kBatch, buffer.Batch());
92
0
  EXPECT_EQ(kBatch * 2, buffer.PendingDecode());
93
0
  EXPECT_EQ(size_t(0), buffer.PendingAdvance());
94
0
}
95
96
TEST_F(ImageAnimationFrameBuffer, BatchTooSmall)
97
0
{
98
0
  const size_t kThreshold = 10;
99
0
  const size_t kBatch = 0;
100
0
  AnimationFrameBuffer buffer;
101
0
  buffer.Initialize(kThreshold, kBatch, 0);
102
0
103
0
  EXPECT_EQ(kThreshold, buffer.Threshold());
104
0
  EXPECT_EQ(size_t(1), buffer.Batch());
105
0
  EXPECT_EQ(size_t(2), buffer.PendingDecode());
106
0
  EXPECT_EQ(size_t(0), buffer.PendingAdvance());
107
0
}
108
109
TEST_F(ImageAnimationFrameBuffer, BatchTooBig)
110
0
{
111
0
  const size_t kThreshold = 50;
112
0
  const size_t kBatch = SIZE_MAX;
113
0
  AnimationFrameBuffer buffer;
114
0
  buffer.Initialize(kThreshold, kBatch, 0);
115
0
116
0
  // The rounding is important here (e.g. SIZE_MAX/4 * 2 != SIZE_MAX/2).
117
0
  EXPECT_EQ(SIZE_MAX/4, buffer.Batch());
118
0
  EXPECT_EQ(buffer.Batch() * 2 + 1, buffer.Threshold());
119
0
  EXPECT_EQ(buffer.Batch() * 2, buffer.PendingDecode());
120
0
  EXPECT_EQ(size_t(0), buffer.PendingAdvance());
121
0
}
122
123
TEST_F(ImageAnimationFrameBuffer, FinishUnderBatchAndThreshold)
124
0
{
125
0
  const size_t kThreshold = 30;
126
0
  const size_t kBatch = 10;
127
0
  AnimationFrameBuffer buffer;
128
0
  buffer.Initialize(kThreshold, kBatch, 0);
129
0
  const auto& frames = buffer.Frames();
130
0
131
0
  EXPECT_EQ(kBatch * 2, buffer.PendingDecode());
132
0
133
0
  RawAccessFrameRef firstFrame;
134
0
  for (size_t i = 0; i < 5; ++i) {
135
0
    RawAccessFrameRef frame = CreateEmptyFrame();
136
0
    bool keepDecoding = buffer.Insert(frame->RawAccessRef());
137
0
    EXPECT_TRUE(keepDecoding);
138
0
    EXPECT_FALSE(buffer.SizeKnown());
139
0
140
0
    if (i == 4) {
141
0
      EXPECT_EQ(size_t(15), buffer.PendingDecode());
142
0
      keepDecoding = buffer.MarkComplete();
143
0
      EXPECT_FALSE(keepDecoding);
144
0
      EXPECT_TRUE(buffer.SizeKnown());
145
0
      EXPECT_EQ(size_t(0), buffer.PendingDecode());
146
0
      EXPECT_FALSE(buffer.HasRedecodeError());
147
0
    }
148
0
149
0
    EXPECT_FALSE(buffer.MayDiscard());
150
0
151
0
    imgFrame* gotFrame = buffer.Get(i);
152
0
    EXPECT_EQ(frame.get(), gotFrame);
153
0
    ASSERT_EQ(i + 1, frames.Length());
154
0
    EXPECT_EQ(frame.get(), frames[i].get());
155
0
156
0
    if (i == 0) {
157
0
      firstFrame = std::move(frame);
158
0
      EXPECT_EQ(size_t(0), buffer.Displayed());
159
0
    } else {
160
0
      EXPECT_EQ(i - 1, buffer.Displayed());
161
0
      bool restartDecoder = buffer.AdvanceTo(i);
162
0
      EXPECT_FALSE(restartDecoder);
163
0
      EXPECT_EQ(i, buffer.Displayed());
164
0
    }
165
0
166
0
    gotFrame = buffer.Get(0);
167
0
    EXPECT_EQ(firstFrame.get(), gotFrame);
168
0
  }
169
0
170
0
  // Loop again over the animation and make sure it is still all there.
171
0
  for (size_t i = 0; i < frames.Length(); ++i) {
172
0
    EXPECT_TRUE(buffer.Get(i) != nullptr);
173
0
174
0
    bool restartDecoder = buffer.AdvanceTo(i);
175
0
    EXPECT_FALSE(restartDecoder);
176
0
  }
177
0
}
178
179
TEST_F(ImageAnimationFrameBuffer, FinishMultipleBatchesUnderThreshold)
180
0
{
181
0
  const size_t kThreshold = 30;
182
0
  const size_t kBatch = 2;
183
0
  AnimationFrameBuffer buffer;
184
0
  buffer.Initialize(kThreshold, kBatch, 0);
185
0
  const auto& frames = buffer.Frames();
186
0
187
0
  EXPECT_EQ(kBatch * 2, buffer.PendingDecode());
188
0
189
0
  // Add frames until it tells us to stop.
190
0
  bool keepDecoding;
191
0
  do {
192
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
193
0
    EXPECT_FALSE(buffer.SizeKnown());
194
0
    EXPECT_FALSE(buffer.MayDiscard());
195
0
  } while (keepDecoding);
196
0
197
0
  EXPECT_EQ(size_t(0), buffer.PendingDecode());
198
0
  EXPECT_EQ(size_t(4), frames.Length());
199
0
200
0
  // Progress through the animation until it lets us decode again.
201
0
  bool restartDecoder = false;
202
0
  size_t i = 0;
203
0
  do {
204
0
    EXPECT_TRUE(buffer.Get(i) != nullptr);
205
0
    if (i > 0) {
206
0
      restartDecoder = buffer.AdvanceTo(i);
207
0
    }
208
0
    ++i;
209
0
  } while (!restartDecoder);
210
0
211
0
  EXPECT_EQ(size_t(2), buffer.PendingDecode());
212
0
  EXPECT_EQ(size_t(2), buffer.Displayed());
213
0
214
0
  // Add the last frame.
215
0
  keepDecoding = buffer.Insert(CreateEmptyFrame());
216
0
  EXPECT_TRUE(keepDecoding);
217
0
  keepDecoding = buffer.MarkComplete();
218
0
  EXPECT_FALSE(keepDecoding);
219
0
  EXPECT_TRUE(buffer.SizeKnown());
220
0
  EXPECT_EQ(size_t(0), buffer.PendingDecode());
221
0
  EXPECT_EQ(size_t(5), frames.Length());
222
0
  EXPECT_FALSE(buffer.HasRedecodeError());
223
0
224
0
  // Finish progressing through the animation.
225
0
  for ( ; i < frames.Length(); ++i) {
226
0
    EXPECT_TRUE(buffer.Get(i) != nullptr);
227
0
    restartDecoder = buffer.AdvanceTo(i);
228
0
    EXPECT_FALSE(restartDecoder);
229
0
  }
230
0
231
0
  // Loop again over the animation and make sure it is still all there.
232
0
  for (i = 0; i < frames.Length(); ++i) {
233
0
    EXPECT_TRUE(buffer.Get(i) != nullptr);
234
0
    restartDecoder = buffer.AdvanceTo(i);
235
0
    EXPECT_FALSE(restartDecoder);
236
0
  }
237
0
238
0
  // Loop to the third frame and then reset the animation.
239
0
  for (i = 0; i < 3; ++i) {
240
0
    EXPECT_TRUE(buffer.Get(i) != nullptr);
241
0
    restartDecoder = buffer.AdvanceTo(i);
242
0
    EXPECT_FALSE(restartDecoder);
243
0
  }
244
0
245
0
  // Since we are below the threshold, we can reset the get index only.
246
0
  // Nothing else should have changed.
247
0
  restartDecoder = buffer.Reset();
248
0
  EXPECT_FALSE(restartDecoder);
249
0
  CheckRetained(buffer, 0, 5);
250
0
  EXPECT_EQ(size_t(0), buffer.PendingDecode());
251
0
  EXPECT_EQ(size_t(0), buffer.PendingAdvance());
252
0
  EXPECT_EQ(size_t(0), buffer.Displayed());
253
0
}
254
255
TEST_F(ImageAnimationFrameBuffer, MayDiscard)
256
0
{
257
0
  const size_t kThreshold = 8;
258
0
  const size_t kBatch = 3;
259
0
  AnimationFrameBuffer buffer;
260
0
  buffer.Initialize(kThreshold, kBatch, 0);
261
0
  const auto& frames = buffer.Frames();
262
0
263
0
  EXPECT_EQ(kBatch * 2, buffer.PendingDecode());
264
0
265
0
  // Add frames until it tells us to stop.
266
0
  bool keepDecoding;
267
0
  do {
268
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
269
0
    EXPECT_FALSE(buffer.SizeKnown());
270
0
    EXPECT_FALSE(buffer.MayDiscard());
271
0
  } while (keepDecoding);
272
0
273
0
  EXPECT_EQ(size_t(0), buffer.PendingDecode());
274
0
  EXPECT_EQ(size_t(6), frames.Length());
275
0
276
0
  // Progress through the animation until it lets us decode again.
277
0
  bool restartDecoder = false;
278
0
  size_t i = 0;
279
0
  do {
280
0
    EXPECT_TRUE(buffer.Get(i) != nullptr);
281
0
    if (i > 0) {
282
0
      restartDecoder = buffer.AdvanceTo(i);
283
0
    }
284
0
    ++i;
285
0
  } while (!restartDecoder);
286
0
287
0
  EXPECT_EQ(size_t(3), buffer.PendingDecode());
288
0
  EXPECT_EQ(size_t(3), buffer.Displayed());
289
0
290
0
  // Add more frames.
291
0
  do {
292
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
293
0
    EXPECT_FALSE(buffer.SizeKnown());
294
0
  } while (keepDecoding);
295
0
296
0
  EXPECT_TRUE(buffer.MayDiscard());
297
0
  EXPECT_EQ(size_t(0), buffer.PendingDecode());
298
0
  EXPECT_EQ(size_t(9), frames.Length());
299
0
300
0
  // It should have be able to remove two frames given we have advanced to the
301
0
  // fourth frame.
302
0
  CheckRetained(buffer, 0, 1);
303
0
  CheckRemoved(buffer, 1, 3);
304
0
  CheckRetained(buffer, 3, 9);
305
0
306
0
  // Progress through the animation so more. Make sure it removes frames as we
307
0
  // go along.
308
0
  do {
309
0
    EXPECT_TRUE(buffer.Get(i) != nullptr);
310
0
    restartDecoder = buffer.AdvanceTo(i);
311
0
    EXPECT_FALSE(frames[i - 1]);
312
0
    EXPECT_TRUE(frames[i]);
313
0
    i++;
314
0
  } while (!restartDecoder);
315
0
316
0
  EXPECT_EQ(size_t(3), buffer.PendingDecode());
317
0
  EXPECT_EQ(size_t(6), buffer.Displayed());
318
0
319
0
  // Add the last frame. It should still let us add more frames, but the next
320
0
  // frame will restart at the beginning.
321
0
  keepDecoding = buffer.Insert(CreateEmptyFrame());
322
0
  EXPECT_TRUE(keepDecoding);
323
0
  keepDecoding = buffer.MarkComplete();
324
0
  EXPECT_TRUE(keepDecoding);
325
0
  EXPECT_TRUE(buffer.SizeKnown());
326
0
  EXPECT_EQ(size_t(2), buffer.PendingDecode());
327
0
  EXPECT_EQ(size_t(10), frames.Length());
328
0
  EXPECT_FALSE(buffer.HasRedecodeError());
329
0
330
0
  // Use remaining pending room. It shouldn't add new frames, only replace.
331
0
  do {
332
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
333
0
  } while (keepDecoding);
334
0
335
0
  EXPECT_EQ(size_t(0), buffer.PendingDecode());
336
0
  EXPECT_EQ(size_t(10), frames.Length());
337
0
338
0
  // Advance as far as we can. This should require us to loop the animation to
339
0
  // reach a missing frame.
340
0
  do {
341
0
    if (i == frames.Length()) {
342
0
      i = 0;
343
0
    }
344
0
345
0
    if (!buffer.Get(i)) {
346
0
      break;
347
0
    }
348
0
349
0
    restartDecoder = buffer.AdvanceTo(i);
350
0
    ++i;
351
0
  } while (true);
352
0
353
0
  EXPECT_EQ(size_t(3), buffer.PendingDecode());
354
0
  EXPECT_EQ(size_t(2), i);
355
0
  EXPECT_EQ(size_t(1), buffer.Displayed());
356
0
357
0
  // Decode some more.
358
0
  keepDecoding = Fill(buffer, buffer.PendingDecode());
359
0
  EXPECT_FALSE(keepDecoding);
360
0
  EXPECT_EQ(size_t(0), buffer.PendingDecode());
361
0
362
0
  // Can we retry advancing again?
363
0
  EXPECT_TRUE(buffer.Get(i) != nullptr);
364
0
  restartDecoder = buffer.AdvanceTo(i);
365
0
  EXPECT_EQ(size_t(2), buffer.Displayed());
366
0
  EXPECT_FALSE(frames[i - 1]);
367
0
  EXPECT_TRUE(frames[i]);
368
0
369
0
  // Since we are above the threshold, we must reset everything.
370
0
  restartDecoder = buffer.Reset();
371
0
  EXPECT_FALSE(restartDecoder);
372
0
  CheckRetained(buffer, 0, 1);
373
0
  CheckRemoved(buffer, 1, frames.Length());
374
0
  EXPECT_EQ(kBatch * 2, buffer.PendingDecode());
375
0
  EXPECT_EQ(size_t(0), buffer.PendingAdvance());
376
0
  EXPECT_EQ(size_t(0), buffer.Displayed());
377
0
}
378
379
TEST_F(ImageAnimationFrameBuffer, ResetIncompleteAboveThreshold)
380
0
{
381
0
  const size_t kThreshold = 5;
382
0
  const size_t kBatch = 2;
383
0
  AnimationFrameBuffer buffer;
384
0
  buffer.Initialize(kThreshold, kBatch, 0);
385
0
  const auto& frames = buffer.Frames();
386
0
387
0
  // Add frames until we exceed the threshold.
388
0
  bool keepDecoding;
389
0
  bool restartDecoder;
390
0
  size_t i = 0;
391
0
  do {
392
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
393
0
    EXPECT_TRUE(keepDecoding);
394
0
    if (i > 0) {
395
0
      restartDecoder = buffer.AdvanceTo(i);
396
0
      EXPECT_FALSE(restartDecoder);
397
0
    }
398
0
    ++i;
399
0
  } while (!buffer.MayDiscard());
400
0
401
0
  // Should have threshold + 1 frames, and still not complete.
402
0
  EXPECT_EQ(size_t(6), frames.Length());
403
0
  EXPECT_FALSE(buffer.SizeKnown());
404
0
405
0
  // Restart the animation, we still had pending frames to decode since we
406
0
  // advanced in lockstep, so it should not ask us to restart the decoder.
407
0
  restartDecoder = buffer.Reset();
408
0
  EXPECT_FALSE(restartDecoder);
409
0
  CheckRetained(buffer, 0, 1);
410
0
  CheckRemoved(buffer, 1, frames.Length());
411
0
  EXPECT_EQ(kBatch * 2, buffer.PendingDecode());
412
0
  EXPECT_EQ(size_t(0), buffer.PendingAdvance());
413
0
  EXPECT_EQ(size_t(0), buffer.Displayed());
414
0
415
0
  // Adding new frames should not grow the insertion array, but instead
416
0
  // should reuse the space already allocated. Given that we are able to
417
0
  // discard frames once we cross the threshold, we should confirm that
418
0
  // we only do so if we have advanced beyond them.
419
0
  size_t oldFramesLength = frames.Length();
420
0
  size_t advanceUpTo = frames.Length() - kBatch;
421
0
  for (i = 0; i < oldFramesLength; ++i) {
422
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
423
0
    EXPECT_TRUE(keepDecoding);
424
0
    EXPECT_TRUE(frames[i]);
425
0
    EXPECT_EQ(oldFramesLength, frames.Length());
426
0
    if (i > 0) {
427
0
      // If we stop advancing, we should still retain the previous frames.
428
0
      EXPECT_TRUE(frames[i-1]);
429
0
      if (i <= advanceUpTo) {
430
0
        restartDecoder = buffer.AdvanceTo(i);
431
0
        EXPECT_FALSE(restartDecoder);
432
0
      }
433
0
    }
434
0
  }
435
0
436
0
  // Add one more frame. It should have grown the array this time.
437
0
  keepDecoding = buffer.Insert(CreateEmptyFrame());
438
0
  EXPECT_TRUE(keepDecoding);
439
0
  ASSERT_EQ(i + 1, frames.Length());
440
0
  EXPECT_TRUE(frames[i]);
441
0
}
442
443
TEST_F(ImageAnimationFrameBuffer, StartAfterBeginning)
444
0
{
445
0
  const size_t kThreshold = 30;
446
0
  const size_t kBatch = 2;
447
0
  const size_t kStartFrame = 7;
448
0
  AnimationFrameBuffer buffer;
449
0
  buffer.Initialize(kThreshold, kBatch, kStartFrame);
450
0
451
0
  EXPECT_EQ(kStartFrame, buffer.PendingAdvance());
452
0
453
0
  // Add frames until it tells us to stop. It should be later than before,
454
0
  // because it auto-advances until its displayed frame is kStartFrame.
455
0
  bool keepDecoding;
456
0
  size_t i = 0;
457
0
  do {
458
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
459
0
    EXPECT_FALSE(buffer.SizeKnown());
460
0
    EXPECT_FALSE(buffer.MayDiscard());
461
0
462
0
    if (i <= kStartFrame) {
463
0
      EXPECT_EQ(i, buffer.Displayed());
464
0
      EXPECT_EQ(kStartFrame - i, buffer.PendingAdvance());
465
0
    } else {
466
0
      EXPECT_EQ(kStartFrame, buffer.Displayed());
467
0
      EXPECT_EQ(size_t(0), buffer.PendingAdvance());
468
0
    }
469
0
470
0
    i++;
471
0
  } while (keepDecoding);
472
0
473
0
  EXPECT_EQ(size_t(0), buffer.PendingDecode());
474
0
  EXPECT_EQ(size_t(0), buffer.PendingAdvance());
475
0
  EXPECT_EQ(size_t(10), buffer.Frames().Length());
476
0
}
477
478
TEST_F(ImageAnimationFrameBuffer, StartAfterBeginningAndReset)
479
0
{
480
0
  const size_t kThreshold = 30;
481
0
  const size_t kBatch = 2;
482
0
  const size_t kStartFrame = 7;
483
0
  AnimationFrameBuffer buffer;
484
0
  buffer.Initialize(kThreshold, kBatch, kStartFrame);
485
0
486
0
  EXPECT_EQ(kStartFrame, buffer.PendingAdvance());
487
0
488
0
  // Add frames until it tells us to stop. It should be later than before,
489
0
  // because it auto-advances until its displayed frame is kStartFrame.
490
0
  for (size_t i = 0; i < 5; ++i) {
491
0
    bool keepDecoding = buffer.Insert(CreateEmptyFrame());
492
0
    EXPECT_TRUE(keepDecoding);
493
0
    EXPECT_FALSE(buffer.SizeKnown());
494
0
    EXPECT_FALSE(buffer.MayDiscard());
495
0
    EXPECT_EQ(i, buffer.Displayed());
496
0
    EXPECT_EQ(kStartFrame - i, buffer.PendingAdvance());
497
0
  }
498
0
499
0
  // When we reset the animation, it goes back to the beginning. That means
500
0
  // we can forget about what we were told to advance to at the start. While
501
0
  // we have plenty of frames in our buffer, we still need one more because
502
0
  // in the real scenario, the decoder thread is still running and it is easier
503
0
  // to let it insert its last frame than to coordinate quitting earlier.
504
0
  buffer.Reset();
505
0
  EXPECT_EQ(size_t(0), buffer.Displayed());
506
0
  EXPECT_EQ(size_t(1), buffer.PendingDecode());
507
0
  EXPECT_EQ(size_t(0), buffer.PendingAdvance());
508
0
}
509
510
TEST_F(ImageAnimationFrameBuffer, RedecodeMoreFrames)
511
0
{
512
0
  const size_t kThreshold = 5;
513
0
  const size_t kBatch = 2;
514
0
  AnimationFrameBuffer buffer;
515
0
  buffer.Initialize(kThreshold, kBatch, 0);
516
0
  const auto& frames = buffer.Frames();
517
0
518
0
  // Add frames until we exceed the threshold.
519
0
  bool keepDecoding;
520
0
  bool restartDecoder;
521
0
  size_t i = 0;
522
0
  do {
523
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
524
0
    EXPECT_TRUE(keepDecoding);
525
0
    if (i > 0) {
526
0
      restartDecoder = buffer.AdvanceTo(i);
527
0
      EXPECT_FALSE(restartDecoder);
528
0
    }
529
0
    ++i;
530
0
  } while (!buffer.MayDiscard());
531
0
532
0
  // Should have threshold + 1 frames, and still not complete.
533
0
  EXPECT_EQ(size_t(6), frames.Length());
534
0
  EXPECT_FALSE(buffer.SizeKnown());
535
0
536
0
  // Now we lock in at 6 frames.
537
0
  keepDecoding = buffer.MarkComplete();
538
0
  EXPECT_TRUE(keepDecoding);
539
0
  EXPECT_TRUE(buffer.SizeKnown());
540
0
  EXPECT_FALSE(buffer.HasRedecodeError());
541
0
542
0
  // Reinsert 6 frames first.
543
0
  i = 0;
544
0
  do {
545
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
546
0
    EXPECT_TRUE(keepDecoding);
547
0
    restartDecoder = buffer.AdvanceTo(i);
548
0
    EXPECT_FALSE(restartDecoder);
549
0
    ++i;
550
0
  } while (i < 6);
551
0
552
0
  // We should now encounter an error and shutdown further decodes.
553
0
  keepDecoding = buffer.Insert(CreateEmptyFrame());
554
0
  EXPECT_FALSE(keepDecoding);
555
0
  EXPECT_EQ(size_t(0), buffer.PendingDecode());
556
0
  EXPECT_TRUE(buffer.HasRedecodeError());
557
0
}
558
559
TEST_F(ImageAnimationFrameBuffer, RedecodeFewerFrames)
560
0
{
561
0
  const size_t kThreshold = 5;
562
0
  const size_t kBatch = 2;
563
0
  AnimationFrameBuffer buffer;
564
0
  buffer.Initialize(kThreshold, kBatch, 0);
565
0
  const auto& frames = buffer.Frames();
566
0
567
0
  // Add frames until we exceed the threshold.
568
0
  bool keepDecoding;
569
0
  bool restartDecoder;
570
0
  size_t i = 0;
571
0
  do {
572
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
573
0
    EXPECT_TRUE(keepDecoding);
574
0
    if (i > 0) {
575
0
      restartDecoder = buffer.AdvanceTo(i);
576
0
      EXPECT_FALSE(restartDecoder);
577
0
    }
578
0
    ++i;
579
0
  } while (!buffer.MayDiscard());
580
0
581
0
  // Should have threshold + 1 frames, and still not complete.
582
0
  EXPECT_EQ(size_t(6), frames.Length());
583
0
  EXPECT_FALSE(buffer.SizeKnown());
584
0
585
0
  // Now we lock in at 6 frames.
586
0
  keepDecoding = buffer.MarkComplete();
587
0
  EXPECT_TRUE(keepDecoding);
588
0
  EXPECT_TRUE(buffer.SizeKnown());
589
0
  EXPECT_FALSE(buffer.HasRedecodeError());
590
0
591
0
  // Reinsert 5 frames before marking complete.
592
0
  i = 0;
593
0
  do {
594
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
595
0
    EXPECT_TRUE(keepDecoding);
596
0
    restartDecoder = buffer.AdvanceTo(i);
597
0
    EXPECT_FALSE(restartDecoder);
598
0
    ++i;
599
0
  } while (i < 5);
600
0
601
0
  // We should now encounter an error and shutdown further decodes.
602
0
  keepDecoding = buffer.MarkComplete();
603
0
  EXPECT_FALSE(keepDecoding);
604
0
  EXPECT_EQ(size_t(0), buffer.PendingDecode());
605
0
  EXPECT_TRUE(buffer.HasRedecodeError());
606
0
}
607
608
TEST_F(ImageAnimationFrameBuffer, RedecodeFewerFramesAndBehindAdvancing)
609
0
{
610
0
  const size_t kThreshold = 5;
611
0
  const size_t kBatch = 2;
612
0
  AnimationFrameBuffer buffer;
613
0
  buffer.Initialize(kThreshold, kBatch, 0);
614
0
  const auto& frames = buffer.Frames();
615
0
616
0
  // Add frames until we exceed the threshold.
617
0
  bool keepDecoding;
618
0
  bool restartDecoder;
619
0
  size_t i = 0;
620
0
  do {
621
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
622
0
    EXPECT_TRUE(keepDecoding);
623
0
    if (i > 0) {
624
0
      restartDecoder = buffer.AdvanceTo(i);
625
0
      EXPECT_FALSE(restartDecoder);
626
0
    }
627
0
    ++i;
628
0
  } while (!buffer.MayDiscard());
629
0
630
0
  // Should have threshold + 1 frames, and still not complete.
631
0
  EXPECT_EQ(size_t(6), frames.Length());
632
0
  EXPECT_FALSE(buffer.SizeKnown());
633
0
634
0
  // Now we lock in at 6 frames.
635
0
  keepDecoding = buffer.MarkComplete();
636
0
  EXPECT_TRUE(keepDecoding);
637
0
  EXPECT_TRUE(buffer.SizeKnown());
638
0
  EXPECT_FALSE(buffer.HasRedecodeError());
639
0
640
0
  // Reinsert frames without advancing until we exhaust our pending space. This
641
0
  // should be less than the current buffer length by definition.
642
0
  i = 0;
643
0
  do {
644
0
    keepDecoding = buffer.Insert(CreateEmptyFrame());
645
0
    ++i;
646
0
  } while (keepDecoding);
647
0
648
0
  EXPECT_EQ(size_t(2), i);
649
0
650
0
  // We should now encounter an error and shutdown further decodes.
651
0
  keepDecoding = buffer.MarkComplete();
652
0
  EXPECT_FALSE(keepDecoding);
653
0
  EXPECT_EQ(size_t(0), buffer.PendingDecode());
654
0
  EXPECT_TRUE(buffer.HasRedecodeError());
655
0
656
0
  // We should however be able to continue advancing to the last decoded frame
657
0
  // without it requesting the decoder to restart.
658
0
  i = 0;
659
0
  do {
660
0
    restartDecoder = buffer.AdvanceTo(i);
661
0
    EXPECT_FALSE(restartDecoder);
662
0
    ++i;
663
0
  } while (i < 2);
664
0
}
665