Yifan Hong | e71fe24 | 2021-02-22 15:00:15 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2021 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 <string.h> |
| 18 | #include <sys/stat.h> |
| 19 | #include <sys/types.h> |
| 20 | #include <unistd.h> |
| 21 | |
| 22 | #include <filesystem> |
| 23 | #include <optional> |
| 24 | #include <string_view> |
| 25 | |
| 26 | #include <android-base/file.h> |
| 27 | #include <android-base/logging.h> |
| 28 | #include <android-base/result.h> |
| 29 | #include <android-base/strings.h> |
| 30 | #include <bootimg.h> |
| 31 | #include <gmock/gmock.h> |
| 32 | #include <gtest/gtest.h> |
| 33 | #include <libavb/libavb.h> |
| 34 | |
| 35 | #include "vendor_boot_img_utils.h" |
| 36 | |
| 37 | using android::base::borrowed_fd; |
| 38 | using android::base::ErrnoError; |
| 39 | using android::base::GetExecutableDirectory; |
| 40 | using android::base::ReadFdToString; |
| 41 | using android::base::Result; |
| 42 | using testing::AllOf; |
| 43 | using testing::Each; |
| 44 | using testing::Eq; |
| 45 | using testing::HasSubstr; |
| 46 | using testing::Not; |
| 47 | using testing::Property; |
| 48 | using std::string_literals::operator""s; |
| 49 | |
| 50 | // Expect that the Result<T> returned by |expr| is successful, and value matches |result_matcher|. |
| 51 | #define EXPECT_RESULT(expr, result_matcher) \ |
| 52 | EXPECT_THAT(expr, AllOf(Property(&decltype(expr)::ok, Eq(true)), \ |
| 53 | Property(&decltype(expr)::value, result_matcher))) |
| 54 | |
| 55 | // Expect that the Result<T> returned by |expr| fails, and error message matches |error_matcher|. |
| 56 | #define EXPECT_ERROR(expr, error_matcher) \ |
| 57 | do { \ |
| 58 | EXPECT_THAT( \ |
| 59 | expr, \ |
| 60 | AllOf(Property(&decltype(expr)::ok, Eq(false)), \ |
| 61 | Property(&decltype(expr)::error, \ |
| 62 | Property(&decltype(expr)::error_type::message, error_matcher)))); \ |
| 63 | } while (0) |
| 64 | |
| 65 | namespace { |
| 66 | |
| 67 | // Wrapper of fstat. |
| 68 | Result<uint64_t> FileSize(borrowed_fd fd, std::filesystem::path path) { |
| 69 | struct stat sb; |
| 70 | if (fstat(fd.get(), &sb) == -1) return ErrnoError() << "fstat(" << path << ")"; |
| 71 | return sb.st_size; |
| 72 | } |
| 73 | |
| 74 | // Seek to beginning then read the whole file. |
| 75 | Result<std::string> ReadStartOfFdToString(borrowed_fd fd, std::filesystem::path path) { |
| 76 | if (lseek64(fd.get(), 0, SEEK_SET) != 0) |
| 77 | return ErrnoError() << "lseek64(" << path << ", 0, SEEK_SET)"; |
| 78 | std::string content; |
| 79 | if (!android::base::ReadFdToString(fd, &content)) return ErrnoError() << "read(" << path << ")"; |
| 80 | return content; |
| 81 | } |
| 82 | |
| 83 | // Round |value| up to page boundary. |
| 84 | inline uint32_t round_up(uint32_t value, uint32_t page_size) { |
| 85 | return (value + page_size - 1) / page_size * page_size; |
| 86 | } |
| 87 | |
| 88 | // Match is successful if |arg| is a zero-padded version of |expected|. |
| 89 | MATCHER_P(IsPadded, expected, (negation ? "is" : "isn't") + " zero-padded of expected value"s) { |
| 90 | if (arg.size() < expected.size()) return false; |
| 91 | if (0 != memcmp(arg.data(), expected.data(), expected.size())) return false; |
| 92 | auto remainder = std::string_view(arg).substr(expected.size()); |
| 93 | for (char e : remainder) |
| 94 | if (e != '\0') return false; |
| 95 | return true; |
| 96 | } |
| 97 | |
| 98 | // Same as Eq, but don't print the content to avoid spam. |
| 99 | MATCHER_P(MemEq, expected, (negation ? "is" : "isn't") + " expected value"s) { |
| 100 | if (arg.size() != expected.size()) return false; |
| 101 | return 0 == memcmp(arg.data(), expected.data(), expected.size()); |
| 102 | } |
| 103 | |
| 104 | // Expect that |arg| and |expected| has the same AVB footer. |
| 105 | MATCHER_P(HasSameAvbFooter, expected, |
| 106 | (negation ? "has" : "does not have") + "expected AVB footer"s) { |
| 107 | if (expected.size() < AVB_FOOTER_SIZE || arg.size() < AVB_FOOTER_SIZE) return false; |
| 108 | return std::string_view(expected).substr(expected.size() - AVB_FOOTER_SIZE) == |
| 109 | std::string_view(arg).substr(arg.size() - AVB_FOOTER_SIZE); |
| 110 | } |
| 111 | |
| 112 | // A lazy handle of a file. |
| 113 | struct TestFileHandle { |
| 114 | virtual ~TestFileHandle() = default; |
| 115 | // Lazily call OpenImpl(), cache result in open_result_. |
| 116 | android::base::Result<void> Open() { |
| 117 | if (!open_result_.has_value()) open_result_ = OpenImpl(); |
| 118 | return open_result_.value(); |
| 119 | } |
| 120 | // The original size at the time when the file is opened. If the file has been modified, |
| 121 | // this field is NOT updated. |
| 122 | uint64_t size() { |
| 123 | CHECK(open_result_.has_value()); |
| 124 | return size_; |
| 125 | } |
| 126 | // The current size of the file. If the file has been modified since opened, |
| 127 | // this is updated. |
| 128 | Result<uint64_t> fsize() { |
| 129 | CHECK(open_result_.has_value()); |
| 130 | return FileSize(fd_, abs_path_); |
| 131 | } |
| 132 | borrowed_fd fd() { |
| 133 | CHECK(open_result_.has_value()); |
| 134 | return fd_; |
| 135 | } |
| 136 | Result<std::string> Read() { |
| 137 | CHECK(open_result_.has_value()); |
| 138 | return ReadStartOfFdToString(fd_, abs_path_); |
| 139 | } |
| 140 | |
| 141 | private: |
| 142 | std::filesystem::path abs_path_; |
| 143 | uint64_t size_; |
| 144 | std::optional<android::base::Result<void>> open_result_; |
| 145 | borrowed_fd fd_{-1}; |
| 146 | // Opens |rel_path_| as a readonly fd, pass it to Transform, and store result to |
| 147 | // |borrowed_fd_|. |
| 148 | android::base::Result<void> OpenImpl() { |
| 149 | android::base::unique_fd read_fd(TEMP_FAILURE_RETRY( |
| 150 | open(abs_path_.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_BINARY))); |
| 151 | if (!read_fd.ok()) return ErrnoError() << "open(" << abs_path_ << ")"; |
| 152 | auto size = FileSize(read_fd, abs_path_); |
| 153 | if (!size.ok()) return size.error(); |
| 154 | size_ = *size; |
| 155 | |
| 156 | auto borrowed_fd = Transform(abs_path_, std::move(read_fd)); |
| 157 | if (!borrowed_fd.ok()) return borrowed_fd.error(); |
| 158 | fd_ = borrowed_fd.value(); |
| 159 | |
| 160 | return {}; |
| 161 | } |
| 162 | |
| 163 | protected: |
| 164 | // |rel_path| is the relative path under test data directory. |
| 165 | TestFileHandle(const std::filesystem::path& rel_path) |
| 166 | : abs_path_(std::move(std::filesystem::path(GetExecutableDirectory()) / rel_path)) {} |
| 167 | // Given |read_fd|, the readonly fd on the test file, return an fd that's suitable for client |
| 168 | // to use. Implementation is responsible for managing the lifetime of the returned fd. |
| 169 | virtual android::base::Result<borrowed_fd> Transform(const std::filesystem::path& abs_path, |
| 170 | android::base::unique_fd read_fd) = 0; |
| 171 | }; |
| 172 | |
| 173 | // A TestFileHandle where the file is readonly. |
| 174 | struct ReadOnlyTestFileHandle : TestFileHandle { |
| 175 | ReadOnlyTestFileHandle(const std::filesystem::path& rel_path) : TestFileHandle(rel_path) {} |
| 176 | |
| 177 | private: |
| 178 | android::base::unique_fd owned_fd_; |
| 179 | android::base::Result<borrowed_fd> Transform(const std::filesystem::path&, |
| 180 | android::base::unique_fd read_fd) override { |
| 181 | owned_fd_ = std::move(read_fd); |
| 182 | return owned_fd_; |
| 183 | } |
| 184 | }; |
| 185 | |
| 186 | // A TestFileHandle where the test file is copies, hence read-writable. |
| 187 | struct ReadWriteTestFileHandle : TestFileHandle { |
| 188 | ReadWriteTestFileHandle(const std::filesystem::path& rel_path) : TestFileHandle(rel_path) {} |
| 189 | |
| 190 | private: |
| 191 | std::unique_ptr<TemporaryFile> temp_file_; |
| 192 | |
| 193 | android::base::Result<borrowed_fd> Transform(const std::filesystem::path& abs_path, |
| 194 | android::base::unique_fd read_fd) override { |
| 195 | // Make a copy to avoid writing to test data. Test files are small, so it is okay |
| 196 | // to read the whole file. |
| 197 | auto content = ReadStartOfFdToString(read_fd, abs_path); |
| 198 | if (!content.ok()) return content.error(); |
| 199 | temp_file_ = std::make_unique<TemporaryFile>(); |
| 200 | if (temp_file_->fd == -1) |
| 201 | return ErrnoError() << "copy " << abs_path << ": open temp file failed"; |
| 202 | if (!android::base::WriteStringToFd(*content, temp_file_->fd)) |
| 203 | return ErrnoError() << "copy " << abs_path << ": write temp file failed"; |
| 204 | |
| 205 | return temp_file_->fd; |
| 206 | } |
| 207 | }; |
| 208 | |
| 209 | class RepackVendorBootImgTestEnv : public ::testing::Environment { |
| 210 | public: |
| 211 | virtual void SetUp() { |
| 212 | OpenTestFile("test_dtb.img", &dtb, &dtb_content); |
| 213 | OpenTestFile("test_bootconfig.img", &bootconfig, &bootconfig_content); |
| 214 | OpenTestFile("test_vendor_ramdisk_none.img", &none, &none_content); |
| 215 | OpenTestFile("test_vendor_ramdisk_platform.img", &platform, &platform_content); |
| 216 | OpenTestFile("test_vendor_ramdisk_replace.img", &replace, &replace_content); |
| 217 | } |
| 218 | |
| 219 | std::unique_ptr<TestFileHandle> dtb; |
| 220 | std::string dtb_content; |
| 221 | std::unique_ptr<TestFileHandle> bootconfig; |
| 222 | std::string bootconfig_content; |
| 223 | std::unique_ptr<TestFileHandle> none; |
| 224 | std::string none_content; |
| 225 | std::unique_ptr<TestFileHandle> platform; |
| 226 | std::string platform_content; |
| 227 | std::unique_ptr<TestFileHandle> replace; |
| 228 | std::string replace_content; |
| 229 | |
| 230 | private: |
| 231 | void OpenTestFile(const char* rel_path, std::unique_ptr<TestFileHandle>* handle, |
| 232 | std::string* content) { |
| 233 | *handle = std::make_unique<ReadOnlyTestFileHandle>(rel_path); |
| 234 | ASSERT_RESULT_OK((*handle)->Open()); |
| 235 | auto content_res = (*handle)->Read(); |
| 236 | ASSERT_RESULT_OK(content_res); |
| 237 | *content = *content_res; |
| 238 | } |
| 239 | }; |
| 240 | RepackVendorBootImgTestEnv* env = nullptr; |
| 241 | |
| 242 | struct RepackVendorBootImgTestParam { |
| 243 | std::string vendor_boot_file_name; |
| 244 | uint32_t expected_header_version; |
| 245 | friend std::ostream& operator<<(std::ostream& os, const RepackVendorBootImgTestParam& param) { |
| 246 | return os << param.vendor_boot_file_name; |
| 247 | } |
| 248 | }; |
| 249 | |
| 250 | class RepackVendorBootImgTest : public ::testing::TestWithParam<RepackVendorBootImgTestParam> { |
| 251 | public: |
| 252 | virtual void SetUp() { |
| 253 | vboot = std::make_unique<ReadWriteTestFileHandle>(GetParam().vendor_boot_file_name); |
| 254 | ASSERT_RESULT_OK(vboot->Open()); |
| 255 | } |
| 256 | std::unique_ptr<TestFileHandle> vboot; |
| 257 | }; |
| 258 | |
| 259 | TEST_P(RepackVendorBootImgTest, InvalidSize) { |
| 260 | EXPECT_ERROR(replace_vendor_ramdisk(vboot->fd(), vboot->size() + 1, "default", |
| 261 | env->replace->fd(), env->replace->size()), |
| 262 | HasSubstr("Size of vendor boot does not match")); |
| 263 | EXPECT_ERROR(replace_vendor_ramdisk(vboot->fd(), vboot->size(), "default", env->replace->fd(), |
| 264 | env->replace->size() + 1), |
| 265 | HasSubstr("Size of new vendor ramdisk does not match")); |
| 266 | } |
| 267 | |
| 268 | TEST_P(RepackVendorBootImgTest, ReplaceUnknown) { |
| 269 | auto res = replace_vendor_ramdisk(vboot->fd(), vboot->size(), "unknown", env->replace->fd(), |
| 270 | env->replace->size()); |
| 271 | if (GetParam().expected_header_version == 3) { |
| 272 | EXPECT_ERROR(res, Eq("Require vendor boot header V4 but is V3")); |
| 273 | } else if (GetParam().expected_header_version == 4) { |
| 274 | EXPECT_ERROR(res, Eq("Vendor ramdisk 'unknown' not found")); |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | TEST_P(RepackVendorBootImgTest, ReplaceDefault) { |
| 279 | auto old_content = vboot->Read(); |
| 280 | ASSERT_RESULT_OK(old_content); |
| 281 | |
| 282 | ASSERT_RESULT_OK(replace_vendor_ramdisk(vboot->fd(), vboot->size(), "default", |
| 283 | env->replace->fd(), env->replace->size())); |
| 284 | EXPECT_RESULT(vboot->fsize(), vboot->size()) << "File size should not change after repack"; |
| 285 | |
| 286 | auto new_content_res = vboot->Read(); |
| 287 | ASSERT_RESULT_OK(new_content_res); |
| 288 | std::string_view new_content(*new_content_res); |
| 289 | |
| 290 | auto hdr = reinterpret_cast<const vendor_boot_img_hdr_v3*>(new_content.data()); |
| 291 | ASSERT_EQ(0, memcmp(VENDOR_BOOT_MAGIC, hdr->magic, VENDOR_BOOT_MAGIC_SIZE)); |
| 292 | ASSERT_EQ(GetParam().expected_header_version, hdr->header_version); |
| 293 | EXPECT_EQ(hdr->vendor_ramdisk_size, env->replace->size()); |
| 294 | EXPECT_EQ(hdr->dtb_size, env->dtb->size()); |
| 295 | |
| 296 | auto o = round_up(sizeof(vendor_boot_img_hdr_v3), hdr->page_size); |
| 297 | auto p = round_up(hdr->vendor_ramdisk_size, hdr->page_size); |
| 298 | auto q = round_up(hdr->dtb_size, hdr->page_size); |
| 299 | |
| 300 | EXPECT_THAT(new_content.substr(o, p), IsPadded(env->replace_content)); |
| 301 | EXPECT_THAT(new_content.substr(o + p, q), IsPadded(env->dtb_content)); |
| 302 | |
| 303 | if (hdr->header_version < 4) return; |
| 304 | |
| 305 | auto hdr_v4 = static_cast<const vendor_boot_img_hdr_v4*>(hdr); |
| 306 | EXPECT_EQ(hdr_v4->vendor_ramdisk_table_entry_num, 1); |
| 307 | EXPECT_EQ(hdr_v4->vendor_ramdisk_table_size, 1 * hdr_v4->vendor_ramdisk_table_entry_size); |
| 308 | EXPECT_GE(hdr_v4->vendor_ramdisk_table_entry_size, sizeof(vendor_ramdisk_table_entry_v4)); |
| 309 | auto entry = reinterpret_cast<const vendor_ramdisk_table_entry_v4*>(&new_content[o + p + q]); |
| 310 | EXPECT_EQ(entry->ramdisk_offset, 0); |
| 311 | EXPECT_EQ(entry->ramdisk_size, hdr_v4->vendor_ramdisk_size); |
| 312 | EXPECT_EQ(entry->ramdisk_type, VENDOR_RAMDISK_TYPE_NONE); |
| 313 | |
| 314 | EXPECT_EQ(hdr_v4->bootconfig_size, env->bootconfig->size()); |
| 315 | auto r = round_up(hdr_v4->vendor_ramdisk_table_size, hdr_v4->page_size); |
| 316 | auto s = round_up(hdr_v4->bootconfig_size, hdr_v4->page_size); |
| 317 | EXPECT_THAT(new_content.substr(o + p + q + r, s), IsPadded(env->bootconfig_content)); |
| 318 | |
| 319 | EXPECT_THAT(new_content, HasSameAvbFooter(*old_content)); |
| 320 | } |
| 321 | |
| 322 | INSTANTIATE_TEST_SUITE_P( |
| 323 | RepackVendorBootImgTest, RepackVendorBootImgTest, |
| 324 | ::testing::Values(RepackVendorBootImgTestParam{"vendor_boot_v3.img", 3}, |
| 325 | RepackVendorBootImgTestParam{"vendor_boot_v4_with_frag.img", 4}, |
| 326 | RepackVendorBootImgTestParam{"vendor_boot_v4_without_frag.img", 4}), |
| 327 | [](const auto& info) { |
| 328 | return android::base::StringReplace(info.param.vendor_boot_file_name, ".", "_", false); |
| 329 | }); |
| 330 | |
| 331 | std::string_view GetRamdiskName(const vendor_ramdisk_table_entry_v4* entry) { |
| 332 | auto ramdisk_name = reinterpret_cast<const char*>(entry->ramdisk_name); |
| 333 | return std::string_view(ramdisk_name, strnlen(ramdisk_name, VENDOR_RAMDISK_NAME_SIZE)); |
| 334 | } |
| 335 | |
| 336 | class RepackVendorBootImgTestV4 : public ::testing::TestWithParam<uint32_t /* ramdisk type */> { |
| 337 | public: |
| 338 | virtual void SetUp() { |
| 339 | vboot = std::make_unique<ReadWriteTestFileHandle>("vendor_boot_v4_with_frag.img"); |
| 340 | ASSERT_RESULT_OK(vboot->Open()); |
| 341 | } |
| 342 | std::unique_ptr<TestFileHandle> vboot; |
| 343 | }; |
| 344 | |
| 345 | TEST_P(RepackVendorBootImgTestV4, Replace) { |
| 346 | uint32_t replace_ramdisk_type = GetParam(); |
| 347 | std::string replace_ramdisk_name; |
| 348 | std::string expect_new_ramdisk_content; |
| 349 | uint32_t expect_none_size = env->none->size(); |
| 350 | uint32_t expect_platform_size = env->platform->size(); |
| 351 | switch (replace_ramdisk_type) { |
| 352 | case VENDOR_RAMDISK_TYPE_NONE: |
| 353 | replace_ramdisk_name = "none_ramdisk"; |
| 354 | expect_new_ramdisk_content = env->replace_content + env->platform_content; |
| 355 | expect_none_size = env->replace->size(); |
| 356 | break; |
| 357 | case VENDOR_RAMDISK_TYPE_PLATFORM: |
| 358 | replace_ramdisk_name = "platform_ramdisk"; |
| 359 | expect_new_ramdisk_content = env->none_content + env->replace_content; |
| 360 | expect_platform_size = env->replace->size(); |
| 361 | break; |
| 362 | default: |
| 363 | LOG(FATAL) << "Ramdisk type " << replace_ramdisk_type |
| 364 | << " is not supported by this test."; |
| 365 | } |
| 366 | |
| 367 | auto old_content = vboot->Read(); |
| 368 | ASSERT_RESULT_OK(old_content); |
| 369 | |
| 370 | ASSERT_RESULT_OK(replace_vendor_ramdisk(vboot->fd(), vboot->size(), replace_ramdisk_name, |
| 371 | env->replace->fd(), env->replace->size())); |
| 372 | EXPECT_RESULT(vboot->fsize(), vboot->size()) << "File size should not change after repack"; |
| 373 | |
| 374 | auto new_content_res = vboot->Read(); |
| 375 | ASSERT_RESULT_OK(new_content_res); |
| 376 | std::string_view new_content(*new_content_res); |
| 377 | |
| 378 | auto hdr = reinterpret_cast<const vendor_boot_img_hdr_v4*>(new_content.data()); |
| 379 | ASSERT_EQ(0, memcmp(VENDOR_BOOT_MAGIC, hdr->magic, VENDOR_BOOT_MAGIC_SIZE)); |
| 380 | ASSERT_EQ(4, hdr->header_version); |
| 381 | EXPECT_EQ(hdr->vendor_ramdisk_size, expect_none_size + expect_platform_size); |
| 382 | EXPECT_EQ(hdr->dtb_size, env->dtb->size()); |
| 383 | EXPECT_EQ(hdr->bootconfig_size, env->bootconfig->size()); |
| 384 | |
| 385 | auto o = round_up(sizeof(vendor_boot_img_hdr_v3), hdr->page_size); |
| 386 | auto p = round_up(hdr->vendor_ramdisk_size, hdr->page_size); |
| 387 | auto q = round_up(hdr->dtb_size, hdr->page_size); |
| 388 | auto r = round_up(hdr->vendor_ramdisk_table_size, hdr->page_size); |
| 389 | auto s = round_up(hdr->bootconfig_size, hdr->page_size); |
| 390 | |
| 391 | EXPECT_THAT(new_content.substr(o, p), IsPadded(expect_new_ramdisk_content)); |
| 392 | EXPECT_THAT(new_content.substr(o + p, q), IsPadded(env->dtb_content)); |
| 393 | |
| 394 | // Check changes in table. |
| 395 | EXPECT_EQ(hdr->vendor_ramdisk_table_entry_num, 2); |
| 396 | EXPECT_EQ(hdr->vendor_ramdisk_table_size, 2 * hdr->vendor_ramdisk_table_entry_size); |
| 397 | EXPECT_GE(hdr->vendor_ramdisk_table_entry_size, sizeof(vendor_ramdisk_table_entry_v4)); |
| 398 | auto entry_none = |
| 399 | reinterpret_cast<const vendor_ramdisk_table_entry_v4*>(&new_content[o + p + q]); |
| 400 | EXPECT_EQ(entry_none->ramdisk_offset, 0); |
| 401 | EXPECT_EQ(entry_none->ramdisk_size, expect_none_size); |
| 402 | EXPECT_EQ(entry_none->ramdisk_type, VENDOR_RAMDISK_TYPE_NONE); |
| 403 | EXPECT_EQ(GetRamdiskName(entry_none), "none_ramdisk"); |
| 404 | |
| 405 | auto entry_platform = reinterpret_cast<const vendor_ramdisk_table_entry_v4*>( |
| 406 | &new_content[o + p + q + hdr->vendor_ramdisk_table_entry_size]); |
| 407 | EXPECT_EQ(entry_platform->ramdisk_offset, expect_none_size); |
| 408 | EXPECT_EQ(entry_platform->ramdisk_size, expect_platform_size); |
| 409 | EXPECT_EQ(entry_platform->ramdisk_type, VENDOR_RAMDISK_TYPE_PLATFORM); |
| 410 | EXPECT_EQ(GetRamdiskName(entry_platform), "platform_ramdisk"); |
| 411 | |
| 412 | EXPECT_THAT(new_content.substr(o + p + q + r, s), IsPadded(env->bootconfig_content)); |
| 413 | |
| 414 | EXPECT_THAT(new_content, HasSameAvbFooter(*old_content)); |
| 415 | } |
| 416 | INSTANTIATE_TEST_SUITE_P(RepackVendorBootImgTest, RepackVendorBootImgTestV4, |
| 417 | ::testing::Values(VENDOR_RAMDISK_TYPE_NONE, VENDOR_RAMDISK_TYPE_PLATFORM), |
| 418 | [](const auto& info) { |
| 419 | return info.param == VENDOR_RAMDISK_TYPE_NONE ? "none" : "platform"; |
| 420 | }); |
| 421 | |
| 422 | } // namespace |
| 423 | |
| 424 | int main(int argc, char* argv[]) { |
| 425 | ::testing::InitGoogleTest(&argc, argv); |
| 426 | env = static_cast<RepackVendorBootImgTestEnv*>( |
| 427 | testing::AddGlobalTestEnvironment(new RepackVendorBootImgTestEnv)); |
| 428 | return RUN_ALL_TESTS(); |
| 429 | } |