1 // Copyright 2018 The Fuchsia 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 <lib/fzl/owned-vmo-mapper.h>
6 #include <lib/inspect/block.h>
7 #include <lib/inspect/snapshot.h>
8 #include <unittest/unittest.h>
9
10 namespace {
11
12 using inspect::BlockType;
13 using inspect::Snapshot;
14 using inspect::internal::Block;
15 using inspect::internal::HeaderBlockFields;
16
ValidRead()17 bool ValidRead() {
18 BEGIN_TEST;
19
20 fzl::OwnedVmoMapper vmo;
21 ASSERT_EQ(ZX_OK, vmo.CreateAndMap(4096, "test"));
22 memset(vmo.start(), 'a', 4096);
23 Block* header = reinterpret_cast<Block*>(vmo.start());
24 header->header = HeaderBlockFields::Order::Make(0) |
25 HeaderBlockFields::Type::Make(BlockType::kHeader) |
26 HeaderBlockFields::Version::Make(0);
27 memcpy(&header->header_data[4], inspect::kMagicNumber, 4);
28 header->payload.u64 = 0;
29
30 zx::vmo dup;
31 ASSERT_EQ(ZX_OK, vmo.vmo().duplicate(ZX_RIGHT_SAME_RIGHTS, &dup));
32 Snapshot snapshot;
33 zx_status_t status = Snapshot::Create(std::move(dup), &snapshot);
34
35 EXPECT_EQ(ZX_OK, status);
36 EXPECT_EQ(4096, snapshot.size());
37
38 // Make sure that the data was actually fully copied to the snapshot.
39 uint8_t buf[snapshot.size() - sizeof(Block)];
40 memset(buf, 'a', snapshot.size() - sizeof(Block));
41 EXPECT_EQ(0, memcmp(snapshot.data() + sizeof(Block), buf, snapshot.size() - sizeof(Block)));
42
43 END_TEST;
44 }
45
InvalidWritePending()46 bool InvalidWritePending() {
47 BEGIN_TEST;
48
49 fzl::OwnedVmoMapper vmo;
50 ASSERT_EQ(ZX_OK, vmo.CreateAndMap(4096, "test"));
51 Block* header = reinterpret_cast<Block*>(vmo.start());
52 header->header = HeaderBlockFields::Order::Make(0) |
53 HeaderBlockFields::Type::Make(BlockType::kHeader) |
54 HeaderBlockFields::Version::Make(0);
55 memcpy(&header->header_data[4], inspect::kMagicNumber, 4);
56 header->payload.u64 = 1;
57
58 zx::vmo dup;
59 ASSERT_EQ(ZX_OK, vmo.vmo().duplicate(ZX_RIGHT_SAME_RIGHTS, &dup));
60 Snapshot snapshot;
61 zx_status_t status = Snapshot::Create(std::move(dup), &snapshot);
62
63 EXPECT_EQ(ZX_ERR_INTERNAL, status);
64 EXPECT_FALSE(snapshot);
65
66 END_TEST;
67 }
68
ValidPendingSkipCheck()69 bool ValidPendingSkipCheck() {
70 BEGIN_TEST;
71
72 fzl::OwnedVmoMapper vmo;
73 ASSERT_EQ(ZX_OK, vmo.CreateAndMap(4096, "test"));
74 Block* header = reinterpret_cast<Block*>(vmo.start());
75 header->header = HeaderBlockFields::Order::Make(0) |
76 HeaderBlockFields::Type::Make(BlockType::kHeader) |
77 HeaderBlockFields::Version::Make(0);
78 memcpy(&header->header_data[4], inspect::kMagicNumber, 4);
79 header->payload.u64 = 1;
80
81 zx::vmo dup;
82 ASSERT_EQ(ZX_OK, vmo.vmo().duplicate(ZX_RIGHT_SAME_RIGHTS, &dup));
83 Snapshot snapshot;
84 zx_status_t status = Snapshot::Create(
85 std::move(dup), {.read_attempts = 100, .skip_consistency_check = true}, &snapshot);
86 EXPECT_EQ(ZX_OK, status);
87 EXPECT_EQ(4096, snapshot.size());
88
89 END_TEST;
90 }
91
InvalidGenerationChange()92 bool InvalidGenerationChange() {
93 BEGIN_TEST;
94
95 fzl::OwnedVmoMapper vmo;
96 ASSERT_EQ(ZX_OK, vmo.CreateAndMap(4096, "test"));
97 Block* header = reinterpret_cast<Block*>(vmo.start());
98 header->header = HeaderBlockFields::Order::Make(0) |
99 HeaderBlockFields::Type::Make(BlockType::kHeader) |
100 HeaderBlockFields::Version::Make(0);
101 memcpy(&header->header_data[4], inspect::kMagicNumber, 4);
102 header->payload.u64 = 0;
103
104 zx::vmo dup;
105 ASSERT_EQ(ZX_OK, vmo.vmo().duplicate(ZX_RIGHT_SAME_RIGHTS, &dup));
106 Snapshot snapshot;
107 zx_status_t status = Snapshot::Create(
108 std::move(dup), Snapshot::kDefaultOptions,
109 [header] (uint8_t* buffer, size_t buffer_size) { header->payload.u64 += 2; }, &snapshot);
110
111 EXPECT_EQ(ZX_ERR_INTERNAL, status);
112
113 END_TEST;
114 }
115
ValidGenerationChangeSkipCheck()116 bool ValidGenerationChangeSkipCheck() {
117 BEGIN_TEST;
118
119 fzl::OwnedVmoMapper vmo;
120 ASSERT_EQ(ZX_OK, vmo.CreateAndMap(4096, "test"));
121 Block* header = reinterpret_cast<Block*>(vmo.start());
122 header->header = HeaderBlockFields::Order::Make(0) |
123 HeaderBlockFields::Type::Make(BlockType::kHeader) |
124 HeaderBlockFields::Version::Make(0);
125 memcpy(&header->header_data[4], inspect::kMagicNumber, 4);
126 header->payload.u64 = 0;
127
128 zx::vmo dup;
129 ASSERT_EQ(ZX_OK, vmo.vmo().duplicate(ZX_RIGHT_SAME_RIGHTS, &dup));
130 Snapshot snapshot;
131 zx_status_t status = Snapshot::Create(
132 std::move(dup), {.read_attempts = 100, .skip_consistency_check = true},
133 [header] (uint8_t* buffer, size_t buffer_size) { header->payload.u64 += 2; }, &snapshot);
134
135 EXPECT_EQ(ZX_OK, status);
136 EXPECT_EQ(4096, snapshot.size());
137
138 END_TEST;
139 }
140
InvalidBadMagicNumber()141 bool InvalidBadMagicNumber() {
142 BEGIN_TEST;
143
144 fzl::OwnedVmoMapper vmo;
145 ASSERT_EQ(ZX_OK, vmo.CreateAndMap(4096, "test"));
146 Block* header = reinterpret_cast<Block*>(vmo.start());
147 header->header = HeaderBlockFields::Order::Make(0) |
148 HeaderBlockFields::Type::Make(BlockType::kHeader) |
149 HeaderBlockFields::Version::Make(0);
150 header->payload.u64 = 0;
151
152 zx::vmo dup;
153 ASSERT_EQ(ZX_OK, vmo.vmo().duplicate(ZX_RIGHT_SAME_RIGHTS, &dup));
154 Snapshot snapshot;
155 zx_status_t status = Snapshot::Create(std::move(dup), &snapshot);
156
157 EXPECT_EQ(ZX_ERR_INTERNAL, status);
158
159 END_TEST;
160 }
161
InvalidBadMagicNumberSkipCheck()162 bool InvalidBadMagicNumberSkipCheck() {
163 BEGIN_TEST;
164
165 fzl::OwnedVmoMapper vmo;
166 ASSERT_EQ(ZX_OK, vmo.CreateAndMap(4096, "test"));
167 Block* header = reinterpret_cast<Block*>(vmo.start());
168 header->header = HeaderBlockFields::Order::Make(0) |
169 HeaderBlockFields::Type::Make(BlockType::kHeader) |
170 HeaderBlockFields::Version::Make(0);
171 header->payload.u64 = 0;
172
173 zx::vmo dup;
174 ASSERT_EQ(ZX_OK, vmo.vmo().duplicate(ZX_RIGHT_SAME_RIGHTS, &dup));
175 Snapshot snapshot;
176 zx_status_t status = Snapshot::Create(
177 std::move(dup), {.read_attempts = 100, .skip_consistency_check = true}, &snapshot);
178
179 EXPECT_EQ(ZX_ERR_INTERNAL, status);
180
181 END_TEST;
182 }
183
184 } // namespace
185
186 BEGIN_TEST_CASE(SnapshotTests)
187 RUN_TEST(ValidRead)
188 RUN_TEST(InvalidWritePending)
189 RUN_TEST(ValidPendingSkipCheck)
190 RUN_TEST(InvalidGenerationChange)
191 RUN_TEST(ValidGenerationChangeSkipCheck)
192 RUN_TEST(InvalidBadMagicNumber)
193 RUN_TEST(InvalidBadMagicNumberSkipCheck)
194 END_TEST_CASE(SnapshotTests)
195