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