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 = [&call_count](Stream::AccessMode mode) {
240 call_count++;
241 EXPECT_EQ(Stream::AccessMode::READ, mode);
242 };
243
244 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ,
245 base::Bind(callback), nullptr));
246 mock_loop_.Run();
247 EXPECT_EQ(1, call_count);
248
249 stream_->AddReadPacketString({}, "foobar");
250 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ,
251 base::Bind(callback), nullptr));
252 mock_loop_.Run();
253 EXPECT_EQ(2, call_count);
254
255 stream_->ClearReadQueue();
256
257 auto one_sec_delay = base::TimeDelta::FromSeconds(1);
258 stream_->AddReadPacketString(one_sec_delay, "baz");
259 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
260 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ,
261 base::Bind(callback), nullptr));
262 mock_loop_.Run();
263 EXPECT_EQ(3, call_count);
264 }
265
TEST_F(FakeStreamTest,ReadAsync)266 TEST_F(FakeStreamTest, ReadAsync) {
267 CreateStream(Stream::AccessMode::READ);
268 std::string input_data = "foobar-baz";
269 size_t split_pos = input_data.find('-');
270
271 auto one_sec_delay = base::TimeDelta::FromSeconds(1);
272 stream_->AddReadPacketString({}, input_data.substr(0, split_pos));
273 stream_->AddReadPacketString(one_sec_delay, input_data.substr(split_pos));
274
275 {
276 InSequence seq;
277 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(1);
278 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
279 }
280
281 std::vector<char> buffer;
282 buffer.resize(input_data.size());
283
284 int success_count = 0;
285 int error_count = 0;
286 auto on_success = [&success_count] { success_count++; };
287 auto on_failure = [&error_count](const Error* /* error */) { error_count++; };
288
289 EXPECT_TRUE(stream_->ReadAllAsync(buffer.data(), buffer.size(),
290 base::Bind(on_success),
291 base::Bind(on_failure),
292 nullptr));
293 mock_loop_.Run();
294 EXPECT_EQ(1, success_count);
295 EXPECT_EQ(0, error_count);
296 EXPECT_EQ(input_data, (std::string{buffer.begin(), buffer.end()}));
297 }
298
TEST_F(FakeStreamTest,WriteEmpty)299 TEST_F(FakeStreamTest, WriteEmpty) {
300 CreateStream(Stream::AccessMode::WRITE);
301 EXPECT_EQ(-1, WriteString("foo"));
302 }
303
TEST_F(FakeStreamTest,WritePartial)304 TEST_F(FakeStreamTest, WritePartial) {
305 CreateStream(Stream::AccessMode::WRITE);
306 stream_->ExpectWritePacketSize({}, 6);
307 EXPECT_EQ(3, WriteString("foo"));
308 EXPECT_EQ(3, WriteString("bar"));
309 EXPECT_EQ(-1, WriteString("baz"));
310
311 EXPECT_EQ("foobar", stream_->GetFlushedOutputDataAsString());
312 }
313
TEST_F(FakeStreamTest,WriteFullPackets)314 TEST_F(FakeStreamTest, WriteFullPackets) {
315 CreateStream(Stream::AccessMode::WRITE);
316
317 stream_->ExpectWritePacketSize({}, 3);
318 EXPECT_EQ(3, WriteString("foo"));
319 EXPECT_EQ(-1, WriteString("bar"));
320
321 stream_->ExpectWritePacketSize({}, 3);
322 EXPECT_EQ(3, WriteString("bar"));
323
324 stream_->ExpectWritePacketSize({}, 3);
325 EXPECT_EQ(3, WriteString("quux"));
326
327 EXPECT_EQ("foobarquu", stream_->GetFlushedOutputDataAsString());
328 }
329
TEST_F(FakeStreamTest,WriteAndVerifyData)330 TEST_F(FakeStreamTest, WriteAndVerifyData) {
331 CreateStream(Stream::AccessMode::WRITE);
332
333 stream_->ExpectWritePacketString({}, "foo");
334 stream_->ExpectWritePacketString({}, "bar");
335 EXPECT_EQ(3, WriteString("foobar"));
336 EXPECT_EQ(3, WriteString("bar"));
337
338 stream_->ExpectWritePacketString({}, "foo");
339 stream_->ExpectWritePacketString({}, "baz");
340 EXPECT_EQ(3, WriteString("foobar"));
341 EXPECT_EQ(-1, WriteString("bar"));
342
343 stream_->ExpectWritePacketString({}, "foobar");
344 EXPECT_EQ(3, WriteString("foo"));
345 EXPECT_EQ(2, WriteString("ba"));
346 EXPECT_EQ(-1, WriteString("z"));
347 }
348
TEST_F(FakeStreamTest,WriteWithDelay)349 TEST_F(FakeStreamTest, WriteWithDelay) {
350 CreateStream(Stream::AccessMode::WRITE);
351
352 const auto delay = base::TimeDelta::FromMilliseconds(500);
353
354 stream_->ExpectWritePacketSize({}, 3);
355 stream_->ExpectWritePacketSize(delay, 3);
356 EXPECT_EQ(3, WriteString("foobar"));
357
358 EXPECT_EQ(0, WriteString("bar"));
359 EXPECT_EQ(0, WriteString("bar"));
360 clock_.Advance(delay);
361 EXPECT_EQ(3, WriteString("bar"));
362
363 EXPECT_EQ("foobar", stream_->GetFlushedOutputDataAsString());
364 }
365
TEST_F(FakeStreamTest,WriteWithError)366 TEST_F(FakeStreamTest, WriteWithError) {
367 CreateStream(Stream::AccessMode::WRITE);
368
369 const auto delay = base::TimeDelta::FromMilliseconds(500);
370
371 stream_->ExpectWritePacketSize({}, 3);
372 stream_->QueueWriteError({});
373 stream_->ExpectWritePacketSize({}, 3);
374 stream_->QueueWriteErrorWithMessage(delay, "Dummy message");
375 stream_->ExpectWritePacketString({}, "foobar");
376
377 const std::string data = "foobarbaz";
378 EXPECT_EQ(3, WriteString(data));
379 EXPECT_EQ(-1, WriteString(data)); // Simulated error #1.
380 EXPECT_EQ(3, WriteString(data));
381 EXPECT_EQ(0, WriteString(data)); // Waiting for data...
382 clock_.Advance(delay);
383 EXPECT_EQ(-1, WriteString(data)); // Simulated error #2.
384 EXPECT_EQ(6, WriteString(data));
385 EXPECT_EQ(-1, WriteString(data)); // No more data expected.
386 }
387
TEST_F(FakeStreamTest,WaitForDataWrite)388 TEST_F(FakeStreamTest, WaitForDataWrite) {
389 CreateStream(Stream::AccessMode::WRITE);
390
391 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(2);
392
393 int call_count = 0;
394 auto callback = [&call_count](Stream::AccessMode mode) {
395 call_count++;
396 EXPECT_EQ(Stream::AccessMode::WRITE, mode);
397 };
398
399 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::WRITE,
400 base::Bind(callback), nullptr));
401 mock_loop_.Run();
402 EXPECT_EQ(1, call_count);
403
404 stream_->ExpectWritePacketString({}, "foobar");
405 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::WRITE,
406 base::Bind(callback), nullptr));
407 mock_loop_.Run();
408 EXPECT_EQ(2, call_count);
409
410 stream_->ClearWriteQueue();
411
412 auto one_sec_delay = base::TimeDelta::FromSeconds(1);
413 stream_->ExpectWritePacketString(one_sec_delay, "baz");
414 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
415 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::WRITE,
416 base::Bind(callback), nullptr));
417 mock_loop_.Run();
418 EXPECT_EQ(3, call_count);
419 }
420
TEST_F(FakeStreamTest,WriteAsync)421 TEST_F(FakeStreamTest, WriteAsync) {
422 CreateStream(Stream::AccessMode::WRITE);
423 std::string output_data = "foobar-baz";
424 size_t split_pos = output_data.find('-');
425
426 auto one_sec_delay = base::TimeDelta::FromSeconds(1);
427 stream_->ExpectWritePacketString({}, output_data.substr(0, split_pos));
428 stream_->ExpectWritePacketString(one_sec_delay,
429 output_data.substr(split_pos));
430
431 {
432 InSequence seq;
433 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(1);
434 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
435 }
436
437 int success_count = 0;
438 int error_count = 0;
439 auto on_success = [&success_count] { success_count++; };
440 auto on_failure = [&error_count](const Error* /* error */) { error_count++; };
441
442 EXPECT_TRUE(stream_->WriteAllAsync(output_data.data(), output_data.size(),
443 base::Bind(on_success),
444 base::Bind(on_failure),
445 nullptr));
446 mock_loop_.Run();
447 EXPECT_EQ(1, success_count);
448 EXPECT_EQ(0, error_count);
449 EXPECT_EQ(output_data, stream_->GetFlushedOutputDataAsString());
450 }
451
TEST_F(FakeStreamTest,WaitForDataReadWrite)452 TEST_F(FakeStreamTest, WaitForDataReadWrite) {
453 CreateStream(Stream::AccessMode::READ_WRITE);
454 auto one_sec_delay = base::TimeDelta::FromSeconds(1);
455 auto two_sec_delay = base::TimeDelta::FromSeconds(2);
456
457 int call_count = 0;
458 auto callback = [&call_count](Stream::AccessMode mode,
459 Stream::AccessMode expected_mode) {
460 call_count++;
461 EXPECT_EQ(static_cast<int>(expected_mode), static_cast<int>(mode));
462 };
463
464 stream_->AddReadPacketString(one_sec_delay, "foo");
465 stream_->ExpectWritePacketString(two_sec_delay, "bar");
466
467 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
468 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE,
469 base::Bind(callback,
470 Stream::AccessMode::READ),
471 nullptr));
472 mock_loop_.Run();
473 EXPECT_EQ(1, call_count);
474
475 // The above step has adjusted the clock by 1 second already.
476 stream_->ClearReadQueue();
477 stream_->AddReadPacketString(two_sec_delay, "foo");
478 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
479 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE,
480 base::Bind(callback,
481 Stream::AccessMode::WRITE),
482 nullptr));
483 mock_loop_.Run();
484 EXPECT_EQ(2, call_count);
485
486 clock_.Advance(one_sec_delay);
487
488 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, zero_delay)).Times(1);
489 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE,
490 base::Bind(callback,
491 Stream::AccessMode::READ_WRITE),
492 nullptr));
493 mock_loop_.Run();
494 EXPECT_EQ(3, call_count);
495
496 stream_->ClearReadQueue();
497 stream_->ClearWriteQueue();
498 stream_->AddReadPacketString(one_sec_delay, "foo");
499 stream_->ExpectWritePacketString(one_sec_delay, "bar");
500
501 EXPECT_CALL(mock_loop_, PostDelayedTask(_, _, one_sec_delay)).Times(1);
502 EXPECT_TRUE(stream_->WaitForData(Stream::AccessMode::READ_WRITE,
503 base::Bind(callback,
504 Stream::AccessMode::READ_WRITE),
505 nullptr));
506 mock_loop_.Run();
507 EXPECT_EQ(4, call_count);
508 }
509
510 } // namespace brillo
511