blob: b7059bc95cf3e2498928fdad69ea13d3a07f8adb [file] [log] [blame]
Amin Hassaniee6d9a12017-08-31 14:09:15 -07001//
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
35using chromeos_update_engine::test_utils::ExpectVectorsEq;
36using std::min;
37using std::string;
38using std::vector;
39
40namespace chromeos_update_engine {
41
42namespace {
43const size_t kBlockSize = 8;
44const size_t kRandomIterations = 1000;
45} // namespace
46
47class ExtentReaderTest : public ::testing::Test {
48 protected:
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 }
62 void TearDown() override { fd_->Close(); }
63
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 test_utils::ScopedTempFile temp_file_{"ExtentReaderTest-file.XXXXXX"};
76 brillo::Blob sample_;
77};
78
79TEST_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));
Amin Hassanid8b67f42017-12-06 13:47:52 -080084 brillo::Blob blob1(utils::BlocksInExtents(extents) * kBlockSize);
Amin Hassaniee6d9a12017-08-31 14:09:15 -070085 EXPECT_TRUE(reader.Read(blob1.data(), blob1.size()));
86 brillo::Blob blob2;
87 ReadExtents(extents, &blob2);
88 ExpectVectorsEq(blob1, blob2);
89}
90
91TEST_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
101TEST_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
110TEST_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));
Amin Hassanid8b67f42017-12-06 13:47:52 -0800115 brillo::Blob blob(utils::BlocksInExtents(extents) * kBlockSize + 1);
Amin Hassaniee6d9a12017-08-31 14:09:15 -0700116 EXPECT_FALSE(reader.Read(blob.data(), blob.size()));
117}
118
119TEST_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
127TEST_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
134TEST_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
143TEST_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
Amin Hassanid8b67f42017-12-06 13:47:52 -0800155 brillo::Blob blob(utils::BlocksInExtents(extents) * kBlockSize);
Amin Hassaniee6d9a12017-08-31 14:09:15 -0700156 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