1/*
2 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/base/fileutils.h"
12#include "webrtc/base/gunit.h"
13#include "webrtc/base/pathutils.h"
14#include "webrtc/base/stream.h"
15
16namespace rtc {
17
18///////////////////////////////////////////////////////////////////////////////
19// TestStream
20///////////////////////////////////////////////////////////////////////////////
21
22class TestStream : public StreamInterface {
23 public:
24  TestStream() : pos_(0) { }
25
26  virtual StreamState GetState() const { return SS_OPEN; }
27  virtual StreamResult Read(void* buffer, size_t buffer_len,
28                            size_t* read, int* error) {
29    unsigned char* uc_buffer = static_cast<unsigned char*>(buffer);
30    for (size_t i = 0; i < buffer_len; ++i) {
31      uc_buffer[i] = static_cast<unsigned char>(pos_++);
32    }
33    if (read)
34      *read = buffer_len;
35    return SR_SUCCESS;
36  }
37  virtual StreamResult Write(const void* data, size_t data_len,
38                             size_t* written, int* error) {
39    if (error)
40      *error = -1;
41    return SR_ERROR;
42  }
43  virtual void Close() { }
44  virtual bool SetPosition(size_t position) {
45    pos_ = position;
46    return true;
47  }
48  virtual bool GetPosition(size_t* position) const {
49    if (position) *position = pos_;
50    return true;
51  }
52  virtual bool GetSize(size_t* size) const {
53    return false;
54  }
55  virtual bool GetAvailable(size_t* size) const {
56    return false;
57  }
58
59 private:
60  size_t pos_;
61};
62
63bool VerifyTestBuffer(unsigned char* buffer, size_t len,
64                      unsigned char value) {
65  bool passed = true;
66  for (size_t i = 0; i < len; ++i) {
67    if (buffer[i] != value++) {
68      passed = false;
69      break;
70    }
71  }
72  // Ensure that we don't pass again without re-writing
73  memset(buffer, 0, len);
74  return passed;
75}
76
77void SeekTest(StreamInterface* stream, const unsigned char value) {
78  size_t bytes;
79  unsigned char buffer[13] = { 0 };
80  const size_t kBufSize = sizeof(buffer);
81
82  EXPECT_EQ(stream->Read(buffer, kBufSize, &bytes, NULL), SR_SUCCESS);
83  EXPECT_EQ(bytes, kBufSize);
84  EXPECT_TRUE(VerifyTestBuffer(buffer, kBufSize, value));
85  EXPECT_TRUE(stream->GetPosition(&bytes));
86  EXPECT_EQ(13U, bytes);
87
88  EXPECT_TRUE(stream->SetPosition(7));
89
90  EXPECT_EQ(stream->Read(buffer, kBufSize, &bytes, NULL), SR_SUCCESS);
91  EXPECT_EQ(bytes, kBufSize);
92  EXPECT_TRUE(VerifyTestBuffer(buffer, kBufSize, value + 7));
93  EXPECT_TRUE(stream->GetPosition(&bytes));
94  EXPECT_EQ(20U, bytes);
95}
96
97TEST(FifoBufferTest, TestAll) {
98  const size_t kSize = 16;
99  const char in[kSize * 2 + 1] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
100  char out[kSize * 2];
101  void* p;
102  const void* q;
103  size_t bytes;
104  FifoBuffer buf(kSize);
105  StreamInterface* stream = &buf;
106
107  // Test assumptions about base state
108  EXPECT_EQ(SS_OPEN, stream->GetState());
109  EXPECT_EQ(SR_BLOCK, stream->Read(out, kSize, &bytes, NULL));
110  EXPECT_TRUE(NULL != stream->GetReadData(&bytes));
111  EXPECT_EQ((size_t)0, bytes);
112  stream->ConsumeReadData(0);
113  EXPECT_TRUE(NULL != stream->GetWriteBuffer(&bytes));
114  EXPECT_EQ(kSize, bytes);
115  stream->ConsumeWriteBuffer(0);
116
117  // Try a full write
118  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize, &bytes, NULL));
119  EXPECT_EQ(kSize, bytes);
120
121  // Try a write that should block
122  EXPECT_EQ(SR_BLOCK, stream->Write(in, kSize, &bytes, NULL));
123
124  // Try a full read
125  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize, &bytes, NULL));
126  EXPECT_EQ(kSize, bytes);
127  EXPECT_EQ(0, memcmp(in, out, kSize));
128
129  // Try a read that should block
130  EXPECT_EQ(SR_BLOCK, stream->Read(out, kSize, &bytes, NULL));
131
132  // Try a too-big write
133  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize * 2, &bytes, NULL));
134  EXPECT_EQ(bytes, kSize);
135
136  // Try a too-big read
137  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize * 2, &bytes, NULL));
138  EXPECT_EQ(kSize, bytes);
139  EXPECT_EQ(0, memcmp(in, out, kSize));
140
141  // Try some small writes and reads
142  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize / 2, &bytes, NULL));
143  EXPECT_EQ(kSize / 2, bytes);
144  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, NULL));
145  EXPECT_EQ(kSize / 2, bytes);
146  EXPECT_EQ(0, memcmp(in, out, kSize / 2));
147  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize / 2, &bytes, NULL));
148  EXPECT_EQ(kSize / 2, bytes);
149  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize / 2, &bytes, NULL));
150  EXPECT_EQ(kSize / 2, bytes);
151  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, NULL));
152  EXPECT_EQ(kSize / 2, bytes);
153  EXPECT_EQ(0, memcmp(in, out, kSize / 2));
154  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, NULL));
155  EXPECT_EQ(kSize / 2, bytes);
156  EXPECT_EQ(0, memcmp(in, out, kSize / 2));
157
158  // Try wraparound reads and writes in the following pattern
159  // WWWWWWWWWWWW.... 0123456789AB....
160  // RRRRRRRRXXXX.... ........89AB....
161  // WWWW....XXXXWWWW 4567....89AB0123
162  // XXXX....RRRRXXXX 4567........0123
163  // XXXXWWWWWWWWXXXX 4567012345670123
164  // RRRRXXXXXXXXRRRR ....01234567....
165  // ....RRRRRRRR.... ................
166  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize * 3 / 4, &bytes, NULL));
167  EXPECT_EQ(kSize * 3 / 4, bytes);
168  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, NULL));
169  EXPECT_EQ(kSize / 2, bytes);
170  EXPECT_EQ(0, memcmp(in, out, kSize / 2));
171  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize / 2, &bytes, NULL));
172  EXPECT_EQ(kSize / 2, bytes);
173  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 4, &bytes, NULL));
174  EXPECT_EQ(kSize / 4 , bytes);
175  EXPECT_EQ(0, memcmp(in + kSize / 2, out, kSize / 4));
176  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize / 2, &bytes, NULL));
177  EXPECT_EQ(kSize / 2, bytes);
178  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, NULL));
179  EXPECT_EQ(kSize / 2 , bytes);
180  EXPECT_EQ(0, memcmp(in, out, kSize / 2));
181  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, NULL));
182  EXPECT_EQ(kSize / 2 , bytes);
183  EXPECT_EQ(0, memcmp(in, out, kSize / 2));
184
185  // Use GetWriteBuffer to reset the read_position for the next tests
186  stream->GetWriteBuffer(&bytes);
187  stream->ConsumeWriteBuffer(0);
188
189  // Try using GetReadData to do a full read
190  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize, &bytes, NULL));
191  q = stream->GetReadData(&bytes);
192  EXPECT_TRUE(NULL != q);
193  EXPECT_EQ(kSize, bytes);
194  EXPECT_EQ(0, memcmp(q, in, kSize));
195  stream->ConsumeReadData(kSize);
196  EXPECT_EQ(SR_BLOCK, stream->Read(out, kSize, &bytes, NULL));
197
198  // Try using GetReadData to do some small reads
199  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize, &bytes, NULL));
200  q = stream->GetReadData(&bytes);
201  EXPECT_TRUE(NULL != q);
202  EXPECT_EQ(kSize, bytes);
203  EXPECT_EQ(0, memcmp(q, in, kSize / 2));
204  stream->ConsumeReadData(kSize / 2);
205  q = stream->GetReadData(&bytes);
206  EXPECT_TRUE(NULL != q);
207  EXPECT_EQ(kSize / 2, bytes);
208  EXPECT_EQ(0, memcmp(q, in + kSize / 2, kSize / 2));
209  stream->ConsumeReadData(kSize / 2);
210  EXPECT_EQ(SR_BLOCK, stream->Read(out, kSize, &bytes, NULL));
211
212  // Try using GetReadData in a wraparound case
213  // WWWWWWWWWWWWWWWW 0123456789ABCDEF
214  // RRRRRRRRRRRRXXXX ............CDEF
215  // WWWWWWWW....XXXX 01234567....CDEF
216  // ............RRRR 01234567........
217  // RRRRRRRR........ ................
218  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize, &bytes, NULL));
219  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize * 3 / 4, &bytes, NULL));
220  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize / 2, &bytes, NULL));
221  q = stream->GetReadData(&bytes);
222  EXPECT_TRUE(NULL != q);
223  EXPECT_EQ(kSize / 4, bytes);
224  EXPECT_EQ(0, memcmp(q, in + kSize * 3 / 4, kSize / 4));
225  stream->ConsumeReadData(kSize / 4);
226  q = stream->GetReadData(&bytes);
227  EXPECT_TRUE(NULL != q);
228  EXPECT_EQ(kSize / 2, bytes);
229  EXPECT_EQ(0, memcmp(q, in, kSize / 2));
230  stream->ConsumeReadData(kSize / 2);
231
232  // Use GetWriteBuffer to reset the read_position for the next tests
233  stream->GetWriteBuffer(&bytes);
234  stream->ConsumeWriteBuffer(0);
235
236  // Try using GetWriteBuffer to do a full write
237  p = stream->GetWriteBuffer(&bytes);
238  EXPECT_TRUE(NULL != p);
239  EXPECT_EQ(kSize, bytes);
240  memcpy(p, in, kSize);
241  stream->ConsumeWriteBuffer(kSize);
242  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize, &bytes, NULL));
243  EXPECT_EQ(kSize, bytes);
244  EXPECT_EQ(0, memcmp(in, out, kSize));
245
246  // Try using GetWriteBuffer to do some small writes
247  p = stream->GetWriteBuffer(&bytes);
248  EXPECT_TRUE(NULL != p);
249  EXPECT_EQ(kSize, bytes);
250  memcpy(p, in, kSize / 2);
251  stream->ConsumeWriteBuffer(kSize / 2);
252  p = stream->GetWriteBuffer(&bytes);
253  EXPECT_TRUE(NULL != p);
254  EXPECT_EQ(kSize / 2, bytes);
255  memcpy(p, in + kSize / 2, kSize / 2);
256  stream->ConsumeWriteBuffer(kSize / 2);
257  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize, &bytes, NULL));
258  EXPECT_EQ(kSize, bytes);
259  EXPECT_EQ(0, memcmp(in, out, kSize));
260
261  // Try using GetWriteBuffer in a wraparound case
262  // WWWWWWWWWWWW.... 0123456789AB....
263  // RRRRRRRRXXXX.... ........89AB....
264  // ........XXXXWWWW ........89AB0123
265  // WWWW....XXXXXXXX 4567....89AB0123
266  // RRRR....RRRRRRRR ................
267  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize * 3 / 4, &bytes, NULL));
268  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, NULL));
269  p = stream->GetWriteBuffer(&bytes);
270  EXPECT_TRUE(NULL != p);
271  EXPECT_EQ(kSize / 4, bytes);
272  memcpy(p, in, kSize / 4);
273  stream->ConsumeWriteBuffer(kSize / 4);
274  p = stream->GetWriteBuffer(&bytes);
275  EXPECT_TRUE(NULL != p);
276  EXPECT_EQ(kSize / 2, bytes);
277  memcpy(p, in + kSize / 4, kSize / 4);
278  stream->ConsumeWriteBuffer(kSize / 4);
279  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize * 3 / 4, &bytes, NULL));
280  EXPECT_EQ(kSize * 3 / 4, bytes);
281  EXPECT_EQ(0, memcmp(in + kSize / 2, out, kSize / 4));
282  EXPECT_EQ(0, memcmp(in, out + kSize / 4, kSize / 4));
283
284  // Check that the stream is now empty
285  EXPECT_EQ(SR_BLOCK, stream->Read(out, kSize, &bytes, NULL));
286
287  // Try growing the buffer
288  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize, &bytes, NULL));
289  EXPECT_EQ(kSize, bytes);
290  EXPECT_TRUE(buf.SetCapacity(kSize * 2));
291  EXPECT_EQ(SR_SUCCESS, stream->Write(in + kSize, kSize, &bytes, NULL));
292  EXPECT_EQ(kSize, bytes);
293  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize * 2, &bytes, NULL));
294  EXPECT_EQ(kSize * 2, bytes);
295  EXPECT_EQ(0, memcmp(in, out, kSize * 2));
296
297  // Try shrinking the buffer
298  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize, &bytes, NULL));
299  EXPECT_EQ(kSize, bytes);
300  EXPECT_TRUE(buf.SetCapacity(kSize));
301  EXPECT_EQ(SR_BLOCK, stream->Write(in, kSize, &bytes, NULL));
302  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize, &bytes, NULL));
303  EXPECT_EQ(kSize, bytes);
304  EXPECT_EQ(0, memcmp(in, out, kSize));
305
306  // Write to the stream, close it, read the remaining bytes
307  EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize / 2, &bytes, NULL));
308  stream->Close();
309  EXPECT_EQ(SS_CLOSED, stream->GetState());
310  EXPECT_EQ(SR_EOS, stream->Write(in, kSize / 2, &bytes, NULL));
311  EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, NULL));
312  EXPECT_EQ(0, memcmp(in, out, kSize / 2));
313  EXPECT_EQ(SR_EOS, stream->Read(out, kSize / 2, &bytes, NULL));
314}
315
316TEST(FifoBufferTest, FullBufferCheck) {
317  FifoBuffer buff(10);
318  buff.ConsumeWriteBuffer(10);
319
320  size_t free;
321  EXPECT_TRUE(buff.GetWriteBuffer(&free) != NULL);
322  EXPECT_EQ(0U, free);
323}
324
325TEST(FifoBufferTest, WriteOffsetAndReadOffset) {
326  const size_t kSize = 16;
327  const char in[kSize * 2 + 1] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
328  char out[kSize * 2];
329  FifoBuffer buf(kSize);
330
331  // Write 14 bytes.
332  EXPECT_EQ(SR_SUCCESS, buf.Write(in, 14, NULL, NULL));
333
334  // Make sure data is in |buf|.
335  size_t buffered;
336  EXPECT_TRUE(buf.GetBuffered(&buffered));
337  EXPECT_EQ(14u, buffered);
338
339  // Read 10 bytes.
340  buf.ConsumeReadData(10);
341
342  // There should be now 12 bytes of available space.
343  size_t remaining;
344  EXPECT_TRUE(buf.GetWriteRemaining(&remaining));
345  EXPECT_EQ(12u, remaining);
346
347  // Write at offset 12, this should fail.
348  EXPECT_EQ(SR_BLOCK, buf.WriteOffset(in, 10, 12, NULL));
349
350  // Write 8 bytes at offset 4, this wraps around the buffer.
351  EXPECT_EQ(SR_SUCCESS, buf.WriteOffset(in, 8, 4, NULL));
352
353  // Number of available space remains the same until we call
354  // ConsumeWriteBuffer().
355  EXPECT_TRUE(buf.GetWriteRemaining(&remaining));
356  EXPECT_EQ(12u, remaining);
357  buf.ConsumeWriteBuffer(12);
358
359  // There's 4 bytes bypassed and 4 bytes no read so skip them and verify the
360  // 8 bytes written.
361  size_t read;
362  EXPECT_EQ(SR_SUCCESS, buf.ReadOffset(out, 8, 8, &read));
363  EXPECT_EQ(8u, read);
364  EXPECT_EQ(0, memcmp(out, in, 8));
365
366  // There should still be 16 bytes available for reading.
367  EXPECT_TRUE(buf.GetBuffered(&buffered));
368  EXPECT_EQ(16u, buffered);
369
370  // Read at offset 16, this should fail since we don't have that much data.
371  EXPECT_EQ(SR_BLOCK, buf.ReadOffset(out, 10, 16, NULL));
372}
373
374}  // namespace rtc
375