• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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