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 "rtc_base/memory/fifo_buffer.h"
12 
13 #include <string.h>
14 
15 #include "test/gtest.h"
16 
17 namespace rtc {
18 
TEST(FifoBufferTest,TestAll)19 TEST(FifoBufferTest, TestAll) {
20   const size_t kSize = 16;
21   const char in[kSize * 2 + 1] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
22   char out[kSize * 2];
23   void* p;
24   const void* q;
25   size_t bytes;
26   FifoBuffer buf(kSize);
27 
28   // Test assumptions about base state
29   EXPECT_EQ(SS_OPEN, buf.GetState());
30   EXPECT_EQ(SR_BLOCK, buf.Read(out, kSize, &bytes, nullptr));
31   EXPECT_TRUE(nullptr != buf.GetWriteBuffer(&bytes));
32   EXPECT_EQ(kSize, bytes);
33   buf.ConsumeWriteBuffer(0);
34 
35   // Try a full write
36   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize, &bytes, nullptr));
37   EXPECT_EQ(kSize, bytes);
38 
39   // Try a write that should block
40   EXPECT_EQ(SR_BLOCK, buf.Write(in, kSize, &bytes, nullptr));
41 
42   // Try a full read
43   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize, &bytes, nullptr));
44   EXPECT_EQ(kSize, bytes);
45   EXPECT_EQ(0, memcmp(in, out, kSize));
46 
47   // Try a read that should block
48   EXPECT_EQ(SR_BLOCK, buf.Read(out, kSize, &bytes, nullptr));
49 
50   // Try a too-big write
51   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize * 2, &bytes, nullptr));
52   EXPECT_EQ(bytes, kSize);
53 
54   // Try a too-big read
55   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize * 2, &bytes, nullptr));
56   EXPECT_EQ(kSize, bytes);
57   EXPECT_EQ(0, memcmp(in, out, kSize));
58 
59   // Try some small writes and reads
60   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize / 2, &bytes, nullptr));
61   EXPECT_EQ(kSize / 2, bytes);
62   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize / 2, &bytes, nullptr));
63   EXPECT_EQ(kSize / 2, bytes);
64   EXPECT_EQ(0, memcmp(in, out, kSize / 2));
65   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize / 2, &bytes, nullptr));
66   EXPECT_EQ(kSize / 2, bytes);
67   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize / 2, &bytes, nullptr));
68   EXPECT_EQ(kSize / 2, bytes);
69   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize / 2, &bytes, nullptr));
70   EXPECT_EQ(kSize / 2, bytes);
71   EXPECT_EQ(0, memcmp(in, out, kSize / 2));
72   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize / 2, &bytes, nullptr));
73   EXPECT_EQ(kSize / 2, bytes);
74   EXPECT_EQ(0, memcmp(in, out, kSize / 2));
75 
76   // Try wraparound reads and writes in the following pattern
77   // WWWWWWWWWWWW.... 0123456789AB....
78   // RRRRRRRRXXXX.... ........89AB....
79   // WWWW....XXXXWWWW 4567....89AB0123
80   // XXXX....RRRRXXXX 4567........0123
81   // XXXXWWWWWWWWXXXX 4567012345670123
82   // RRRRXXXXXXXXRRRR ....01234567....
83   // ....RRRRRRRR.... ................
84   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize * 3 / 4, &bytes, nullptr));
85   EXPECT_EQ(kSize * 3 / 4, bytes);
86   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize / 2, &bytes, nullptr));
87   EXPECT_EQ(kSize / 2, bytes);
88   EXPECT_EQ(0, memcmp(in, out, kSize / 2));
89   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize / 2, &bytes, nullptr));
90   EXPECT_EQ(kSize / 2, bytes);
91   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize / 4, &bytes, nullptr));
92   EXPECT_EQ(kSize / 4, bytes);
93   EXPECT_EQ(0, memcmp(in + kSize / 2, out, kSize / 4));
94   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize / 2, &bytes, nullptr));
95   EXPECT_EQ(kSize / 2, bytes);
96   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize / 2, &bytes, nullptr));
97   EXPECT_EQ(kSize / 2, bytes);
98   EXPECT_EQ(0, memcmp(in, out, kSize / 2));
99   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize / 2, &bytes, nullptr));
100   EXPECT_EQ(kSize / 2, bytes);
101   EXPECT_EQ(0, memcmp(in, out, kSize / 2));
102 
103   // Use GetWriteBuffer to reset the read_position for the next tests
104   buf.GetWriteBuffer(&bytes);
105   buf.ConsumeWriteBuffer(0);
106 
107   // Try using GetReadData to do a full read
108   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize, &bytes, nullptr));
109   q = buf.GetReadData(&bytes);
110   EXPECT_TRUE(nullptr != q);
111   EXPECT_EQ(kSize, bytes);
112   EXPECT_EQ(0, memcmp(q, in, kSize));
113   buf.ConsumeReadData(kSize);
114   EXPECT_EQ(SR_BLOCK, buf.Read(out, kSize, &bytes, nullptr));
115 
116   // Try using GetReadData to do some small reads
117   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize, &bytes, nullptr));
118   q = buf.GetReadData(&bytes);
119   EXPECT_TRUE(nullptr != q);
120   EXPECT_EQ(kSize, bytes);
121   EXPECT_EQ(0, memcmp(q, in, kSize / 2));
122   buf.ConsumeReadData(kSize / 2);
123   q = buf.GetReadData(&bytes);
124   EXPECT_TRUE(nullptr != q);
125   EXPECT_EQ(kSize / 2, bytes);
126   EXPECT_EQ(0, memcmp(q, in + kSize / 2, kSize / 2));
127   buf.ConsumeReadData(kSize / 2);
128   EXPECT_EQ(SR_BLOCK, buf.Read(out, kSize, &bytes, nullptr));
129 
130   // Try using GetReadData in a wraparound case
131   // WWWWWWWWWWWWWWWW 0123456789ABCDEF
132   // RRRRRRRRRRRRXXXX ............CDEF
133   // WWWWWWWW....XXXX 01234567....CDEF
134   // ............RRRR 01234567........
135   // RRRRRRRR........ ................
136   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize, &bytes, nullptr));
137   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize * 3 / 4, &bytes, nullptr));
138   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize / 2, &bytes, nullptr));
139   q = buf.GetReadData(&bytes);
140   EXPECT_TRUE(nullptr != q);
141   EXPECT_EQ(kSize / 4, bytes);
142   EXPECT_EQ(0, memcmp(q, in + kSize * 3 / 4, kSize / 4));
143   buf.ConsumeReadData(kSize / 4);
144   q = buf.GetReadData(&bytes);
145   EXPECT_TRUE(nullptr != q);
146   EXPECT_EQ(kSize / 2, bytes);
147   EXPECT_EQ(0, memcmp(q, in, kSize / 2));
148   buf.ConsumeReadData(kSize / 2);
149 
150   // Use GetWriteBuffer to reset the read_position for the next tests
151   buf.GetWriteBuffer(&bytes);
152   buf.ConsumeWriteBuffer(0);
153 
154   // Try using GetWriteBuffer to do a full write
155   p = buf.GetWriteBuffer(&bytes);
156   EXPECT_TRUE(nullptr != p);
157   EXPECT_EQ(kSize, bytes);
158   memcpy(p, in, kSize);
159   buf.ConsumeWriteBuffer(kSize);
160   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize, &bytes, nullptr));
161   EXPECT_EQ(kSize, bytes);
162   EXPECT_EQ(0, memcmp(in, out, kSize));
163 
164   // Try using GetWriteBuffer to do some small writes
165   p = buf.GetWriteBuffer(&bytes);
166   EXPECT_TRUE(nullptr != p);
167   EXPECT_EQ(kSize, bytes);
168   memcpy(p, in, kSize / 2);
169   buf.ConsumeWriteBuffer(kSize / 2);
170   p = buf.GetWriteBuffer(&bytes);
171   EXPECT_TRUE(nullptr != p);
172   EXPECT_EQ(kSize / 2, bytes);
173   memcpy(p, in + kSize / 2, kSize / 2);
174   buf.ConsumeWriteBuffer(kSize / 2);
175   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize, &bytes, nullptr));
176   EXPECT_EQ(kSize, bytes);
177   EXPECT_EQ(0, memcmp(in, out, kSize));
178 
179   // Try using GetWriteBuffer in a wraparound case
180   // WWWWWWWWWWWW.... 0123456789AB....
181   // RRRRRRRRXXXX.... ........89AB....
182   // ........XXXXWWWW ........89AB0123
183   // WWWW....XXXXXXXX 4567....89AB0123
184   // RRRR....RRRRRRRR ................
185   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize * 3 / 4, &bytes, nullptr));
186   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize / 2, &bytes, nullptr));
187   p = buf.GetWriteBuffer(&bytes);
188   EXPECT_TRUE(nullptr != p);
189   EXPECT_EQ(kSize / 4, bytes);
190   memcpy(p, in, kSize / 4);
191   buf.ConsumeWriteBuffer(kSize / 4);
192   p = buf.GetWriteBuffer(&bytes);
193   EXPECT_TRUE(nullptr != p);
194   EXPECT_EQ(kSize / 2, bytes);
195   memcpy(p, in + kSize / 4, kSize / 4);
196   buf.ConsumeWriteBuffer(kSize / 4);
197   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize * 3 / 4, &bytes, nullptr));
198   EXPECT_EQ(kSize * 3 / 4, bytes);
199   EXPECT_EQ(0, memcmp(in + kSize / 2, out, kSize / 4));
200   EXPECT_EQ(0, memcmp(in, out + kSize / 4, kSize / 4));
201 
202   // Check that the stream is now empty
203   EXPECT_EQ(SR_BLOCK, buf.Read(out, kSize, &bytes, nullptr));
204 
205   // Try growing the buffer
206   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize, &bytes, nullptr));
207   EXPECT_EQ(kSize, bytes);
208   EXPECT_TRUE(buf.SetCapacity(kSize * 2));
209   EXPECT_EQ(SR_SUCCESS, buf.Write(in + kSize, kSize, &bytes, nullptr));
210   EXPECT_EQ(kSize, bytes);
211   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize * 2, &bytes, nullptr));
212   EXPECT_EQ(kSize * 2, bytes);
213   EXPECT_EQ(0, memcmp(in, out, kSize * 2));
214 
215   // Try shrinking the buffer
216   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize, &bytes, nullptr));
217   EXPECT_EQ(kSize, bytes);
218   EXPECT_TRUE(buf.SetCapacity(kSize));
219   EXPECT_EQ(SR_BLOCK, buf.Write(in, kSize, &bytes, nullptr));
220   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize, &bytes, nullptr));
221   EXPECT_EQ(kSize, bytes);
222   EXPECT_EQ(0, memcmp(in, out, kSize));
223 
224   // Write to the stream, close it, read the remaining bytes
225   EXPECT_EQ(SR_SUCCESS, buf.Write(in, kSize / 2, &bytes, nullptr));
226   buf.Close();
227   EXPECT_EQ(SS_CLOSED, buf.GetState());
228   EXPECT_EQ(SR_EOS, buf.Write(in, kSize / 2, &bytes, nullptr));
229   EXPECT_EQ(SR_SUCCESS, buf.Read(out, kSize / 2, &bytes, nullptr));
230   EXPECT_EQ(0, memcmp(in, out, kSize / 2));
231   EXPECT_EQ(SR_EOS, buf.Read(out, kSize / 2, &bytes, nullptr));
232 }
233 
TEST(FifoBufferTest,FullBufferCheck)234 TEST(FifoBufferTest, FullBufferCheck) {
235   FifoBuffer buff(10);
236   buff.ConsumeWriteBuffer(10);
237 
238   size_t free;
239   EXPECT_TRUE(buff.GetWriteBuffer(&free) != nullptr);
240   EXPECT_EQ(0U, free);
241 }
242 
TEST(FifoBufferTest,WriteOffsetAndReadOffset)243 TEST(FifoBufferTest, WriteOffsetAndReadOffset) {
244   const size_t kSize = 16;
245   const char in[kSize * 2 + 1] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
246   char out[kSize * 2];
247   FifoBuffer buf(kSize);
248 
249   // Write 14 bytes.
250   EXPECT_EQ(SR_SUCCESS, buf.Write(in, 14, nullptr, nullptr));
251 
252   // Make sure data is in |buf|.
253   size_t buffered;
254   EXPECT_TRUE(buf.GetBuffered(&buffered));
255   EXPECT_EQ(14u, buffered);
256 
257   // Read 10 bytes.
258   buf.ConsumeReadData(10);
259 
260   // There should be now 12 bytes of available space.
261   size_t remaining;
262   EXPECT_TRUE(buf.GetWriteRemaining(&remaining));
263   EXPECT_EQ(12u, remaining);
264 
265   // Write at offset 12, this should fail.
266   EXPECT_EQ(SR_BLOCK, buf.WriteOffset(in, 10, 12, nullptr));
267 
268   // Write 8 bytes at offset 4, this wraps around the buffer.
269   EXPECT_EQ(SR_SUCCESS, buf.WriteOffset(in, 8, 4, nullptr));
270 
271   // Number of available space remains the same until we call
272   // ConsumeWriteBuffer().
273   EXPECT_TRUE(buf.GetWriteRemaining(&remaining));
274   EXPECT_EQ(12u, remaining);
275   buf.ConsumeWriteBuffer(12);
276 
277   // There's 4 bytes bypassed and 4 bytes no read so skip them and verify the
278   // 8 bytes written.
279   size_t read;
280   EXPECT_EQ(SR_SUCCESS, buf.ReadOffset(out, 8, 8, &read));
281   EXPECT_EQ(8u, read);
282   EXPECT_EQ(0, memcmp(out, in, 8));
283 
284   // There should still be 16 bytes available for reading.
285   EXPECT_TRUE(buf.GetBuffered(&buffered));
286   EXPECT_EQ(16u, buffered);
287 
288   // Read at offset 16, this should fail since we don't have that much data.
289   EXPECT_EQ(SR_BLOCK, buf.ReadOffset(out, 10, 16, nullptr));
290 }
291 
292 }  // namespace rtc
293