1 // Copyright 2015 The Chromium OS 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 <brillo/streams/fake_stream.h>
6
7 #include <vector>
8
9 #include <base/callback.h>
10 #include <base/test/simple_test_clock.h>
11 #include <brillo/bind_lambda.h>
12 #include <brillo/message_loops/mock_message_loop.h>
13 #include <gmock/gmock.h>
14 #include <gtest/gtest.h>
15
16 using testing::AnyNumber;
17 using testing::InSequence;
18 using testing::_;
19
20 namespace brillo {
21
22 class FakeStreamTest : public testing::Test {
23 public:
SetUp()24 void SetUp() override {
25 mock_loop_.SetAsCurrent();
26 // Ignore calls to RunOnce().
27 EXPECT_CALL(mock_loop_, RunOnce(true)).Times(AnyNumber());
28 }
29
CreateStream(Stream::AccessMode mode)30 void CreateStream(Stream::AccessMode mode) {
31 stream_.reset(new FakeStream{mode, &clock_});
32 }
33
34 // Performs non-blocking read on the stream and returns the read data
35 // as a string in |out_buffer|. Returns true if the read was successful or
36 // false when an error occurs. |*eos| is set to true when end of stream is
37 // reached.
ReadString(size_t size_to_read,std::string * out_buffer,bool * eos)38 bool ReadString(size_t size_to_read, std::string* out_buffer, bool* eos) {
39 std::vector<char> data;
40 data.resize(size_to_read);
41 size_t size_read = 0;
42 bool ok = stream_->ReadNonBlocking(data.data(), data.size(), &size_read,
43 eos, nullptr);
44 if (ok) {
45 out_buffer->assign(data.data(), data.data() + size_read);
46 } else {
47 out_buffer->clear();
48 }
49 return ok;
50 }
51
52 // Writes a string to a stream. Returns the number of bytes written or -1
53 // in case an error occurred.
WriteString(const std::string & data)54 int WriteString(const std::string& data) {
55 size_t written = 0;
56 if (!stream_->WriteNonBlocking(data.data(), data.size(), &written, nullptr))
57 return -1;
58 return static_cast<int>(written);
59 }
60
61 protected:
62 base::SimpleTestClock clock_;
63 MockMessageLoop mock_loop_{&clock_};
64 std::unique_ptr<FakeStream> stream_;
65 const base::TimeDelta zero_delay;
66 };
67
TEST_F(FakeStreamTest,InitReadOnly)68 TEST_F(FakeStreamTest, InitReadOnly) {
69 CreateStream(Stream::AccessMode::READ);
70 EXPECT_TRUE(stream_->IsOpen());
71 EXPECT_TRUE(stream_->CanRead());
72 EXPECT_FALSE(stream_->CanWrite());
73 EXPECT_FALSE(stream_->CanSeek());
74 EXPECT_FALSE(stream_->CanGetSize());
75 EXPECT_EQ(0, stream_->GetSize());
76 EXPECT_EQ(0, stream_->GetRemainingSize());
77 EXPECT_EQ(0, stream_->GetPosition());
78 }
79
TEST_F(FakeStreamTest,InitWriteOnly)80 TEST_F(FakeStreamTest, InitWriteOnly) {
81 CreateStream(Stream::AccessMode::WRITE);
82 EXPECT_TRUE(stream_->IsOpen());
83 EXPECT_FALSE(stream_->CanRead());
84 EXPECT_TRUE(stream_->CanWrite());
85 EXPECT_FALSE(stream_->CanSeek());
86 EXPECT_FALSE(stream_->CanGetSize());
87 EXPECT_EQ(0, stream_->GetSize());
88 EXPECT_EQ(0, stream_->GetRemainingSize());
89 EXPECT_EQ(0, stream_->GetPosition());
90 }
91
TEST_F(FakeStreamTest,InitReadWrite)92 TEST_F(FakeStreamTest, InitReadWrite) {
93 CreateStream(Stream::AccessMode::READ_WRITE);
94 EXPECT_TRUE(stream_->IsOpen());
95 EXPECT_TRUE(stream_->CanRead());
96 EXPECT_TRUE(stream_->CanWrite());
97 EXPECT_FALSE(stream_->CanSeek());
98 EXPECT_FALSE(stream_->CanGetSize());
99 EXPECT_EQ(0, stream_->GetSize());
100 EXPECT_EQ(0, stream_->GetRemainingSize());
101 EXPECT_EQ(0, stream_->GetPosition());
102 }
103
TEST_F(FakeStreamTest,ReadEmpty)104 TEST_F(FakeStreamTest, ReadEmpty) {
105 CreateStream(Stream::AccessMode::READ);
106 std::string data;
107 bool eos = false;
108 EXPECT_TRUE(ReadString(100, &data, &eos));
109 EXPECT_TRUE(eos);
110 EXPECT_TRUE(data.empty());
111 }
112
TEST_F(FakeStreamTest,ReadFullPacket)113 TEST_F(FakeStreamTest, ReadFullPacket) {
114 CreateStream(Stream::AccessMode::READ);
115 stream_->AddReadPacketString({}, "foo");
116 std::string data;
117 bool eos = false;
118 EXPECT_TRUE(ReadString(100, &data, &eos));
119 EXPECT_FALSE(eos);
120 EXPECT_EQ("foo", data);
121
122 EXPECT_TRUE(ReadString(100, &data, &eos));
123 EXPECT_TRUE(eos);
124 EXPECT_TRUE(data.empty());
125 }
126
TEST_F(FakeStreamTest,ReadPartialPacket)127 TEST_F(FakeStreamTest, ReadPartialPacket) {
128 CreateStream(Stream::AccessMode::READ);
129 stream_->AddReadPacketString({}, "foobar");
130 std::string data;
131 bool eos = false;
132 EXPECT_TRUE(ReadString(3, &data, &eos));
133 EXPECT_FALSE(eos);
134 EXPECT_EQ("foo", data);
135
136 EXPECT_TRUE(ReadString(100, &data, &eos));
137 EXPECT_FALSE(eos);
138 EXPECT_EQ("bar", data);
139
140 EXPECT_TRUE(ReadString(100, &data, &eos));
141 EXPECT_TRUE(eos);
142 EXPECT_TRUE(data.empty());
143 }
144
TEST_F(FakeStreamTest,ReadMultiplePackets)145 TEST_F(FakeStreamTest, ReadMultiplePackets) {
146 CreateStream(Stream::AccessMode::READ);
147 stream_->AddReadPacketString({}, "foobar");
148 stream_->AddReadPacketString({}, "baz");
149 stream_->AddReadPacketString({}, "quux");
150 std::string data;
151 bool eos = false;
152 EXPECT_TRUE(ReadString(100, &data, &eos));
153 EXPECT_FALSE(eos);
154 EXPECT_EQ("foobar", data);
155
156 EXPECT_TRUE(ReadString(2, &data, &eos));
157 EXPECT_FALSE(eos);
158 EXPECT_EQ("ba", data);
159
160 EXPECT_TRUE(ReadString(100, &data, &eos));
161 EXPECT_FALSE(eos);
162 EXPECT_EQ("z", data);
163
164 EXPECT_TRUE(ReadString(100, &data, &eos));
165 EXPECT_FALSE(eos);
166 EXPECT_EQ("quux", data);
167
168 EXPECT_TRUE(ReadString(100, &data, &eos));
169 EXPECT_TRUE(eos);
170 EXPECT_TRUE(data.empty());
171
172 stream_->AddReadPacketString({}, "foo-bar");
173 EXPECT_TRUE(ReadString(100, &data, &eos));
174 EXPECT_FALSE(eos);
175 EXPECT_EQ("foo-bar", data);
176 }
177
TEST_F(FakeStreamTest,ReadPacketsWithDelay)178 TEST_F(FakeStreamTest, ReadPacketsWithDelay) {
179 CreateStream(Stream::AccessMode::READ);
180 stream_->AddReadPacketString({}, "foobar");
181 stream_->AddReadPacketString(base::TimeDelta::FromSeconds(1), "baz");
182 std::string data;
183 bool eos = false;
184 EXPECT_TRUE(ReadString(100, &data, &eos));
185 EXPECT_FALSE(eos);
186 EXPECT_EQ("foobar", data);
187
188 EXPECT_TRUE(ReadString(100, &data, &eos));
189 EXPECT_FALSE(eos);
190 EXPECT_TRUE(data.empty());
191
192 EXPECT_TRUE(ReadString(100, &data, &eos));
193 EXPECT_FALSE(eos);
194 EXPECT_TRUE(data.empty());
195
196 clock_.Advance(base::TimeDelta::FromSeconds(1));
197
198 EXPECT_TRUE(ReadString(100, &data, &eos));
199 EXPECT_FALSE(eos);
200 EXPECT_EQ("baz", data);
201 }
202
TEST_F(FakeStreamTest,ReadPacketsWithError)203 TEST_F(FakeStreamTest, ReadPacketsWithError) {
204 CreateStream(Stream::AccessMode::READ);
205 stream_->AddReadPacketString({}, "foobar");
206 stream_->QueueReadErrorWithMessage(base::TimeDelta::FromSeconds(1),
207 "Dummy error");
208 stream_->AddReadPacketString({}, "baz");
209
210 std::string data;
211 bool eos = false;
212 EXPECT_TRUE(ReadString(100, &data, &eos));
213 EXPECT_FALSE(eos);
214 EXPECT_EQ("foobar", data);
215
216 EXPECT_TRUE(ReadString(100, &data, &eos));
217 EXPECT_FALSE(eos);
218 EXPECT_TRUE(data.empty());
219
220 EXPECT_TRUE(ReadString(100, &data, &eos));
221 EXPECT_FALSE(eos);
222 EXPECT_TRUE(data.empty());
223
224 clock_.Advance(base::TimeDelta::FromSeconds(1));
225
226 EXPECT_FALSE(ReadString(100, &data, &eos));
227
228 EXPECT_TRUE(ReadString(100, &data, &eos));
229 EXPECT_FALSE(eos);
230 EXPECT_EQ("baz", data);
231 }
232
TEST_F(FakeStreamTest,WaitForDataRead)233 TEST_F(FakeStreamTest, WaitForDataRead) {
234 CreateStream(Stream::AccessMode::READ);
235
236 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(2);
237
238 int call_count = 0;
239 auto callback = [](int* call_count, Stream::AccessMode mode) {
240 (*call_count)++;
241 EXPECT_EQ(Stream::AccessMode::READ, mode);
242 };
243
244 EXPECT_TRUE(
245 stream_->WaitForData(Stream::AccessMode::READ,
246 base::Bind(callback, base::Unretained(&call_count)),
247 nullptr));
248 mock_loop_.Run();
249 EXPECT_EQ(1, call_count);
250
251 stream_->AddReadPacketString({}, "foobar");
252 EXPECT_TRUE(
253 stream_->WaitForData(Stream::AccessMode::READ,
254 base::Bind(callback, base::Unretained(&call_count)),
255 nullptr));
256 mock_loop_.Run();
257 EXPECT_EQ(2, call_count);
258
259 stream_->ClearReadQueue();
260
261 auto one_sec_delay = base::TimeDelta::FromSeconds(1);
262 stream_->AddReadPacketString(one_sec_delay, "baz");
263 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
264 EXPECT_TRUE(
265 stream_->WaitForData(Stream::AccessMode::READ,
266 base::Bind(callback, base::Unretained(&call_count)),
267 nullptr));
268 mock_loop_.Run();
269 EXPECT_EQ(3, call_count);
270 }
271
TEST_F(FakeStreamTest,ReadAsync)272 TEST_F(FakeStreamTest, ReadAsync) {
273 CreateStream(Stream::AccessMode::READ);
274 std::string input_data = "foobar-baz";
275 size_t split_pos = input_data.find('-');
276
277 auto one_sec_delay = base::TimeDelta::FromSeconds(1);
278 stream_->AddReadPacketString({}, input_data.substr(0, split_pos));
279 stream_->AddReadPacketString(one_sec_delay, input_data.substr(split_pos));
280
281 {
282 InSequence seq;
283 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(1);
284 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
285 }
286
287 std::vector<char> buffer;
288 buffer.resize(input_data.size());
289
290 int success_count = 0;
291 int error_count = 0;
292 auto on_success = [](int* success_count) { (*success_count)++; };
293 auto on_failure = [](int* error_count, const Error* /* error */) {
294 (*error_count)++;
295 };
296
297 EXPECT_TRUE(stream_->ReadAllAsync(
298 buffer.data(),
299 buffer.size(),
300 base::Bind(on_success, base::Unretained(&success_count)),
301 base::Bind(on_failure, base::Unretained(&error_count)),
302 nullptr));
303 mock_loop_.Run();
304 EXPECT_EQ(1, success_count);
305 EXPECT_EQ(0, error_count);
306 EXPECT_EQ(input_data, (std::string{buffer.begin(), buffer.end()}));
307 }
308
TEST_F(FakeStreamTest,WriteEmpty)309 TEST_F(FakeStreamTest, WriteEmpty) {
310 CreateStream(Stream::AccessMode::WRITE);
311 EXPECT_EQ(-1, WriteString("foo"));
312 }
313
TEST_F(FakeStreamTest,WritePartial)314 TEST_F(FakeStreamTest, WritePartial) {
315 CreateStream(Stream::AccessMode::WRITE);
316 stream_->ExpectWritePacketSize({}, 6);
317 EXPECT_EQ(3, WriteString("foo"));
318 EXPECT_EQ(3, WriteString("bar"));
319 EXPECT_EQ(-1, WriteString("baz"));
320
321 EXPECT_EQ("foobar", stream_->GetFlushedOutputDataAsString());
322 }
323
TEST_F(FakeStreamTest,WriteFullPackets)324 TEST_F(FakeStreamTest, WriteFullPackets) {
325 CreateStream(Stream::AccessMode::WRITE);
326
327 stream_->ExpectWritePacketSize({}, 3);
328 EXPECT_EQ(3, WriteString("foo"));
329 EXPECT_EQ(-1, WriteString("bar"));
330
331 stream_->ExpectWritePacketSize({}, 3);
332 EXPECT_EQ(3, WriteString("bar"));
333
334 stream_->ExpectWritePacketSize({}, 3);
335 EXPECT_EQ(3, WriteString("quux"));
336
337 EXPECT_EQ("foobarquu", stream_->GetFlushedOutputDataAsString());
338 }
339
TEST_F(FakeStreamTest,WriteAndVerifyData)340 TEST_F(FakeStreamTest, WriteAndVerifyData) {
341 CreateStream(Stream::AccessMode::WRITE);
342
343 stream_->ExpectWritePacketString({}, "foo");
344 stream_->ExpectWritePacketString({}, "bar");
345 EXPECT_EQ(3, WriteString("foobar"));
346 EXPECT_EQ(3, WriteString("bar"));
347
348 stream_->ExpectWritePacketString({}, "foo");
349 stream_->ExpectWritePacketString({}, "baz");
350 EXPECT_EQ(3, WriteString("foobar"));
351 EXPECT_EQ(-1, WriteString("bar"));
352
353 stream_->ExpectWritePacketString({}, "foobar");
354 EXPECT_EQ(3, WriteString("foo"));
355 EXPECT_EQ(2, WriteString("ba"));
356 EXPECT_EQ(-1, WriteString("z"));
357 }
358
TEST_F(FakeStreamTest,WriteWithDelay)359 TEST_F(FakeStreamTest, WriteWithDelay) {
360 CreateStream(Stream::AccessMode::WRITE);
361
362 const auto delay = base::TimeDelta::FromMilliseconds(500);
363
364 stream_->ExpectWritePacketSize({}, 3);
365 stream_->ExpectWritePacketSize(delay, 3);
366 EXPECT_EQ(3, WriteString("foobar"));
367
368 EXPECT_EQ(0, WriteString("bar"));
369 EXPECT_EQ(0, WriteString("bar"));
370 clock_.Advance(delay);
371 EXPECT_EQ(3, WriteString("bar"));
372
373 EXPECT_EQ("foobar", stream_->GetFlushedOutputDataAsString());
374 }
375
TEST_F(FakeStreamTest,WriteWithError)376 TEST_F(FakeStreamTest, WriteWithError) {
377 CreateStream(Stream::AccessMode::WRITE);
378
379 const auto delay = base::TimeDelta::FromMilliseconds(500);
380
381 stream_->ExpectWritePacketSize({}, 3);
382 stream_->QueueWriteError({});
383 stream_->ExpectWritePacketSize({}, 3);
384 stream_->QueueWriteErrorWithMessage(delay, "Dummy message");
385 stream_->ExpectWritePacketString({}, "foobar");
386
387 const std::string data = "foobarbaz";
388 EXPECT_EQ(3, WriteString(data));
389 EXPECT_EQ(-1, WriteString(data)); // Simulated error #1.
390 EXPECT_EQ(3, WriteString(data));
391 EXPECT_EQ(0, WriteString(data)); // Waiting for data...
392 clock_.Advance(delay);
393 EXPECT_EQ(-1, WriteString(data)); // Simulated error #2.
394 EXPECT_EQ(6, WriteString(data));
395 EXPECT_EQ(-1, WriteString(data)); // No more data expected.
396 }
397
TEST_F(FakeStreamTest,WaitForDataWrite)398 TEST_F(FakeStreamTest, WaitForDataWrite) {
399 CreateStream(Stream::AccessMode::WRITE);
400
401 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(2);
402
403 int call_count = 0;
404 auto callback = [](int* call_count, Stream::AccessMode mode) {
405 (*call_count)++;
406 EXPECT_EQ(Stream::AccessMode::WRITE, mode);
407 };
408
409 EXPECT_TRUE(
410 stream_->WaitForData(Stream::AccessMode::WRITE,
411 base::Bind(callback, base::Unretained(&call_count)),
412 nullptr));
413 mock_loop_.Run();
414 EXPECT_EQ(1, call_count);
415
416 stream_->ExpectWritePacketString({}, "foobar");
417 EXPECT_TRUE(
418 stream_->WaitForData(Stream::AccessMode::WRITE,
419 base::Bind(callback, base::Unretained(&call_count)),
420 nullptr));
421 mock_loop_.Run();
422 EXPECT_EQ(2, call_count);
423
424 stream_->ClearWriteQueue();
425
426 auto one_sec_delay = base::TimeDelta::FromSeconds(1);
427 stream_->ExpectWritePacketString(one_sec_delay, "baz");
428 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
429 EXPECT_TRUE(
430 stream_->WaitForData(Stream::AccessMode::WRITE,
431 base::Bind(callback, base::Unretained(&call_count)),
432 nullptr));
433 mock_loop_.Run();
434 EXPECT_EQ(3, call_count);
435 }
436
TEST_F(FakeStreamTest,WriteAsync)437 TEST_F(FakeStreamTest, WriteAsync) {
438 CreateStream(Stream::AccessMode::WRITE);
439 std::string output_data = "foobar-baz";
440 size_t split_pos = output_data.find('-');
441
442 auto one_sec_delay = base::TimeDelta::FromSeconds(1);
443 stream_->ExpectWritePacketString({}, output_data.substr(0, split_pos));
444 stream_->ExpectWritePacketString(one_sec_delay,
445 output_data.substr(split_pos));
446
447 {
448 InSequence seq;
449 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(1);
450 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
451 }
452
453 int success_count = 0;
454 int error_count = 0;
455 auto on_success = [](int* success_count) { (*success_count)++; };
456 auto on_failure = [](int* error_count, const Error* /* error */) {
457 (*error_count)++;
458 };
459
460 EXPECT_TRUE(stream_->WriteAllAsync(
461 output_data.data(),
462 output_data.size(),
463 base::Bind(on_success, base::Unretained(&success_count)),
464 base::Bind(on_failure, base::Unretained(&error_count)),
465 nullptr));
466 mock_loop_.Run();
467 EXPECT_EQ(1, success_count);
468 EXPECT_EQ(0, error_count);
469 EXPECT_EQ(output_data, stream_->GetFlushedOutputDataAsString());
470 }
471
TEST_F(FakeStreamTest,WaitForDataReadWrite)472 TEST_F(FakeStreamTest, WaitForDataReadWrite) {
473 CreateStream(Stream::AccessMode::READ_WRITE);
474 auto one_sec_delay = base::TimeDelta::FromSeconds(1);
475 auto two_sec_delay = base::TimeDelta::FromSeconds(2);
476
477 int call_count = 0;
478 auto callback = [](int* call_count,
479 Stream::AccessMode mode,
480 Stream::AccessMode expected_mode) {
481 (*call_count)++;
482 EXPECT_EQ(static_cast<int>(expected_mode), static_cast<int>(mode));
483 };
484
485 stream_->AddReadPacketString(one_sec_delay, "foo");
486 stream_->ExpectWritePacketString(two_sec_delay, "bar");
487
488 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
489 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE,
490 base::Bind(callback,
491 base::Unretained(&call_count),
492 Stream::AccessMode::READ),
493 nullptr));
494 mock_loop_.Run();
495 EXPECT_EQ(1, call_count);
496
497 // The above step has adjusted the clock by 1 second already.
498 stream_->ClearReadQueue();
499 stream_->AddReadPacketString(two_sec_delay, "foo");
500 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
501 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE,
502 base::Bind(callback,
503 base::Unretained(&call_count),
504 Stream::AccessMode::WRITE),
505 nullptr));
506 mock_loop_.Run();
507 EXPECT_EQ(2, call_count);
508
509 clock_.Advance(one_sec_delay);
510
511 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(1);
512 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE,
513 base::Bind(callback,
514 base::Unretained(&call_count),
515 Stream::AccessMode::READ_WRITE),
516 nullptr));
517 mock_loop_.Run();
518 EXPECT_EQ(3, call_count);
519
520 stream_->ClearReadQueue();
521 stream_->ClearWriteQueue();
522 stream_->AddReadPacketString(one_sec_delay, "foo");
523 stream_->ExpectWritePacketString(one_sec_delay, "bar");
524
525 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
526 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE,
527 base::Bind(callback,
528 base::Unretained(&call_count),
529 Stream::AccessMode::READ_WRITE),
530 nullptr));
531 mock_loop_.Run();
532 EXPECT_EQ(4, call_count);
533 }
534
535 } // namespace brillo
536