1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/time/time.h"
10 #include "media/base/data_buffer.h"
11 #include "media/base/seekable_buffer.h"
12 #include "media/base/timestamp_constants.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 class SeekableBufferTest
: public testing::Test
{
19 SeekableBufferTest() : buffer_(kBufferSize
, kBufferSize
) {
23 static const int kDataSize
= 409600;
24 static const int kBufferSize
= 4096;
25 static const int kWriteSize
= 512;
27 void SetUp() override
{
28 // Note: We use srand() and rand() rather than base::RandXXX() to improve
29 // unit test performance. We don't need good random numbers, just
30 // something that generates "mixed data."
31 const unsigned int kKnownSeed
= 0x98765432;
34 // Create random test data samples.
35 for (int i
= 0; i
< kDataSize
; i
++)
36 data_
[i
] = static_cast<char>(rand());
39 int GetRandomInt(int maximum
) {
40 return rand() % (maximum
+ 1);
43 SeekableBuffer buffer_
;
44 uint8 data_
[kDataSize
];
45 uint8 write_buffer_
[kDataSize
];
48 TEST_F(SeekableBufferTest
, RandomReadWrite
) {
49 int write_position
= 0;
50 int read_position
= 0;
51 while (read_position
< kDataSize
) {
52 // Write a random amount of data.
53 int write_size
= GetRandomInt(kBufferSize
);
54 write_size
= std::min(write_size
, kDataSize
- write_position
);
55 bool should_append
= buffer_
.Append(data_
+ write_position
, write_size
);
56 write_position
+= write_size
;
57 EXPECT_GE(write_position
, read_position
);
58 EXPECT_EQ(write_position
- read_position
, buffer_
.forward_bytes());
59 EXPECT_EQ(should_append
, buffer_
.forward_bytes() < kBufferSize
)
60 << "Incorrect buffer full reported";
62 // Peek a random amount of data.
63 int copy_size
= GetRandomInt(kBufferSize
);
64 int bytes_copied
= buffer_
.Peek(write_buffer_
, copy_size
);
65 EXPECT_GE(copy_size
, bytes_copied
);
66 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ read_position
, bytes_copied
));
68 // Read a random amount of data.
69 int read_size
= GetRandomInt(kBufferSize
);
70 int bytes_read
= buffer_
.Read(write_buffer_
, read_size
);
71 EXPECT_GE(read_size
, bytes_read
);
72 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ read_position
, bytes_read
));
73 read_position
+= bytes_read
;
74 EXPECT_GE(write_position
, read_position
);
75 EXPECT_EQ(write_position
- read_position
, buffer_
.forward_bytes());
79 TEST_F(SeekableBufferTest
, ReadWriteSeek
) {
80 const int kReadSize
= kWriteSize
/ 4;
82 for (int i
= 0; i
< 10; ++i
) {
83 // Write until buffer is full.
84 for (int j
= 0; j
< kBufferSize
; j
+= kWriteSize
) {
85 bool should_append
= buffer_
.Append(data_
+ j
, kWriteSize
);
86 EXPECT_EQ(j
< kBufferSize
- kWriteSize
, should_append
)
87 << "Incorrect buffer full reported";
88 EXPECT_EQ(j
+ kWriteSize
, buffer_
.forward_bytes());
91 // Simulate a read and seek pattern. Each loop reads 4 times, each time
92 // reading a quarter of |kWriteSize|.
93 int read_position
= 0;
94 int forward_bytes
= kBufferSize
;
95 for (int j
= 0; j
< kBufferSize
; j
+= kWriteSize
) {
97 EXPECT_EQ(kReadSize
, buffer_
.Read(write_buffer_
, kReadSize
));
98 forward_bytes
-= kReadSize
;
99 EXPECT_EQ(forward_bytes
, buffer_
.forward_bytes());
100 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ read_position
, kReadSize
));
101 read_position
+= kReadSize
;
104 EXPECT_TRUE(buffer_
.Seek(2 * kReadSize
));
105 forward_bytes
-= 2 * kReadSize
;
106 read_position
+= 2 * kReadSize
;
107 EXPECT_EQ(forward_bytes
, buffer_
.forward_bytes());
110 EXPECT_EQ(kReadSize
, buffer_
.Peek(write_buffer_
, kReadSize
));
111 EXPECT_EQ(forward_bytes
, buffer_
.forward_bytes());
112 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ read_position
, kReadSize
));
115 EXPECT_EQ(kReadSize
, buffer_
.Read(write_buffer_
, kReadSize
));
116 forward_bytes
-= kReadSize
;
117 EXPECT_EQ(forward_bytes
, buffer_
.forward_bytes());
118 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ read_position
, kReadSize
));
119 read_position
+= kReadSize
;
122 EXPECT_TRUE(buffer_
.Seek(-3 * static_cast<int32
>(kReadSize
)));
123 forward_bytes
+= 3 * kReadSize
;
124 read_position
-= 3 * kReadSize
;
125 EXPECT_EQ(forward_bytes
, buffer_
.forward_bytes());
128 EXPECT_EQ(kReadSize
, buffer_
.Peek(write_buffer_
, kReadSize
));
129 EXPECT_EQ(forward_bytes
, buffer_
.forward_bytes());
130 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ read_position
, kReadSize
));
133 EXPECT_EQ(kReadSize
, buffer_
.Read(write_buffer_
, kReadSize
));
134 forward_bytes
-= kReadSize
;
135 EXPECT_EQ(forward_bytes
, buffer_
.forward_bytes());
136 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ read_position
, kReadSize
));
137 read_position
+= kReadSize
;
140 EXPECT_EQ(kReadSize
, buffer_
.Peek(write_buffer_
, kReadSize
));
141 EXPECT_EQ(forward_bytes
, buffer_
.forward_bytes());
142 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ read_position
, kReadSize
));
145 EXPECT_EQ(kReadSize
, buffer_
.Read(write_buffer_
, kReadSize
));
146 forward_bytes
-= kReadSize
;
147 EXPECT_EQ(forward_bytes
, buffer_
.forward_bytes());
148 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ read_position
, kReadSize
));
149 read_position
+= kReadSize
;
152 EXPECT_TRUE(buffer_
.Seek(kReadSize
));
153 forward_bytes
-= kReadSize
;
154 read_position
+= kReadSize
;
155 EXPECT_EQ(forward_bytes
, buffer_
.forward_bytes());
160 TEST_F(SeekableBufferTest
, BufferFull
) {
161 const int kMaxWriteSize
= 2 * kBufferSize
;
163 // Write and expect the buffer to be not full.
164 for (int i
= 0; i
< kBufferSize
- kWriteSize
; i
+= kWriteSize
) {
165 EXPECT_TRUE(buffer_
.Append(data_
+ i
, kWriteSize
));
166 EXPECT_EQ(i
+ kWriteSize
, buffer_
.forward_bytes());
169 // Write until we have kMaxWriteSize bytes in the buffer. Buffer is full in
171 for (int i
= buffer_
.forward_bytes(); i
< kMaxWriteSize
; i
+= kWriteSize
) {
172 EXPECT_FALSE(buffer_
.Append(data_
+ i
, kWriteSize
));
173 EXPECT_EQ(i
+ kWriteSize
, buffer_
.forward_bytes());
176 // Read until the buffer is empty.
177 int read_position
= 0;
178 while (buffer_
.forward_bytes()) {
179 // Read a random amount of data.
180 int read_size
= GetRandomInt(kBufferSize
);
181 int forward_bytes
= buffer_
.forward_bytes();
182 int bytes_read
= buffer_
.Read(write_buffer_
, read_size
);
183 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ read_position
, bytes_read
));
184 if (read_size
> forward_bytes
)
185 EXPECT_EQ(forward_bytes
, bytes_read
);
187 EXPECT_EQ(read_size
, bytes_read
);
188 read_position
+= bytes_read
;
189 EXPECT_GE(kMaxWriteSize
, read_position
);
190 EXPECT_EQ(kMaxWriteSize
- read_position
, buffer_
.forward_bytes());
193 // Expects we have no bytes left.
194 EXPECT_EQ(0, buffer_
.forward_bytes());
195 EXPECT_EQ(0, buffer_
.Read(write_buffer_
, 1));
198 TEST_F(SeekableBufferTest
, SeekBackward
) {
199 EXPECT_EQ(0, buffer_
.forward_bytes());
200 EXPECT_EQ(0, buffer_
.backward_bytes());
201 EXPECT_FALSE(buffer_
.Seek(1));
202 EXPECT_FALSE(buffer_
.Seek(-1));
204 const int kReadSize
= 256;
206 // Write into buffer until it's full.
207 for (int i
= 0; i
< kBufferSize
; i
+= kWriteSize
) {
208 // Write a random amount of data.
209 buffer_
.Append(data_
+ i
, kWriteSize
);
212 // Read until buffer is empty.
213 for (int i
= 0; i
< kBufferSize
; i
+= kReadSize
) {
214 EXPECT_EQ(kReadSize
, buffer_
.Read(write_buffer_
, kReadSize
));
215 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ i
, kReadSize
));
219 EXPECT_TRUE(buffer_
.Seek(-static_cast<int32
>(kBufferSize
)));
220 EXPECT_FALSE(buffer_
.Seek(-1));
223 for (int i
= 0; i
< kBufferSize
; i
+= kReadSize
) {
224 EXPECT_EQ(kReadSize
, buffer_
.Read(write_buffer_
, kReadSize
));
225 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ i
, kReadSize
));
229 TEST_F(SeekableBufferTest
, GetCurrentChunk
) {
230 const int kSeekSize
= kWriteSize
/ 3;
232 scoped_refptr
<DataBuffer
> buffer
= DataBuffer::CopyFrom(data_
, kWriteSize
);
236 EXPECT_FALSE(buffer_
.GetCurrentChunk(&data
, &size
));
238 buffer_
.Append(buffer
.get());
239 EXPECT_TRUE(buffer_
.GetCurrentChunk(&data
, &size
));
240 EXPECT_EQ(data
, buffer
->data());
241 EXPECT_EQ(size
, buffer
->data_size());
243 buffer_
.Seek(kSeekSize
);
244 EXPECT_TRUE(buffer_
.GetCurrentChunk(&data
, &size
));
245 EXPECT_EQ(data
, buffer
->data() + kSeekSize
);
246 EXPECT_EQ(size
, buffer
->data_size() - kSeekSize
);
249 TEST_F(SeekableBufferTest
, SeekForward
) {
250 int write_position
= 0;
251 int read_position
= 0;
252 while (read_position
< kDataSize
) {
253 for (int i
= 0; i
< 10 && write_position
< kDataSize
; ++i
) {
254 // Write a random amount of data.
255 int write_size
= GetRandomInt(kBufferSize
);
256 write_size
= std::min(write_size
, kDataSize
- write_position
);
258 bool should_append
= buffer_
.Append(data_
+ write_position
, write_size
);
259 write_position
+= write_size
;
260 EXPECT_GE(write_position
, read_position
);
261 EXPECT_EQ(write_position
- read_position
, buffer_
.forward_bytes());
262 EXPECT_EQ(should_append
, buffer_
.forward_bytes() < kBufferSize
)
263 << "Incorrect buffer full status reported";
266 // Read a random amount of data.
267 int seek_size
= GetRandomInt(kBufferSize
);
268 if (buffer_
.Seek(seek_size
))
269 read_position
+= seek_size
;
270 EXPECT_GE(write_position
, read_position
);
271 EXPECT_EQ(write_position
- read_position
, buffer_
.forward_bytes());
273 // Read a random amount of data.
274 int read_size
= GetRandomInt(kBufferSize
);
275 int bytes_read
= buffer_
.Read(write_buffer_
, read_size
);
276 EXPECT_GE(read_size
, bytes_read
);
277 EXPECT_EQ(0, memcmp(write_buffer_
, data_
+ read_position
, bytes_read
));
278 read_position
+= bytes_read
;
279 EXPECT_GE(write_position
, read_position
);
280 EXPECT_EQ(write_position
- read_position
, buffer_
.forward_bytes());
284 TEST_F(SeekableBufferTest
, AllMethods
) {
285 EXPECT_EQ(0, buffer_
.Read(write_buffer_
, 0));
286 EXPECT_EQ(0, buffer_
.Read(write_buffer_
, 1));
287 EXPECT_TRUE(buffer_
.Seek(0));
288 EXPECT_FALSE(buffer_
.Seek(-1));
289 EXPECT_FALSE(buffer_
.Seek(1));
290 EXPECT_EQ(0, buffer_
.forward_bytes());
291 EXPECT_EQ(0, buffer_
.backward_bytes());
294 TEST_F(SeekableBufferTest
, GetTime
) {
295 const int64 kNoTS
= kNoTimestamp().ToInternalValue();
297 int64 first_time_useconds
;
298 int64 duration_useconds
;
302 { kNoTS
, 1000000, 0, kNoTS
},
303 { kNoTS
, 4000000, 0, kNoTS
},
304 { kNoTS
, 8000000, 0, kNoTS
},
305 { kNoTS
, 1000000, kWriteSize
/ 2, kNoTS
},
306 { kNoTS
, 4000000, kWriteSize
/ 2, kNoTS
},
307 { kNoTS
, 8000000, kWriteSize
/ 2, kNoTS
},
308 { kNoTS
, 1000000, kWriteSize
, kNoTS
},
309 { kNoTS
, 4000000, kWriteSize
, kNoTS
},
310 { kNoTS
, 8000000, kWriteSize
, kNoTS
},
311 { 0, 1000000, 0, 0 },
312 { 0, 4000000, 0, 0 },
313 { 0, 8000000, 0, 0 },
314 { 0, 1000000, kWriteSize
/ 2, 500000 },
315 { 0, 4000000, kWriteSize
/ 2, 2000000 },
316 { 0, 8000000, kWriteSize
/ 2, 4000000 },
317 { 0, 1000000, kWriteSize
, 1000000 },
318 { 0, 4000000, kWriteSize
, 4000000 },
319 { 0, 8000000, kWriteSize
, 8000000 },
320 { 5, 1000000, 0, 5 },
321 { 5, 4000000, 0, 5 },
322 { 5, 8000000, 0, 5 },
323 { 5, 1000000, kWriteSize
/ 2, 500005 },
324 { 5, 4000000, kWriteSize
/ 2, 2000005 },
325 { 5, 8000000, kWriteSize
/ 2, 4000005 },
326 { 5, 1000000, kWriteSize
, 1000005 },
327 { 5, 4000000, kWriteSize
, 4000005 },
328 { 5, 8000000, kWriteSize
, 8000005 },
331 // current_time() must initially return kNoTimestamp().
332 EXPECT_EQ(kNoTimestamp().ToInternalValue(),
333 buffer_
.current_time().ToInternalValue());
335 scoped_refptr
<DataBuffer
> buffer
= DataBuffer::CopyFrom(data_
, kWriteSize
);
337 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
338 buffer
->set_timestamp(base::TimeDelta::FromMicroseconds(
339 tests
[i
].first_time_useconds
));
340 buffer
->set_duration(base::TimeDelta::FromMicroseconds(
341 tests
[i
].duration_useconds
));
342 buffer_
.Append(buffer
.get());
343 EXPECT_TRUE(buffer_
.Seek(tests
[i
].consume_bytes
));
345 int64 actual
= buffer_
.current_time().ToInternalValue();
347 EXPECT_EQ(tests
[i
].expected_time
, actual
) << "With test = { start:"
348 << tests
[i
].first_time_useconds
<< ", duration:"
349 << tests
[i
].duration_useconds
<< ", consumed:"
350 << tests
[i
].consume_bytes
<< " }\n";