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.
4
5#include <cstdlib>
6
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 "testing/gtest/include/gtest/gtest.h"
13
14namespace media {
15
16class SeekableBufferTest : public testing::Test {
17 public:
18  SeekableBufferTest() : buffer_(kBufferSize, kBufferSize) {
19  }
20
21 protected:
22  static const int kDataSize = 409600;
23  static const int kBufferSize = 4096;
24  static const int kWriteSize = 512;
25
26  virtual void SetUp() {
27    // Note: We use srand() and rand() rather than base::RandXXX() to improve
28    // unit test performance.  We don't need good random numbers, just
29    // something that generates "mixed data."
30    const unsigned int kKnownSeed = 0x98765432;
31    srand(kKnownSeed);
32
33    // Create random test data samples.
34    for (int i = 0; i < kDataSize; i++)
35      data_[i] = static_cast<char>(rand());
36  }
37
38  int GetRandomInt(int maximum) {
39    return rand() % (maximum + 1);
40  }
41
42  SeekableBuffer buffer_;
43  uint8 data_[kDataSize];
44  uint8 write_buffer_[kDataSize];
45};
46
47TEST_F(SeekableBufferTest, RandomReadWrite) {
48  int write_position = 0;
49  int read_position = 0;
50  while (read_position < kDataSize) {
51    // Write a random amount of data.
52    int write_size = GetRandomInt(kBufferSize);
53    write_size = std::min(write_size, kDataSize - write_position);
54    bool should_append = buffer_.Append(data_ + write_position, write_size);
55    write_position += write_size;
56    EXPECT_GE(write_position, read_position);
57    EXPECT_EQ(write_position - read_position, buffer_.forward_bytes());
58    EXPECT_EQ(should_append, buffer_.forward_bytes() < kBufferSize)
59        << "Incorrect buffer full reported";
60
61    // Peek a random amount of data.
62    int copy_size = GetRandomInt(kBufferSize);
63    int bytes_copied = buffer_.Peek(write_buffer_, copy_size);
64    EXPECT_GE(copy_size, bytes_copied);
65    EXPECT_EQ(0, memcmp(write_buffer_, data_ + read_position, bytes_copied));
66
67    // Read a random amount of data.
68    int read_size = GetRandomInt(kBufferSize);
69    int bytes_read = buffer_.Read(write_buffer_, read_size);
70    EXPECT_GE(read_size, bytes_read);
71    EXPECT_EQ(0, memcmp(write_buffer_, data_ + read_position, bytes_read));
72    read_position += bytes_read;
73    EXPECT_GE(write_position, read_position);
74    EXPECT_EQ(write_position - read_position, buffer_.forward_bytes());
75  }
76}
77
78TEST_F(SeekableBufferTest, ReadWriteSeek) {
79  const int kReadSize = kWriteSize / 4;
80
81  for (int i = 0; i < 10; ++i) {
82    // Write until buffer is full.
83    for (int j = 0; j < kBufferSize; j += kWriteSize) {
84      bool should_append = buffer_.Append(data_ + j, kWriteSize);
85      EXPECT_EQ(j < kBufferSize - kWriteSize, should_append)
86          << "Incorrect buffer full reported";
87      EXPECT_EQ(j + kWriteSize, buffer_.forward_bytes());
88    }
89
90    // Simulate a read and seek pattern. Each loop reads 4 times, each time
91    // reading a quarter of |kWriteSize|.
92    int read_position = 0;
93    int forward_bytes = kBufferSize;
94    for (int j = 0; j < kBufferSize; j += kWriteSize) {
95      // Read.
96      EXPECT_EQ(kReadSize, buffer_.Read(write_buffer_, kReadSize));
97      forward_bytes -= kReadSize;
98      EXPECT_EQ(forward_bytes, buffer_.forward_bytes());
99      EXPECT_EQ(0, memcmp(write_buffer_, data_ + read_position, kReadSize));
100      read_position += kReadSize;
101
102      // Seek forward.
103      EXPECT_TRUE(buffer_.Seek(2 * kReadSize));
104      forward_bytes -= 2 * kReadSize;
105      read_position += 2 * kReadSize;
106      EXPECT_EQ(forward_bytes, buffer_.forward_bytes());
107
108      // Copy.
109      EXPECT_EQ(kReadSize, buffer_.Peek(write_buffer_, kReadSize));
110      EXPECT_EQ(forward_bytes, buffer_.forward_bytes());
111      EXPECT_EQ(0, memcmp(write_buffer_, data_ + read_position, kReadSize));
112
113      // Read.
114      EXPECT_EQ(kReadSize, buffer_.Read(write_buffer_, kReadSize));
115      forward_bytes -= kReadSize;
116      EXPECT_EQ(forward_bytes, buffer_.forward_bytes());
117      EXPECT_EQ(0, memcmp(write_buffer_, data_ + read_position, kReadSize));
118      read_position += kReadSize;
119
120      // Seek backward.
121      EXPECT_TRUE(buffer_.Seek(-3 * static_cast<int32>(kReadSize)));
122      forward_bytes += 3 * kReadSize;
123      read_position -= 3 * kReadSize;
124      EXPECT_EQ(forward_bytes, buffer_.forward_bytes());
125
126      // Copy.
127      EXPECT_EQ(kReadSize, buffer_.Peek(write_buffer_, kReadSize));
128      EXPECT_EQ(forward_bytes, buffer_.forward_bytes());
129      EXPECT_EQ(0, memcmp(write_buffer_, data_ + read_position, kReadSize));
130
131      // Read.
132      EXPECT_EQ(kReadSize, buffer_.Read(write_buffer_, kReadSize));
133      forward_bytes -= kReadSize;
134      EXPECT_EQ(forward_bytes, buffer_.forward_bytes());
135      EXPECT_EQ(0, memcmp(write_buffer_, data_ + read_position, kReadSize));
136      read_position += kReadSize;
137
138      // Copy.
139      EXPECT_EQ(kReadSize, buffer_.Peek(write_buffer_, kReadSize));
140      EXPECT_EQ(forward_bytes, buffer_.forward_bytes());
141      EXPECT_EQ(0, memcmp(write_buffer_, data_ + read_position, kReadSize));
142
143      // Read.
144      EXPECT_EQ(kReadSize, buffer_.Read(write_buffer_, kReadSize));
145      forward_bytes -= kReadSize;
146      EXPECT_EQ(forward_bytes, buffer_.forward_bytes());
147      EXPECT_EQ(0, memcmp(write_buffer_, data_ + read_position, kReadSize));
148      read_position += kReadSize;
149
150      // Seek forward.
151      EXPECT_TRUE(buffer_.Seek(kReadSize));
152      forward_bytes -= kReadSize;
153      read_position += kReadSize;
154      EXPECT_EQ(forward_bytes, buffer_.forward_bytes());
155    }
156  }
157}
158
159TEST_F(SeekableBufferTest, BufferFull) {
160  const int kMaxWriteSize = 2 * kBufferSize;
161
162  // Write and expect the buffer to be not full.
163  for (int i = 0; i < kBufferSize - kWriteSize; i += kWriteSize) {
164    EXPECT_TRUE(buffer_.Append(data_ + i, kWriteSize));
165    EXPECT_EQ(i + kWriteSize, buffer_.forward_bytes());
166  }
167
168  // Write until we have kMaxWriteSize bytes in the buffer. Buffer is full in
169  // these writes.
170  for (int i = buffer_.forward_bytes(); i < kMaxWriteSize; i += kWriteSize) {
171    EXPECT_FALSE(buffer_.Append(data_ + i, kWriteSize));
172    EXPECT_EQ(i + kWriteSize, buffer_.forward_bytes());
173  }
174
175  // Read until the buffer is empty.
176  int read_position = 0;
177  while (buffer_.forward_bytes()) {
178    // Read a random amount of data.
179    int read_size = GetRandomInt(kBufferSize);
180    int forward_bytes = buffer_.forward_bytes();
181    int bytes_read = buffer_.Read(write_buffer_, read_size);
182    EXPECT_EQ(0, memcmp(write_buffer_, data_ + read_position, bytes_read));
183    if (read_size > forward_bytes)
184      EXPECT_EQ(forward_bytes, bytes_read);
185    else
186      EXPECT_EQ(read_size, bytes_read);
187    read_position += bytes_read;
188    EXPECT_GE(kMaxWriteSize, read_position);
189    EXPECT_EQ(kMaxWriteSize - read_position, buffer_.forward_bytes());
190  }
191
192  // Expects we have no bytes left.
193  EXPECT_EQ(0, buffer_.forward_bytes());
194  EXPECT_EQ(0, buffer_.Read(write_buffer_, 1));
195}
196
197TEST_F(SeekableBufferTest, SeekBackward) {
198  EXPECT_EQ(0, buffer_.forward_bytes());
199  EXPECT_EQ(0, buffer_.backward_bytes());
200  EXPECT_FALSE(buffer_.Seek(1));
201  EXPECT_FALSE(buffer_.Seek(-1));
202
203  const int kReadSize = 256;
204
205  // Write into buffer until it's full.
206  for (int i = 0; i < kBufferSize; i += kWriteSize) {
207    // Write a random amount of data.
208    buffer_.Append(data_ + i, kWriteSize);
209  }
210
211  // Read until buffer is empty.
212  for (int i = 0; i < kBufferSize; i += kReadSize) {
213    EXPECT_EQ(kReadSize, buffer_.Read(write_buffer_, kReadSize));
214    EXPECT_EQ(0, memcmp(write_buffer_, data_ + i, kReadSize));
215  }
216
217  // Seek backward.
218  EXPECT_TRUE(buffer_.Seek(-static_cast<int32>(kBufferSize)));
219  EXPECT_FALSE(buffer_.Seek(-1));
220
221  // Read again.
222  for (int i = 0; i < kBufferSize; i += kReadSize) {
223    EXPECT_EQ(kReadSize, buffer_.Read(write_buffer_, kReadSize));
224    EXPECT_EQ(0, memcmp(write_buffer_, data_ + i, kReadSize));
225  }
226}
227
228TEST_F(SeekableBufferTest, GetCurrentChunk) {
229  const int kSeekSize = kWriteSize / 3;
230
231  scoped_refptr<DataBuffer> buffer = DataBuffer::CopyFrom(data_, kWriteSize);
232
233  const uint8* data;
234  int size;
235  EXPECT_FALSE(buffer_.GetCurrentChunk(&data, &size));
236
237  buffer_.Append(buffer.get());
238  EXPECT_TRUE(buffer_.GetCurrentChunk(&data, &size));
239  EXPECT_EQ(data, buffer->data());
240  EXPECT_EQ(size, buffer->data_size());
241
242  buffer_.Seek(kSeekSize);
243  EXPECT_TRUE(buffer_.GetCurrentChunk(&data, &size));
244  EXPECT_EQ(data, buffer->data() + kSeekSize);
245  EXPECT_EQ(size, buffer->data_size() - kSeekSize);
246}
247
248TEST_F(SeekableBufferTest, SeekForward) {
249  int write_position = 0;
250  int read_position = 0;
251  while (read_position < kDataSize) {
252    for (int i = 0; i < 10 && write_position < kDataSize; ++i) {
253      // Write a random amount of data.
254      int write_size = GetRandomInt(kBufferSize);
255      write_size = std::min(write_size, kDataSize - write_position);
256
257      bool should_append = buffer_.Append(data_ + write_position, write_size);
258      write_position += write_size;
259      EXPECT_GE(write_position, read_position);
260      EXPECT_EQ(write_position - read_position, buffer_.forward_bytes());
261      EXPECT_EQ(should_append, buffer_.forward_bytes() < kBufferSize)
262          << "Incorrect buffer full status reported";
263    }
264
265    // Read a random amount of data.
266    int seek_size = GetRandomInt(kBufferSize);
267    if (buffer_.Seek(seek_size))
268      read_position += seek_size;
269    EXPECT_GE(write_position, read_position);
270    EXPECT_EQ(write_position - read_position, buffer_.forward_bytes());
271
272    // Read a random amount of data.
273    int read_size = GetRandomInt(kBufferSize);
274    int bytes_read = buffer_.Read(write_buffer_, read_size);
275    EXPECT_GE(read_size, bytes_read);
276    EXPECT_EQ(0, memcmp(write_buffer_, data_ + read_position, bytes_read));
277    read_position += bytes_read;
278    EXPECT_GE(write_position, read_position);
279    EXPECT_EQ(write_position - read_position, buffer_.forward_bytes());
280  }
281}
282
283TEST_F(SeekableBufferTest, AllMethods) {
284  EXPECT_EQ(0, buffer_.Read(write_buffer_, 0));
285  EXPECT_EQ(0, buffer_.Read(write_buffer_, 1));
286  EXPECT_TRUE(buffer_.Seek(0));
287  EXPECT_FALSE(buffer_.Seek(-1));
288  EXPECT_FALSE(buffer_.Seek(1));
289  EXPECT_EQ(0, buffer_.forward_bytes());
290  EXPECT_EQ(0, buffer_.backward_bytes());
291}
292
293TEST_F(SeekableBufferTest, GetTime) {
294  const int64 kNoTS = kNoTimestamp().ToInternalValue();
295  const struct {
296    int64 first_time_useconds;
297    int64 duration_useconds;
298    int consume_bytes;
299    int64 expected_time;
300  } tests[] = {
301    { kNoTS, 1000000, 0, kNoTS },
302    { kNoTS, 4000000, 0, kNoTS },
303    { kNoTS, 8000000, 0, kNoTS },
304    { kNoTS, 1000000, kWriteSize / 2, kNoTS },
305    { kNoTS, 4000000, kWriteSize / 2, kNoTS },
306    { kNoTS, 8000000, kWriteSize / 2, kNoTS },
307    { kNoTS, 1000000, kWriteSize, kNoTS },
308    { kNoTS, 4000000, kWriteSize, kNoTS },
309    { kNoTS, 8000000, kWriteSize, kNoTS },
310    { 0, 1000000, 0, 0 },
311    { 0, 4000000, 0, 0 },
312    { 0, 8000000, 0, 0 },
313    { 0, 1000000, kWriteSize / 2, 500000 },
314    { 0, 4000000, kWriteSize / 2, 2000000 },
315    { 0, 8000000, kWriteSize / 2, 4000000 },
316    { 0, 1000000, kWriteSize, 1000000 },
317    { 0, 4000000, kWriteSize, 4000000 },
318    { 0, 8000000, kWriteSize, 8000000 },
319    { 5, 1000000, 0, 5 },
320    { 5, 4000000, 0, 5 },
321    { 5, 8000000, 0, 5 },
322    { 5, 1000000, kWriteSize / 2, 500005 },
323    { 5, 4000000, kWriteSize / 2, 2000005 },
324    { 5, 8000000, kWriteSize / 2, 4000005 },
325    { 5, 1000000, kWriteSize, 1000005 },
326    { 5, 4000000, kWriteSize, 4000005 },
327    { 5, 8000000, kWriteSize, 8000005 },
328  };
329
330  // current_time() must initially return kNoTimestamp().
331  EXPECT_EQ(kNoTimestamp().ToInternalValue(),
332            buffer_.current_time().ToInternalValue());
333
334  scoped_refptr<DataBuffer> buffer = DataBuffer::CopyFrom(data_, kWriteSize);
335
336  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
337    buffer->set_timestamp(base::TimeDelta::FromMicroseconds(
338        tests[i].first_time_useconds));
339    buffer->set_duration(base::TimeDelta::FromMicroseconds(
340        tests[i].duration_useconds));
341    buffer_.Append(buffer.get());
342    EXPECT_TRUE(buffer_.Seek(tests[i].consume_bytes));
343
344    int64 actual = buffer_.current_time().ToInternalValue();
345
346    EXPECT_EQ(tests[i].expected_time, actual) << "With test = { start:"
347        << tests[i].first_time_useconds << ", duration:"
348        << tests[i].duration_useconds << ", consumed:"
349        << tests[i].consume_bytes << " }\n";
350
351    buffer_.Clear();
352  }
353}
354
355}  // namespace media
356