1 //
2 // Copyright (C) 2017 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "update_engine/payload_consumer/extent_reader.h"
18
19 #include <fcntl.h>
20
21 #include <algorithm>
22 #include <string>
23 #include <vector>
24
25 #include <brillo/secure_blob.h>
26 #include <gtest/gtest.h>
27
28 #include "update_engine/common/test_utils.h"
29 #include "update_engine/common/utils.h"
30 #include "update_engine/payload_consumer/file_descriptor.h"
31 #include "update_engine/payload_consumer/payload_constants.h"
32 #include "update_engine/payload_generator/extent_ranges.h"
33 #include "update_engine/payload_generator/extent_utils.h"
34
35 using chromeos_update_engine::test_utils::ExpectVectorsEq;
36 using std::min;
37 using std::string;
38 using std::vector;
39
40 namespace chromeos_update_engine {
41
42 namespace {
43 const size_t kBlockSize = 8;
44 const size_t kRandomIterations = 1000;
45 } // namespace
46
47 class ExtentReaderTest : public ::testing::Test {
48 protected:
SetUp()49 void SetUp() override {
50 sample_.resize(4096 * 10);
51 srand(time(nullptr));
52 unsigned int rand_seed;
53 for (size_t i = 0; i < sample_.size(); i++) {
54 sample_[i] = rand_r(&rand_seed) % 256;
55 }
56 ASSERT_TRUE(utils::WriteFile(
57 temp_file_.path().c_str(), sample_.data(), sample_.size()));
58
59 fd_.reset(new EintrSafeFileDescriptor());
60 ASSERT_TRUE(fd_->Open(temp_file_.path().c_str(), O_RDONLY, 0600));
61 }
TearDown()62 void TearDown() override { fd_->Close(); }
63
ReadExtents(vector<Extent> extents,brillo::Blob * blob)64 void ReadExtents(vector<Extent> extents, brillo::Blob* blob) {
65 blob->clear();
66 for (const auto& extent : extents) {
67 blob->insert(
68 blob->end(),
69 &sample_[extent.start_block() * kBlockSize],
70 &sample_[(extent.start_block() + extent.num_blocks()) * kBlockSize]);
71 }
72 }
73
74 FileDescriptorPtr fd_;
75 ScopedTempFile temp_file_{"ExtentReaderTest-file.XXXXXX"};
76 brillo::Blob sample_;
77 };
78
TEST_F(ExtentReaderTest,SimpleTest)79 TEST_F(ExtentReaderTest, SimpleTest) {
80 vector<Extent> extents = {ExtentForRange(1, 1)};
81 DirectExtentReader reader;
82 EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
83 EXPECT_TRUE(reader.Seek(0));
84 brillo::Blob blob1(utils::BlocksInExtents(extents) * kBlockSize);
85 EXPECT_TRUE(reader.Read(blob1.data(), blob1.size()));
86 brillo::Blob blob2;
87 ReadExtents(extents, &blob2);
88 ExpectVectorsEq(blob1, blob2);
89 }
90
TEST_F(ExtentReaderTest,ZeroExtentLengthTest)91 TEST_F(ExtentReaderTest, ZeroExtentLengthTest) {
92 vector<Extent> extents = {ExtentForRange(1, 0)};
93 DirectExtentReader reader;
94 EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
95 EXPECT_TRUE(reader.Seek(0));
96 brillo::Blob blob(1);
97 EXPECT_TRUE(reader.Read(blob.data(), 0));
98 EXPECT_FALSE(reader.Read(blob.data(), 1));
99 }
100
TEST_F(ExtentReaderTest,NoExtentTest)101 TEST_F(ExtentReaderTest, NoExtentTest) {
102 DirectExtentReader reader;
103 EXPECT_TRUE(reader.Init(fd_, {}, kBlockSize));
104 EXPECT_TRUE(reader.Seek(0));
105 brillo::Blob blob(1);
106 EXPECT_TRUE(reader.Read(blob.data(), 0));
107 EXPECT_FALSE(reader.Read(blob.data(), 1));
108 }
109
TEST_F(ExtentReaderTest,OverflowExtentTest)110 TEST_F(ExtentReaderTest, OverflowExtentTest) {
111 vector<Extent> extents = {ExtentForRange(1, 1)};
112 DirectExtentReader reader;
113 EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
114 EXPECT_TRUE(reader.Seek(0));
115 brillo::Blob blob(utils::BlocksInExtents(extents) * kBlockSize + 1);
116 EXPECT_FALSE(reader.Read(blob.data(), blob.size()));
117 }
118
TEST_F(ExtentReaderTest,SeekOverflow1Test)119 TEST_F(ExtentReaderTest, SeekOverflow1Test) {
120 vector<Extent> extents = {ExtentForRange(1, 0)};
121 DirectExtentReader reader;
122 EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
123 EXPECT_TRUE(reader.Seek(0));
124 EXPECT_FALSE(reader.Seek(1));
125 }
126
TEST_F(ExtentReaderTest,SeekOverflow2Test)127 TEST_F(ExtentReaderTest, SeekOverflow2Test) {
128 DirectExtentReader reader;
129 reader.Init(fd_, {}, kBlockSize);
130 EXPECT_TRUE(reader.Seek(0));
131 EXPECT_FALSE(reader.Seek(1));
132 }
133
TEST_F(ExtentReaderTest,SeekOverflow3Test)134 TEST_F(ExtentReaderTest, SeekOverflow3Test) {
135 vector<Extent> extents = {ExtentForRange(1, 1)};
136 DirectExtentReader reader;
137 EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
138 // Seek to the end of the extents should be fine as long as nothing is read.
139 EXPECT_TRUE(reader.Seek(kBlockSize));
140 EXPECT_FALSE(reader.Seek(kBlockSize + 1));
141 }
142
TEST_F(ExtentReaderTest,RandomReadTest)143 TEST_F(ExtentReaderTest, RandomReadTest) {
144 vector<Extent> extents = {ExtentForRange(0, 0),
145 ExtentForRange(1, 1),
146 ExtentForRange(3, 0),
147 ExtentForRange(4, 2),
148 ExtentForRange(7, 1)};
149 DirectExtentReader reader;
150 EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
151
152 brillo::Blob result;
153 ReadExtents(extents, &result);
154
155 brillo::Blob blob(utils::BlocksInExtents(extents) * kBlockSize);
156 srand(time(nullptr));
157 uint32_t rand_seed;
158 for (size_t idx = 0; idx < kRandomIterations; idx++) {
159 // zero to full size available.
160 size_t start = rand_r(&rand_seed) % blob.size();
161 size_t size = rand_r(&rand_seed) % (blob.size() - start);
162 EXPECT_TRUE(reader.Seek(start));
163 EXPECT_TRUE(reader.Read(blob.data(), size));
164 for (size_t i = 0; i < size; i++) {
165 ASSERT_EQ(blob[i], result[start + i]);
166 }
167 }
168 }
169
170 } // namespace chromeos_update_engine
171