OLD | NEW |
| (Empty) |
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 | |
16 namespace rtc { | |
17 | |
18 /////////////////////////////////////////////////////////////////////////////// | |
19 // TestStream | |
20 /////////////////////////////////////////////////////////////////////////////// | |
21 | |
22 class 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 | |
63 bool 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 | |
77 void 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, nullptr), 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, nullptr), 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 | |
97 TEST(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, nullptr)); | |
110 EXPECT_TRUE(nullptr != stream->GetReadData(&bytes)); | |
111 EXPECT_EQ((size_t)0, bytes); | |
112 stream->ConsumeReadData(0); | |
113 EXPECT_TRUE(nullptr != 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, nullptr)); | |
119 EXPECT_EQ(kSize, bytes); | |
120 | |
121 // Try a write that should block | |
122 EXPECT_EQ(SR_BLOCK, stream->Write(in, kSize, &bytes, nullptr)); | |
123 | |
124 // Try a full read | |
125 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize, &bytes, nullptr)); | |
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, nullptr)); | |
131 | |
132 // Try a too-big write | |
133 EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize * 2, &bytes, nullptr)); | |
134 EXPECT_EQ(bytes, kSize); | |
135 | |
136 // Try a too-big read | |
137 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize * 2, &bytes, nullptr)); | |
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, nullptr)); | |
143 EXPECT_EQ(kSize / 2, bytes); | |
144 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, nullptr)); | |
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, nullptr)); | |
148 EXPECT_EQ(kSize / 2, bytes); | |
149 EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize / 2, &bytes, nullptr)); | |
150 EXPECT_EQ(kSize / 2, bytes); | |
151 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, nullptr)); | |
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, nullptr)); | |
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, nullptr)); | |
167 EXPECT_EQ(kSize * 3 / 4, bytes); | |
168 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, nullptr)); | |
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, nullptr)); | |
172 EXPECT_EQ(kSize / 2, bytes); | |
173 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 4, &bytes, nullptr)); | |
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, nullptr)); | |
177 EXPECT_EQ(kSize / 2, bytes); | |
178 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, nullptr)); | |
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, nullptr)); | |
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, nullptr)); | |
191 q = stream->GetReadData(&bytes); | |
192 EXPECT_TRUE(nullptr != 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, nullptr)); | |
197 | |
198 // Try using GetReadData to do some small reads | |
199 EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize, &bytes, nullptr)); | |
200 q = stream->GetReadData(&bytes); | |
201 EXPECT_TRUE(nullptr != 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(nullptr != 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, nullptr)); | |
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, nullptr)); | |
219 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize * 3 / 4, &bytes, nullptr)); | |
220 EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize / 2, &bytes, nullptr)); | |
221 q = stream->GetReadData(&bytes); | |
222 EXPECT_TRUE(nullptr != 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(nullptr != 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(nullptr != 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, nullptr)); | |
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(nullptr != 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(nullptr != 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, nullptr)); | |
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, nullptr)); | |
268 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, nullptr)); | |
269 p = stream->GetWriteBuffer(&bytes); | |
270 EXPECT_TRUE(nullptr != 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(nullptr != 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, nullptr)); | |
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, nullptr)); | |
286 | |
287 // Try growing the buffer | |
288 EXPECT_EQ(SR_SUCCESS, stream->Write(in, kSize, &bytes, nullptr)); | |
289 EXPECT_EQ(kSize, bytes); | |
290 EXPECT_TRUE(buf.SetCapacity(kSize * 2)); | |
291 EXPECT_EQ(SR_SUCCESS, stream->Write(in + kSize, kSize, &bytes, nullptr)); | |
292 EXPECT_EQ(kSize, bytes); | |
293 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize * 2, &bytes, nullptr)); | |
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, nullptr)); | |
299 EXPECT_EQ(kSize, bytes); | |
300 EXPECT_TRUE(buf.SetCapacity(kSize)); | |
301 EXPECT_EQ(SR_BLOCK, stream->Write(in, kSize, &bytes, nullptr)); | |
302 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize, &bytes, nullptr)); | |
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, nullptr)); | |
308 stream->Close(); | |
309 EXPECT_EQ(SS_CLOSED, stream->GetState()); | |
310 EXPECT_EQ(SR_EOS, stream->Write(in, kSize / 2, &bytes, nullptr)); | |
311 EXPECT_EQ(SR_SUCCESS, stream->Read(out, kSize / 2, &bytes, nullptr)); | |
312 EXPECT_EQ(0, memcmp(in, out, kSize / 2)); | |
313 EXPECT_EQ(SR_EOS, stream->Read(out, kSize / 2, &bytes, nullptr)); | |
314 } | |
315 | |
316 TEST(FifoBufferTest, FullBufferCheck) { | |
317 FifoBuffer buff(10); | |
318 buff.ConsumeWriteBuffer(10); | |
319 | |
320 size_t free; | |
321 EXPECT_TRUE(buff.GetWriteBuffer(&free) != nullptr); | |
322 EXPECT_EQ(0U, free); | |
323 } | |
324 | |
325 TEST(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, nullptr, nullptr)); | |
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, nullptr)); | |
349 | |
350 // Write 8 bytes at offset 4, this wraps around the buffer. | |
351 EXPECT_EQ(SR_SUCCESS, buf.WriteOffset(in, 8, 4, nullptr)); | |
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, nullptr)); | |
372 } | |
373 | |
374 } // namespace rtc | |
OLD | NEW |