blob: 70330a7fdd3f2ad812f1214ade659e6a9ba89d13 [file] [log] [blame]
Brad Bishope45d8c72022-05-25 15:12:53 -04001#include "fru_utils.hpp"
Patrick Venturea62466c2021-02-08 14:55:18 -08002
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +10303#include <algorithm>
Patrick Venturea62466c2021-02-08 14:55:18 -08004#include <array>
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +10305#include <iterator>
Patrick Venturea62466c2021-02-08 14:55:18 -08006
7#include "gtest/gtest.h"
8
9extern "C"
10{
11// Include for I2C_SMBUS_BLOCK_MAX
12#include <linux/i2c.h>
13}
14
Zev Weiss309c0b12022-02-25 01:44:12 +000015static constexpr size_t blockSize = I2C_SMBUS_BLOCK_MAX;
16
Patrick Venturea62466c2021-02-08 14:55:18 -080017TEST(ValidateHeaderTest, InvalidFruVersionReturnsFalse)
18{
19 // Validates the FruVersion is checked for the only legal value.
Ed Tanous07d467b2021-02-23 14:48:37 -080020 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
Patrick Venturea62466c2021-02-08 14:55:18 -080021 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
22
Ed Tanous07d467b2021-02-23 14:48:37 -080023 EXPECT_FALSE(validateHeader(fruHeader));
Patrick Venturea62466c2021-02-08 14:55:18 -080024}
Vijay Khemka1694ef62021-02-12 23:14:49 +000025
Vijay Khemka7a682a32021-04-12 22:15:00 +000026TEST(ValidateHeaderTest, InvalidReservedReturnsFalse)
27{
28 // Validates the reserved bit(7:4) of first bytes.
Ed Tanous07d467b2021-02-23 14:48:37 -080029 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
Vijay Khemka7a682a32021-04-12 22:15:00 +000030 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
31
Ed Tanous07d467b2021-02-23 14:48:37 -080032 EXPECT_FALSE(validateHeader(fruHeader));
Vijay Khemka7a682a32021-04-12 22:15:00 +000033}
34
35TEST(ValidateHeaderTest, InvalidPaddingReturnsFalse)
36{
37 // Validates the padding byte (7th byte).
Ed Tanous07d467b2021-02-23 14:48:37 -080038 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
Vijay Khemka7a682a32021-04-12 22:15:00 +000039 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00};
40
Ed Tanous07d467b2021-02-23 14:48:37 -080041 EXPECT_FALSE(validateHeader(fruHeader));
Vijay Khemka7a682a32021-04-12 22:15:00 +000042}
43
44TEST(ValidateHeaderTest, InvalidChecksumReturnsFalse)
45{
46 // Validates the checksum, check for incorrect value.
Ed Tanous07d467b2021-02-23 14:48:37 -080047 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
Vijay Khemka7a682a32021-04-12 22:15:00 +000048 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00};
49
Ed Tanous07d467b2021-02-23 14:48:37 -080050 EXPECT_FALSE(validateHeader(fruHeader));
Vijay Khemka7a682a32021-04-12 22:15:00 +000051}
52
53TEST(ValidateHeaderTest, ValidChecksumReturnsTrue)
54{
55 // Validates the checksum, check for correct value.
Ed Tanous07d467b2021-02-23 14:48:37 -080056 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
Vijay Khemka7a682a32021-04-12 22:15:00 +000057 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0xf5};
58
Ed Tanous07d467b2021-02-23 14:48:37 -080059 EXPECT_TRUE(validateHeader(fruHeader));
Vijay Khemka7a682a32021-04-12 22:15:00 +000060}
61
Vijay Khemka1694ef62021-02-12 23:14:49 +000062TEST(VerifyOffsetTest, EmptyFruDataReturnsFalse)
63{
64 // Validates the FruData size is checked for non empty.
Ed Tanous07d467b2021-02-23 14:48:37 -080065 std::vector<uint8_t> fruData = {};
Vijay Khemka1694ef62021-02-12 23:14:49 +000066
Ed Tanous07d467b2021-02-23 14:48:37 -080067 EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaChassis, 0));
Vijay Khemka1694ef62021-02-12 23:14:49 +000068}
69
70TEST(VerifyOffsetTest, AreaOutOfRangeReturnsFalse)
71{
72 // Validates the FruArea value, check if it is within range.
Ed Tanous07d467b2021-02-23 14:48:37 -080073 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00};
Vijay Khemka1694ef62021-02-12 23:14:49 +000075
76 unsigned int areaOutOfRange = 8;
77 EXPECT_FALSE(
Ed Tanous07d467b2021-02-23 14:48:37 -080078 verifyOffset(fruData, static_cast<fruAreas>(areaOutOfRange), 0));
Vijay Khemka1694ef62021-02-12 23:14:49 +000079}
80
81TEST(VerifyOffsetTest, OverlapNextAreaReturnsFalse)
82{
83 // Validates the Overlap of offsets with overlapped values.
Ed Tanous07d467b2021-02-23 14:48:37 -080084 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x02, 0x03,
85 0x04, 0x00, 0x00, 0x00};
Vijay Khemka1694ef62021-02-12 23:14:49 +000086
Ed Tanous07d467b2021-02-23 14:48:37 -080087 EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaChassis, 2));
Vijay Khemka1694ef62021-02-12 23:14:49 +000088}
89
90TEST(VerifyOffsetTest, OverlapPrevAreaReturnsFalse)
91{
92 // Validates the Overlap of offsets with overlapped values.
Ed Tanous07d467b2021-02-23 14:48:37 -080093 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x03, 0x02,
94 0x07, 0x00, 0x00, 0x00};
Vijay Khemka1694ef62021-02-12 23:14:49 +000095
Ed Tanous07d467b2021-02-23 14:48:37 -080096 EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaProduct, 2));
Vijay Khemka1694ef62021-02-12 23:14:49 +000097}
98
99TEST(VerifyOffsetTest, ValidInputDataNoOverlapReturnsTrue)
100{
101 // Validates all inputs with expected value and no overlap.
Ed Tanous07d467b2021-02-23 14:48:37 -0800102 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x02, 0x03,
103 0x04, 0x00, 0x00, 0x00};
Vijay Khemka1694ef62021-02-12 23:14:49 +0000104
Ed Tanous07d467b2021-02-23 14:48:37 -0800105 EXPECT_TRUE(verifyOffset(fruData, fruAreas::fruAreaChassis, 1));
Vijay Khemka1694ef62021-02-12 23:14:49 +0000106}
Andrew Jeffery8dacf6a2021-08-02 22:17:18 +0930107
108TEST(VerifyChecksumTest, EmptyInput)
109{
110 std::vector<uint8_t> data = {};
111
112 EXPECT_EQ(calculateChecksum(data), 0);
113}
114
115TEST(VerifyChecksumTest, SingleOneInput)
116{
117 std::vector<uint8_t> data(1, 1);
118
119 EXPECT_EQ(calculateChecksum(data), 255);
120}
121
122TEST(VerifyChecksumTest, AllOneInput)
123{
124 std::vector<uint8_t> data(256, 1);
125
126 EXPECT_EQ(calculateChecksum(data), 0);
127}
128
129TEST(VerifyChecksumTest, WrapBoundaryLow)
130{
Ed Tanousfbce8e22021-09-02 15:29:12 -0700131 std::vector<uint8_t> data = {255, 0};
Andrew Jeffery8dacf6a2021-08-02 22:17:18 +0930132
133 EXPECT_EQ(calculateChecksum(data), 1);
134}
135
136TEST(VerifyChecksumTest, WrapBoundaryExact)
137{
Ed Tanousfbce8e22021-09-02 15:29:12 -0700138 std::vector<uint8_t> data = {255, 1};
Andrew Jeffery8dacf6a2021-08-02 22:17:18 +0930139
140 EXPECT_EQ(calculateChecksum(data), 0);
141}
142
143TEST(VerifyChecksumTest, WrapBoundaryHigh)
144{
Ed Tanousfbce8e22021-09-02 15:29:12 -0700145 std::vector<uint8_t> data = {255, 2};
Andrew Jeffery8dacf6a2021-08-02 22:17:18 +0930146
147 EXPECT_EQ(calculateChecksum(data), 255);
148}
Oskar Senftbd4075f2021-10-05 23:42:43 -0400149
Zev Weiss309c0b12022-02-25 01:44:12 +0000150int64_t getDataTempl(const std::vector<uint8_t>& data, off_t offset,
Zev Weiss1525e852022-03-22 22:27:43 +0000151 size_t length, uint8_t* outBuf)
Oskar Senftbd4075f2021-10-05 23:42:43 -0400152{
Zev Weiss1525e852022-03-22 22:27:43 +0000153 if (offset >= static_cast<off_t>(data.size()))
Oskar Senftbd4075f2021-10-05 23:42:43 -0400154 {
155 return 0;
156 }
157
Ed Tanous3013fb42022-07-09 08:27:06 -0700158 uint16_t idx = offset;
159 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
160 for (; idx < std::min(data.size(), offset + length); ++idx, ++outBuf)
Oskar Senftbd4075f2021-10-05 23:42:43 -0400161 {
162 *outBuf = data[idx];
163 }
164
165 return idx - offset;
166}
167
Zev Weiss309c0b12022-02-25 01:44:12 +0000168TEST(FRUReaderTest, ReadData)
169{
170 std::vector<uint8_t> data = {};
Patrick Williams849f13a2024-12-18 15:43:19 -0500171 data.reserve(blockSize * 2);
Zev Weiss309c0b12022-02-25 01:44:12 +0000172 for (size_t i = 0; i < blockSize * 2; i++)
173 {
174 data.push_back(i);
175 }
Ed Tanous3013fb42022-07-09 08:27:06 -0700176 std::array<uint8_t, blockSize * 2> rdbuf{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000177 auto getData = [&data](auto o, auto l, auto* b) {
178 return getDataTempl(data, o, l, b);
179 };
180 FRUReader reader(getData);
181
182 EXPECT_EQ(reader.read(0, data.size(), rdbuf.data()),
183 static_cast<ssize_t>(data.size()));
184 EXPECT_TRUE(std::equal(rdbuf.begin(), rdbuf.end(), data.begin()));
185 for (size_t i = 0; i < blockSize * 2; i++)
186 {
187 EXPECT_EQ(reader.read(i, 1, rdbuf.data()), 1);
188 EXPECT_EQ(rdbuf[i], i);
189 }
190 EXPECT_EQ(reader.read(blockSize - 1, 2, rdbuf.data()), 2);
191 EXPECT_EQ(rdbuf[0], blockSize - 1);
192 EXPECT_EQ(rdbuf[1], blockSize);
193}
194
195TEST(FRUReaderTest, StartPastUnknownEOF)
196{
197 const std::vector<uint8_t> data = {};
198 auto getData = [&data](auto o, auto l, auto* b) {
199 return getDataTempl(data, o, l, b);
200 };
201 FRUReader reader(getData);
202
203 EXPECT_EQ(reader.read(1, 1, nullptr), 0);
204}
205
206TEST(FRUReaderTest, StartPastKnownEOF)
207{
208 std::vector<uint8_t> data = {};
209 data.resize(blockSize / 2);
Ed Tanous3013fb42022-07-09 08:27:06 -0700210 std::array<uint8_t, blockSize> blockData{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000211 auto getData = [&data](auto o, auto l, auto* b) {
212 return getDataTempl(data, o, l, b);
213 };
214 FRUReader reader(getData);
215
216 EXPECT_EQ(reader.read(0, blockSize, blockData.data()),
217 static_cast<ssize_t>(data.size()));
218 EXPECT_EQ(reader.read(data.size(), 1, nullptr), 0);
219 EXPECT_EQ(reader.read(data.size() + 1, 1, nullptr), 0);
220 EXPECT_EQ(reader.read(blockSize, 1, nullptr), 0);
221 EXPECT_EQ(reader.read(blockSize + 1, 1, nullptr), 0);
222}
223
224TEST(FRUReaderTest, DecreasingEOF)
225{
226 const std::vector<uint8_t> data = {};
227 auto getData = [&data](auto o, auto l, auto* b) {
228 return getDataTempl(data, o, l, b);
229 };
230 FRUReader reader(getData);
231
232 EXPECT_EQ(reader.read(blockSize * 2, 1, nullptr), 0);
233 EXPECT_EQ(reader.read(blockSize + (blockSize / 2), 1, nullptr), 0);
234 EXPECT_EQ(reader.read(blockSize, 1, nullptr), 0);
235 EXPECT_EQ(reader.read(blockSize / 2, 1, nullptr), 0);
236 EXPECT_EQ(reader.read(0, 1, nullptr), 0);
237}
238
239TEST(FRUReaderTest, CacheHit)
240{
241 std::vector<uint8_t> data = {'X'};
Ed Tanous3013fb42022-07-09 08:27:06 -0700242 std::array<uint8_t, blockSize> read1{};
243 std::array<uint8_t, blockSize> read2{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000244 auto getData = [&data](auto o, auto l, auto* b) {
245 return getDataTempl(data, o, l, b);
246 };
247 FRUReader reader(getData);
248
249 // cache hit should return the same data for the second read even if we
250 // change it behind the FRUReader's back after the first
251 EXPECT_EQ(reader.read(0, blockSize, read1.data()), 1);
252 data[0] = 'Y';
253 EXPECT_EQ(reader.read(0, blockSize, read2.data()), 1);
254 EXPECT_EQ(read1[0], read2[0]);
255}
256
257TEST(FRUReaderTest, ReadPastKnownEnd)
258{
259 const std::vector<uint8_t> data = {'X', 'Y'};
Ed Tanous3013fb42022-07-09 08:27:06 -0700260 std::array<uint8_t, blockSize> rdbuf{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000261 auto getData = [&data](auto o, auto l, auto* b) {
262 return getDataTempl(data, o, l, b);
263 };
264 FRUReader reader(getData);
265
266 EXPECT_EQ(reader.read(0, data.size(), rdbuf.data()),
267 static_cast<ssize_t>(data.size()));
268 EXPECT_EQ(rdbuf[0], 'X');
269 EXPECT_EQ(rdbuf[1], 'Y');
270 EXPECT_EQ(reader.read(1, data.size(), rdbuf.data()),
271 static_cast<ssize_t>(data.size() - 1));
272 EXPECT_EQ(rdbuf[0], 'Y');
273}
274
275TEST(FRUReaderTest, MultiBlockRead)
276{
277 std::vector<uint8_t> data = {};
278 data.resize(blockSize, 'X');
279 data.resize(2 * blockSize, 'Y');
Ed Tanous3013fb42022-07-09 08:27:06 -0700280 std::array<uint8_t, 2 * blockSize> rdbuf{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000281 auto getData = [&data](auto o, auto l, auto* b) {
282 return getDataTempl(data, o, l, b);
283 };
284 FRUReader reader(getData);
285
286 EXPECT_EQ(reader.read(0, 2 * blockSize, rdbuf.data()),
287 static_cast<ssize_t>(2 * blockSize));
288 EXPECT_TRUE(std::equal(rdbuf.begin(), rdbuf.end(), data.begin()));
289}
290
291TEST(FRUReaderTest, ShrinkingEEPROM)
292{
293 std::vector<uint8_t> data = {};
294 data.resize(3 * blockSize, 'X');
Ed Tanous3013fb42022-07-09 08:27:06 -0700295 std::array<uint8_t, blockSize> rdbuf{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000296 auto getData = [&data](auto o, auto l, auto* b) {
297 return getDataTempl(data, o, l, b);
298 };
299 FRUReader reader(getData);
300
301 EXPECT_EQ(reader.read(data.size() - 1, 2, rdbuf.data()), 1);
302 data.resize(blockSize);
303 EXPECT_EQ(reader.read(data.size() - 1, 2, rdbuf.data()), 1);
304}
305
Oskar Senftbd4075f2021-10-05 23:42:43 -0400306TEST(FindFRUHeaderTest, InvalidHeader)
307{
308 const std::vector<uint8_t> data = {255, 16};
Zev Weiss1525e852022-03-22 22:27:43 +0000309 off_t offset = 0;
Ed Tanous3013fb42022-07-09 08:27:06 -0700310 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000311 auto getData = [&data](auto o, auto l, auto* b) {
312 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030313 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000314 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400315
Zev Weiss309c0b12022-02-25 01:44:12 +0000316 EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400317}
318
319TEST(FindFRUHeaderTest, NoData)
320{
321 const std::vector<uint8_t> data = {};
Zev Weiss1525e852022-03-22 22:27:43 +0000322 off_t offset = 0;
Ed Tanous3013fb42022-07-09 08:27:06 -0700323 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000324 auto getData = [&data](auto o, auto l, auto* b) {
325 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030326 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000327 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400328
Zev Weiss309c0b12022-02-25 01:44:12 +0000329 EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400330}
331
332TEST(FindFRUHeaderTest, ValidHeader)
333{
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030334 const std::vector<uint8_t> data = {0x01, 0x00, 0x01, 0x02,
335 0x03, 0x04, 0x00, 0xf5};
Zev Weiss1525e852022-03-22 22:27:43 +0000336 off_t offset = 0;
Ed Tanous3013fb42022-07-09 08:27:06 -0700337 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000338 auto getData = [&data](auto o, auto l, auto* b) {
339 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030340 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000341 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400342
Zev Weiss309c0b12022-02-25 01:44:12 +0000343 EXPECT_TRUE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400344 EXPECT_EQ(0, offset);
345}
346
347TEST(FindFRUHeaderTest, TyanInvalidHeader)
348{
349 std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0};
350 data.resize(0x6000 + I2C_SMBUS_BLOCK_MAX);
Zev Weiss1525e852022-03-22 22:27:43 +0000351 off_t offset = 0;
Ed Tanous3013fb42022-07-09 08:27:06 -0700352 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000353 auto getData = [&data](auto o, auto l, auto* b) {
354 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030355 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000356 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400357
Zev Weiss309c0b12022-02-25 01:44:12 +0000358 EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400359}
360
361TEST(FindFRUHeaderTest, TyanNoData)
362{
363 const std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0};
Zev Weiss1525e852022-03-22 22:27:43 +0000364 off_t offset = 0;
Ed Tanous3013fb42022-07-09 08:27:06 -0700365 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000366 auto getData = [&data](auto o, auto l, auto* b) {
367 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030368 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000369 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400370
Zev Weiss309c0b12022-02-25 01:44:12 +0000371 EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400372}
373
374TEST(FindFRUHeaderTest, TyanValidHeader)
375{
376 std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0};
377 data.resize(0x6000);
378 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
379 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0xf5};
380 copy(fruHeader.begin(), fruHeader.end(), back_inserter(data));
381
Zev Weiss1525e852022-03-22 22:27:43 +0000382 off_t offset = 0;
Ed Tanous3013fb42022-07-09 08:27:06 -0700383 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData{};
Zev Weiss309c0b12022-02-25 01:44:12 +0000384 auto getData = [&data](auto o, auto l, auto* b) {
385 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030386 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000387 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400388
Zev Weiss309c0b12022-02-25 01:44:12 +0000389 EXPECT_TRUE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400390 EXPECT_EQ(0x6000, offset);
391}