• 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 = [&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