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