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 rtc::AutoThread main_thread;
21 const size_t kSize = 16;
22 const uint8_t in[kSize * 2 + 1] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
23 uint8_t out[kSize * 2];
24 void* p;
25 const void* q;
26 size_t bytes;
27 FifoBuffer buf(kSize);
28
29 // Test assumptions about base state
30 EXPECT_EQ(SS_OPEN, buf.GetState());
31 int error;
32 EXPECT_EQ(SR_BLOCK, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error));
33 EXPECT_TRUE(nullptr != buf.GetWriteBuffer(&bytes));
34 EXPECT_EQ(kSize, bytes);
35 buf.ConsumeWriteBuffer(0);
36
37 // Try a full write
38 EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize), bytes, error));
39 EXPECT_EQ(kSize, bytes);
40
41 // Try a write that should block
42 EXPECT_EQ(SR_BLOCK, buf.Write(rtc::MakeArrayView(in, kSize), bytes, error));
43
44 // Try a full read
45 EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error));
46 EXPECT_EQ(kSize, bytes);
47 EXPECT_EQ(0, memcmp(in, out, kSize));
48
49 // Try a read that should block
50 EXPECT_EQ(SR_BLOCK, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error));
51
52 // Try a too-big write
53 EXPECT_EQ(SR_SUCCESS,
54 buf.Write(rtc::MakeArrayView(in, kSize * 2), bytes, error));
55 EXPECT_EQ(bytes, kSize);
56
57 // Try a too-big read
58 EXPECT_EQ(SR_SUCCESS,
59 buf.Read(rtc::MakeArrayView(out, kSize * 2), bytes, error));
60 EXPECT_EQ(kSize, bytes);
61 EXPECT_EQ(0, memcmp(in, out, kSize));
62
63 // Try some small writes and reads
64 EXPECT_EQ(SR_SUCCESS,
65 buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error));
66 EXPECT_EQ(kSize / 2, bytes);
67 EXPECT_EQ(SR_SUCCESS,
68 buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error));
69 EXPECT_EQ(kSize / 2, bytes);
70 EXPECT_EQ(0, memcmp(in, out, kSize / 2));
71 EXPECT_EQ(SR_SUCCESS,
72 buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error));
73 EXPECT_EQ(kSize / 2, bytes);
74 EXPECT_EQ(SR_SUCCESS,
75 buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error));
76 EXPECT_EQ(kSize / 2, bytes);
77 EXPECT_EQ(SR_SUCCESS,
78 buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error));
79 EXPECT_EQ(kSize / 2, bytes);
80 EXPECT_EQ(0, memcmp(in, out, kSize / 2));
81 EXPECT_EQ(SR_SUCCESS,
82 buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error));
83 EXPECT_EQ(kSize / 2, bytes);
84 EXPECT_EQ(0, memcmp(in, out, kSize / 2));
85
86 // Try wraparound reads and writes in the following pattern
87 // WWWWWWWWWWWW.... 0123456789AB....
88 // RRRRRRRRXXXX.... ........89AB....
89 // WWWW....XXXXWWWW 4567....89AB0123
90 // XXXX....RRRRXXXX 4567........0123
91 // XXXXWWWWWWWWXXXX 4567012345670123
92 // RRRRXXXXXXXXRRRR ....01234567....
93 // ....RRRRRRRR.... ................
94 EXPECT_EQ(SR_SUCCESS,
95 buf.Write(rtc::MakeArrayView(in, kSize * 3 / 4), bytes, error));
96 EXPECT_EQ(kSize * 3 / 4, bytes);
97 EXPECT_EQ(SR_SUCCESS,
98 buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error));
99 EXPECT_EQ(kSize / 2, bytes);
100 EXPECT_EQ(0, memcmp(in, out, kSize / 2));
101 EXPECT_EQ(SR_SUCCESS,
102 buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error));
103 EXPECT_EQ(kSize / 2, bytes);
104 EXPECT_EQ(SR_SUCCESS,
105 buf.Read(rtc::MakeArrayView(out, kSize / 4), bytes, error));
106 EXPECT_EQ(kSize / 4, bytes);
107 EXPECT_EQ(0, memcmp(in + kSize / 2, out, kSize / 4));
108 EXPECT_EQ(SR_SUCCESS,
109 buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error));
110 EXPECT_EQ(kSize / 2, bytes);
111 EXPECT_EQ(SR_SUCCESS,
112 buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error));
113 EXPECT_EQ(kSize / 2, bytes);
114 EXPECT_EQ(0, memcmp(in, out, kSize / 2));
115 EXPECT_EQ(SR_SUCCESS,
116 buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error));
117 EXPECT_EQ(kSize / 2, bytes);
118 EXPECT_EQ(0, memcmp(in, out, kSize / 2));
119
120 // Use GetWriteBuffer to reset the read_position for the next tests
121 buf.GetWriteBuffer(&bytes);
122 buf.ConsumeWriteBuffer(0);
123
124 // Try using GetReadData to do a full read
125 EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize), bytes, error));
126 q = buf.GetReadData(&bytes);
127 EXPECT_TRUE(nullptr != q);
128 EXPECT_EQ(kSize, bytes);
129 EXPECT_EQ(0, memcmp(q, in, kSize));
130 buf.ConsumeReadData(kSize);
131 EXPECT_EQ(SR_BLOCK, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error));
132
133 // Try using GetReadData to do some small reads
134 EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize), bytes, error));
135 q = buf.GetReadData(&bytes);
136 EXPECT_TRUE(nullptr != q);
137 EXPECT_EQ(kSize, bytes);
138 EXPECT_EQ(0, memcmp(q, in, kSize / 2));
139 buf.ConsumeReadData(kSize / 2);
140 q = buf.GetReadData(&bytes);
141 EXPECT_TRUE(nullptr != q);
142 EXPECT_EQ(kSize / 2, bytes);
143 EXPECT_EQ(0, memcmp(q, in + kSize / 2, kSize / 2));
144 buf.ConsumeReadData(kSize / 2);
145 EXPECT_EQ(SR_BLOCK, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error));
146
147 // Try using GetReadData in a wraparound case
148 // WWWWWWWWWWWWWWWW 0123456789ABCDEF
149 // RRRRRRRRRRRRXXXX ............CDEF
150 // WWWWWWWW....XXXX 01234567....CDEF
151 // ............RRRR 01234567........
152 // RRRRRRRR........ ................
153 EXPECT_EQ(SR_SUCCESS, buf.Write(rtc::MakeArrayView(in, kSize), bytes, error));
154 EXPECT_EQ(SR_SUCCESS,
155 buf.Read(rtc::MakeArrayView(out, kSize * 3 / 4), bytes, error));
156 EXPECT_EQ(SR_SUCCESS,
157 buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error));
158 q = buf.GetReadData(&bytes);
159 EXPECT_TRUE(nullptr != q);
160 EXPECT_EQ(kSize / 4, bytes);
161 EXPECT_EQ(0, memcmp(q, in + kSize * 3 / 4, kSize / 4));
162 buf.ConsumeReadData(kSize / 4);
163 q = buf.GetReadData(&bytes);
164 EXPECT_TRUE(nullptr != q);
165 EXPECT_EQ(kSize / 2, bytes);
166 EXPECT_EQ(0, memcmp(q, in, kSize / 2));
167 buf.ConsumeReadData(kSize / 2);
168
169 // Use GetWriteBuffer to reset the read_position for the next tests
170 buf.GetWriteBuffer(&bytes);
171 buf.ConsumeWriteBuffer(0);
172
173 // Try using GetWriteBuffer to do a full write
174 p = buf.GetWriteBuffer(&bytes);
175 EXPECT_TRUE(nullptr != p);
176 EXPECT_EQ(kSize, bytes);
177 memcpy(p, in, kSize);
178 buf.ConsumeWriteBuffer(kSize);
179 EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error));
180 EXPECT_EQ(kSize, bytes);
181 EXPECT_EQ(0, memcmp(in, out, kSize));
182
183 // Try using GetWriteBuffer to do some small writes
184 p = buf.GetWriteBuffer(&bytes);
185 EXPECT_TRUE(nullptr != p);
186 EXPECT_EQ(kSize, bytes);
187 memcpy(p, in, kSize / 2);
188 buf.ConsumeWriteBuffer(kSize / 2);
189 p = buf.GetWriteBuffer(&bytes);
190 EXPECT_TRUE(nullptr != p);
191 EXPECT_EQ(kSize / 2, bytes);
192 memcpy(p, in + kSize / 2, kSize / 2);
193 buf.ConsumeWriteBuffer(kSize / 2);
194 EXPECT_EQ(SR_SUCCESS, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error));
195 EXPECT_EQ(kSize, bytes);
196 EXPECT_EQ(0, memcmp(in, out, kSize));
197
198 // Try using GetWriteBuffer in a wraparound case
199 // WWWWWWWWWWWW.... 0123456789AB....
200 // RRRRRRRRXXXX.... ........89AB....
201 // ........XXXXWWWW ........89AB0123
202 // WWWW....XXXXXXXX 4567....89AB0123
203 // RRRR....RRRRRRRR ................
204 EXPECT_EQ(SR_SUCCESS,
205 buf.Write(rtc::MakeArrayView(in, kSize * 3 / 4), bytes, error));
206 EXPECT_EQ(SR_SUCCESS,
207 buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error));
208 p = buf.GetWriteBuffer(&bytes);
209 EXPECT_TRUE(nullptr != p);
210 EXPECT_EQ(kSize / 4, bytes);
211 memcpy(p, in, kSize / 4);
212 buf.ConsumeWriteBuffer(kSize / 4);
213 p = buf.GetWriteBuffer(&bytes);
214 EXPECT_TRUE(nullptr != p);
215 EXPECT_EQ(kSize / 2, bytes);
216 memcpy(p, in + kSize / 4, kSize / 4);
217 buf.ConsumeWriteBuffer(kSize / 4);
218 EXPECT_EQ(SR_SUCCESS,
219 buf.Read(rtc::MakeArrayView(out, kSize * 3 / 4), bytes, error));
220 EXPECT_EQ(kSize * 3 / 4, bytes);
221 EXPECT_EQ(0, memcmp(in + kSize / 2, out, kSize / 4));
222 EXPECT_EQ(0, memcmp(in, out + kSize / 4, kSize / 4));
223
224 // Check that the stream is now empty
225 EXPECT_EQ(SR_BLOCK, buf.Read(rtc::MakeArrayView(out, kSize), bytes, error));
226
227 // Write to the stream, close it, read the remaining bytes
228 EXPECT_EQ(SR_SUCCESS,
229 buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error));
230 buf.Close();
231 EXPECT_EQ(SS_CLOSED, buf.GetState());
232 EXPECT_EQ(SR_EOS, buf.Write(rtc::MakeArrayView(in, kSize / 2), bytes, error));
233 EXPECT_EQ(SR_SUCCESS,
234 buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error));
235 EXPECT_EQ(0, memcmp(in, out, kSize / 2));
236 EXPECT_EQ(SR_EOS, buf.Read(rtc::MakeArrayView(out, kSize / 2), bytes, error));
237 }
238
TEST(FifoBufferTest,FullBufferCheck)239 TEST(FifoBufferTest, FullBufferCheck) {
240 rtc::AutoThread main_thread;
241 FifoBuffer buff(10);
242 buff.ConsumeWriteBuffer(10);
243
244 size_t free;
245 EXPECT_TRUE(buff.GetWriteBuffer(&free) != nullptr);
246 EXPECT_EQ(0U, free);
247 }
248
249 } // namespace rtc
250