Home | History | Annotate | Download | only in streams
      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/stream_utils.h>
      6 
      7 #include <limits>
      8 
      9 #include <base/bind.h>
     10 #include <brillo/message_loops/fake_message_loop.h>
     11 #include <brillo/message_loops/message_loop.h>
     12 #include <brillo/streams/mock_stream.h>
     13 #include <brillo/streams/stream_errors.h>
     14 #include <gmock/gmock.h>
     15 #include <gtest/gtest.h>
     16 
     17 using testing::DoAll;
     18 using testing::InSequence;
     19 using testing::Return;
     20 using testing::StrictMock;
     21 using testing::_;
     22 
     23 ACTION_TEMPLATE(InvokeAsyncCallback,
     24                 HAS_1_TEMPLATE_PARAMS(int, k),
     25                 AND_1_VALUE_PARAMS(size)) {
     26   brillo::MessageLoop::current()->PostTask(
     27       FROM_HERE, base::Bind(std::get<k>(args), size));
     28   return true;
     29 }
     30 
     31 ACTION_TEMPLATE(InvokeAsyncCallback,
     32                 HAS_1_TEMPLATE_PARAMS(int, k),
     33                 AND_0_VALUE_PARAMS()) {
     34   brillo::MessageLoop::current()->PostTask(FROM_HERE, std::get<k>(args));
     35   return true;
     36 }
     37 
     38 ACTION_TEMPLATE(InvokeAsyncErrorCallback,
     39                 HAS_1_TEMPLATE_PARAMS(int, k),
     40                 AND_1_VALUE_PARAMS(code)) {
     41   brillo::ErrorPtr error;
     42   brillo::Error::AddTo(&error, FROM_HERE, "test", code, "message");
     43   brillo::MessageLoop::current()->PostTask(
     44       FROM_HERE, base::Bind(std::get<k>(args), base::Owned(error.release())));
     45   return true;
     46 }
     47 
     48 namespace brillo {
     49 
     50 TEST(StreamUtils, ErrorStreamClosed) {
     51   ErrorPtr error;
     52   EXPECT_FALSE(stream_utils::ErrorStreamClosed(FROM_HERE, &error));
     53   EXPECT_EQ(errors::stream::kDomain, error->GetDomain());
     54   EXPECT_EQ(errors::stream::kStreamClosed, error->GetCode());
     55   EXPECT_EQ("Stream is closed", error->GetMessage());
     56 }
     57 
     58 TEST(StreamUtils, ErrorOperationNotSupported) {
     59   ErrorPtr error;
     60   EXPECT_FALSE(stream_utils::ErrorOperationNotSupported(FROM_HERE, &error));
     61   EXPECT_EQ(errors::stream::kDomain, error->GetDomain());
     62   EXPECT_EQ(errors::stream::kOperationNotSupported, error->GetCode());
     63   EXPECT_EQ("Stream operation not supported", error->GetMessage());
     64 }
     65 
     66 TEST(StreamUtils, ErrorReadPastEndOfStream) {
     67   ErrorPtr error;
     68   EXPECT_FALSE(stream_utils::ErrorReadPastEndOfStream(FROM_HERE, &error));
     69   EXPECT_EQ(errors::stream::kDomain, error->GetDomain());
     70   EXPECT_EQ(errors::stream::kPartialData, error->GetCode());
     71   EXPECT_EQ("Reading past the end of stream", error->GetMessage());
     72 }
     73 
     74 TEST(StreamUtils, CheckInt64Overflow) {
     75   const int64_t max_int64 = std::numeric_limits<int64_t>::max();
     76   const uint64_t max_uint64 = std::numeric_limits<uint64_t>::max();
     77   EXPECT_TRUE(stream_utils::CheckInt64Overflow(FROM_HERE, 0, 0, nullptr));
     78   EXPECT_TRUE(stream_utils::CheckInt64Overflow(
     79       FROM_HERE, 0, max_int64, nullptr));
     80   EXPECT_TRUE(stream_utils::CheckInt64Overflow(
     81       FROM_HERE, max_int64, 0, nullptr));
     82   EXPECT_TRUE(stream_utils::CheckInt64Overflow(FROM_HERE, 100, -90, nullptr));
     83   EXPECT_TRUE(stream_utils::CheckInt64Overflow(
     84       FROM_HERE, 1000, -1000, nullptr));
     85 
     86   ErrorPtr error;
     87   EXPECT_FALSE(stream_utils::CheckInt64Overflow(FROM_HERE, 100, -101, &error));
     88   EXPECT_EQ(errors::stream::kDomain, error->GetDomain());
     89   EXPECT_EQ(errors::stream::kInvalidParameter, error->GetCode());
     90   EXPECT_EQ("The stream offset value is out of range", error->GetMessage());
     91 
     92   EXPECT_FALSE(stream_utils::CheckInt64Overflow(
     93       FROM_HERE, max_int64, 1, nullptr));
     94   EXPECT_FALSE(stream_utils::CheckInt64Overflow(
     95       FROM_HERE, max_uint64, 0, nullptr));
     96   EXPECT_FALSE(stream_utils::CheckInt64Overflow(
     97       FROM_HERE, max_uint64, max_int64, nullptr));
     98 }
     99 
    100 TEST(StreamUtils, CalculateStreamPosition) {
    101   using Whence = Stream::Whence;
    102   const uint64_t current_pos = 1234;
    103   const uint64_t end_pos = 2000;
    104   uint64_t pos = 0;
    105 
    106   EXPECT_TRUE(stream_utils::CalculateStreamPosition(
    107       FROM_HERE, 0, Whence::FROM_BEGIN, current_pos, end_pos, &pos, nullptr));
    108   EXPECT_EQ(0u, pos);
    109 
    110   EXPECT_TRUE(stream_utils::CalculateStreamPosition(
    111       FROM_HERE, 0, Whence::FROM_CURRENT, current_pos, end_pos, &pos, nullptr));
    112   EXPECT_EQ(current_pos, pos);
    113 
    114   EXPECT_TRUE(stream_utils::CalculateStreamPosition(
    115       FROM_HERE, 0, Whence::FROM_END, current_pos, end_pos, &pos, nullptr));
    116   EXPECT_EQ(end_pos, pos);
    117 
    118   EXPECT_TRUE(stream_utils::CalculateStreamPosition(
    119       FROM_HERE, 10, Whence::FROM_BEGIN, current_pos, end_pos, &pos, nullptr));
    120   EXPECT_EQ(10u, pos);
    121 
    122   EXPECT_TRUE(stream_utils::CalculateStreamPosition(
    123       FROM_HERE, 10, Whence::FROM_CURRENT, current_pos, end_pos, &pos,
    124       nullptr));
    125   EXPECT_EQ(current_pos + 10, pos);
    126 
    127   EXPECT_TRUE(stream_utils::CalculateStreamPosition(
    128       FROM_HERE, 10, Whence::FROM_END, current_pos, end_pos, &pos, nullptr));
    129   EXPECT_EQ(end_pos + 10, pos);
    130 
    131   EXPECT_TRUE(stream_utils::CalculateStreamPosition(
    132       FROM_HERE, -10, Whence::FROM_CURRENT, current_pos, end_pos, &pos,
    133       nullptr));
    134   EXPECT_EQ(current_pos - 10, pos);
    135 
    136   EXPECT_TRUE(stream_utils::CalculateStreamPosition(
    137       FROM_HERE, -10, Whence::FROM_END, current_pos, end_pos, &pos, nullptr));
    138   EXPECT_EQ(end_pos - 10, pos);
    139 
    140   ErrorPtr error;
    141   EXPECT_FALSE(stream_utils::CalculateStreamPosition(
    142       FROM_HERE, -1, Whence::FROM_BEGIN, current_pos, end_pos, &pos, &error));
    143   EXPECT_EQ(errors::stream::kInvalidParameter, error->GetCode());
    144   EXPECT_EQ("The stream offset value is out of range", error->GetMessage());
    145 
    146   EXPECT_FALSE(stream_utils::CalculateStreamPosition(
    147       FROM_HERE, -1001, Whence::FROM_CURRENT, 1000, end_pos, &pos, nullptr));
    148 
    149   const uint64_t max_int64 = std::numeric_limits<int64_t>::max();
    150   EXPECT_FALSE(stream_utils::CalculateStreamPosition(
    151       FROM_HERE, 1, Whence::FROM_CURRENT, max_int64, end_pos, &pos, nullptr));
    152 }
    153 
    154 class CopyStreamDataTest : public testing::Test {
    155  public:
    156   void SetUp() override {
    157     fake_loop_.SetAsCurrent();
    158     in_stream_.reset(new StrictMock<MockStream>{});
    159     out_stream_.reset(new StrictMock<MockStream>{});
    160   }
    161 
    162   FakeMessageLoop fake_loop_{nullptr};
    163   std::unique_ptr<StrictMock<MockStream>> in_stream_;
    164   std::unique_ptr<StrictMock<MockStream>> out_stream_;
    165   bool succeeded_{false};
    166   bool failed_{false};
    167 
    168   void OnSuccess(uint64_t expected,
    169                  StreamPtr /* in_stream */,
    170                  StreamPtr /* out_stream */,
    171                  uint64_t copied) {
    172     EXPECT_EQ(expected, copied);
    173     succeeded_ = true;
    174   }
    175 
    176   void OnError(const std::string& expected_error,
    177                StreamPtr /* in_stream */,
    178                StreamPtr /* out_stream */,
    179                const Error* error) {
    180     EXPECT_EQ(expected_error, error->GetCode());
    181     failed_ = true;
    182   }
    183 
    184   void ExpectSuccess() {
    185     EXPECT_TRUE(succeeded_);
    186     EXPECT_FALSE(failed_);
    187   }
    188 
    189   void ExpectFailure() {
    190     EXPECT_FALSE(succeeded_);
    191     EXPECT_TRUE(failed_);
    192   }
    193 };
    194 
    195 TEST_F(CopyStreamDataTest, CopyAllAtOnce) {
    196   {
    197     InSequence seq;
    198     EXPECT_CALL(*in_stream_, ReadAsync(_, 100, _, _, _))
    199         .WillOnce(InvokeAsyncCallback<2>(100));
    200     EXPECT_CALL(*out_stream_, WriteAllAsync(_, 100, _, _, _))
    201         .WillOnce(InvokeAsyncCallback<2>());
    202   }
    203   stream_utils::CopyData(
    204       std::move(in_stream_), std::move(out_stream_), 100, 4096,
    205       base::Bind(&CopyStreamDataTest::OnSuccess, base::Unretained(this), 100),
    206       base::Bind(&CopyStreamDataTest::OnError, base::Unretained(this), ""));
    207   fake_loop_.Run();
    208   ExpectSuccess();
    209 }
    210 
    211 TEST_F(CopyStreamDataTest, CopyInBlocks) {
    212   {
    213     InSequence seq;
    214     EXPECT_CALL(*in_stream_, ReadAsync(_, 100, _, _, _))
    215         .WillOnce(InvokeAsyncCallback<2>(60));
    216     EXPECT_CALL(*out_stream_, WriteAllAsync(_, 60, _, _, _))
    217         .WillOnce(InvokeAsyncCallback<2>());
    218     EXPECT_CALL(*in_stream_, ReadAsync(_, 40, _, _, _))
    219         .WillOnce(InvokeAsyncCallback<2>(40));
    220     EXPECT_CALL(*out_stream_, WriteAllAsync(_, 40, _, _, _))
    221         .WillOnce(InvokeAsyncCallback<2>());
    222   }
    223   stream_utils::CopyData(
    224       std::move(in_stream_), std::move(out_stream_), 100, 4096,
    225       base::Bind(&CopyStreamDataTest::OnSuccess, base::Unretained(this), 100),
    226       base::Bind(&CopyStreamDataTest::OnError, base::Unretained(this), ""));
    227   fake_loop_.Run();
    228   ExpectSuccess();
    229 }
    230 
    231 TEST_F(CopyStreamDataTest, CopyTillEndOfStream) {
    232   {
    233     InSequence seq;
    234     EXPECT_CALL(*in_stream_, ReadAsync(_, 100, _, _, _))
    235         .WillOnce(InvokeAsyncCallback<2>(60));
    236     EXPECT_CALL(*out_stream_, WriteAllAsync(_, 60, _, _, _))
    237         .WillOnce(InvokeAsyncCallback<2>());
    238     EXPECT_CALL(*in_stream_, ReadAsync(_, 40, _, _, _))
    239         .WillOnce(InvokeAsyncCallback<2>(0));
    240   }
    241   stream_utils::CopyData(
    242       std::move(in_stream_), std::move(out_stream_), 100, 4096,
    243       base::Bind(&CopyStreamDataTest::OnSuccess, base::Unretained(this), 60),
    244       base::Bind(&CopyStreamDataTest::OnError, base::Unretained(this), ""));
    245   fake_loop_.Run();
    246   ExpectSuccess();
    247 }
    248 
    249 TEST_F(CopyStreamDataTest, CopyInSmallBlocks) {
    250   {
    251     InSequence seq;
    252     EXPECT_CALL(*in_stream_, ReadAsync(_, 60, _, _, _))
    253         .WillOnce(InvokeAsyncCallback<2>(60));
    254     EXPECT_CALL(*out_stream_, WriteAllAsync(_, 60, _, _, _))
    255         .WillOnce(InvokeAsyncCallback<2>());
    256     EXPECT_CALL(*in_stream_, ReadAsync(_, 40, _, _, _))
    257         .WillOnce(InvokeAsyncCallback<2>(40));
    258     EXPECT_CALL(*out_stream_, WriteAllAsync(_, 40, _, _, _))
    259         .WillOnce(InvokeAsyncCallback<2>());
    260   }
    261   stream_utils::CopyData(
    262       std::move(in_stream_), std::move(out_stream_), 100, 60,
    263       base::Bind(&CopyStreamDataTest::OnSuccess, base::Unretained(this), 100),
    264       base::Bind(&CopyStreamDataTest::OnError, base::Unretained(this), ""));
    265   fake_loop_.Run();
    266   ExpectSuccess();
    267 }
    268 
    269 TEST_F(CopyStreamDataTest, ErrorRead) {
    270   {
    271     InSequence seq;
    272     EXPECT_CALL(*in_stream_, ReadAsync(_, 60, _, _, _))
    273         .WillOnce(InvokeAsyncErrorCallback<3>("read"));
    274   }
    275   stream_utils::CopyData(
    276       std::move(in_stream_), std::move(out_stream_), 100, 60,
    277       base::Bind(&CopyStreamDataTest::OnSuccess, base::Unretained(this), 0),
    278       base::Bind(&CopyStreamDataTest::OnError, base::Unretained(this), "read"));
    279   fake_loop_.Run();
    280   ExpectFailure();
    281 }
    282 
    283 TEST_F(CopyStreamDataTest, ErrorWrite) {
    284   {
    285     InSequence seq;
    286     EXPECT_CALL(*in_stream_, ReadAsync(_, 60, _, _, _))
    287         .WillOnce(InvokeAsyncCallback<2>(60));
    288     EXPECT_CALL(*out_stream_, WriteAllAsync(_, 60, _, _, _))
    289         .WillOnce(InvokeAsyncErrorCallback<3>("write"));
    290   }
    291   stream_utils::CopyData(
    292       std::move(in_stream_), std::move(out_stream_), 100, 60,
    293       base::Bind(&CopyStreamDataTest::OnSuccess, base::Unretained(this), 0),
    294       base::Bind(&CopyStreamDataTest::OnError, base::Unretained(this),
    295                  "write"));
    296   fake_loop_.Run();
    297   ExpectFailure();
    298 }
    299 
    300 }  // namespace brillo
    301