From 217d9f98595076f344746bffdafb4314191f3e1b Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 20 Mar 2017 16:57:25 -0700 Subject: tests: Construct two bad packages at runtime for VerifierTest. For the BadPackage tests from VerifierTest: one alters the footer, and the other alters the metadata. Move the two tests to be based on otasigned_v3.zip (they're based on otasigned_v1.zip previously). Also construct the testdata files dynamically (to save the space and for better readability). Test: recovery_component_test Change-Id: I7604d563f8b4fa0c55fec8730c063384158e3abc --- tests/component/verifier_test.cpp | 49 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) (limited to 'tests/component') diff --git a/tests/component/verifier_test.cpp b/tests/component/verifier_test.cpp index 07a8c960f..2cfb6d301 100644 --- a/tests/component/verifier_test.cpp +++ b/tests/component/verifier_test.cpp @@ -115,6 +115,51 @@ TEST(VerifierTest, load_keys_invalid_keys) { ASSERT_FALSE(load_keys(key_file5.path, certs)); } +TEST(VerifierTest, BadPackage_AlteredFooter) { + std::string testkey_v3; + ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("testkey_v3.txt"), &testkey_v3)); + TemporaryFile key_file1; + ASSERT_TRUE(android::base::WriteStringToFile(testkey_v3, key_file1.path)); + std::vector certs; + ASSERT_TRUE(load_keys(key_file1.path, certs)); + + std::string package; + ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("otasigned_v3.zip"), &package)); + ASSERT_EQ(std::string("\xc0\x06\xff\xff\xd2\x06", 6), package.substr(package.size() - 6, 6)); + + // Alter the footer. + package[package.size() - 5] = '\x05'; + ASSERT_EQ(VERIFY_FAILURE, + verify_file(reinterpret_cast(package.data()), package.size(), + certs)); +} + +TEST(VerifierTest, BadPackage_AlteredContent) { + std::string testkey_v3; + ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("testkey_v3.txt"), &testkey_v3)); + TemporaryFile key_file1; + ASSERT_TRUE(android::base::WriteStringToFile(testkey_v3, key_file1.path)); + std::vector certs; + ASSERT_TRUE(load_keys(key_file1.path, certs)); + + std::string package; + ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("otasigned_v3.zip"), &package)); + ASSERT_GT(package.size(), static_cast(100)); + + // Alter the content. + std::string altered1(package); + altered1[50] += 1; + ASSERT_EQ(VERIFY_FAILURE, + verify_file(reinterpret_cast(altered1.data()), altered1.size(), + certs)); + + std::string altered2(package); + altered2[10] += 1; + ASSERT_EQ(VERIFY_FAILURE, + verify_file(reinterpret_cast(altered2.data()), altered2.size(), + certs)); +} + TEST_P(VerifierSuccessTest, VerifySucceed) { ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs, nullptr), VERIFY_SUCCESS); } @@ -157,6 +202,4 @@ INSTANTIATE_TEST_CASE_P(WrongHash, VerifierFailureTest, INSTANTIATE_TEST_CASE_P(BadPackage, VerifierFailureTest, ::testing::Values( std::vector({"random.zip", "v1"}), - std::vector({"fake-eocd.zip", "v1"}), - std::vector({"alter-metadata.zip", "v1"}), - std::vector({"alter-footer.zip", "v1"}))); + std::vector({"fake-eocd.zip", "v1"}))); -- cgit v1.2.3 From 7e61c6a8628bb72c90ca4d5c5b6a609323107d3b Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 20 Mar 2017 16:57:25 -0700 Subject: tests: Construct two bad packages at runtime for VerifierTest. For the BadPackage tests from VerifierTest: one alters the footer, and the other alters the metadata. Move the two tests to be based on otasigned_v3.zip (they're based on otasigned_v1.zip previously). Also construct the testdata files dynamically (to save the space and for better readability). Test: recovery_component_test Change-Id: I7604d563f8b4fa0c55fec8730c063384158e3abc (cherry picked from commit 217d9f98595076f344746bffdafb4314191f3e1b) --- tests/component/verifier_test.cpp | 49 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) (limited to 'tests/component') diff --git a/tests/component/verifier_test.cpp b/tests/component/verifier_test.cpp index 4c0648714..4a3a981f7 100644 --- a/tests/component/verifier_test.cpp +++ b/tests/component/verifier_test.cpp @@ -117,6 +117,51 @@ TEST(VerifierTest, load_keys_invalid_keys) { ASSERT_FALSE(load_keys(key_file5.path, certs)); } +TEST(VerifierTest, BadPackage_AlteredFooter) { + std::string testkey_v3; + ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("testkey_v3.txt"), &testkey_v3)); + TemporaryFile key_file1; + ASSERT_TRUE(android::base::WriteStringToFile(testkey_v3, key_file1.path)); + std::vector certs; + ASSERT_TRUE(load_keys(key_file1.path, certs)); + + std::string package; + ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("otasigned_v3.zip"), &package)); + ASSERT_EQ(std::string("\xc0\x06\xff\xff\xd2\x06", 6), package.substr(package.size() - 6, 6)); + + // Alter the footer. + package[package.size() - 5] = '\x05'; + ASSERT_EQ(VERIFY_FAILURE, + verify_file(reinterpret_cast(package.data()), package.size(), + certs)); +} + +TEST(VerifierTest, BadPackage_AlteredContent) { + std::string testkey_v3; + ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("testkey_v3.txt"), &testkey_v3)); + TemporaryFile key_file1; + ASSERT_TRUE(android::base::WriteStringToFile(testkey_v3, key_file1.path)); + std::vector certs; + ASSERT_TRUE(load_keys(key_file1.path, certs)); + + std::string package; + ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("otasigned_v3.zip"), &package)); + ASSERT_GT(package.size(), static_cast(100)); + + // Alter the content. + std::string altered1(package); + altered1[50] += 1; + ASSERT_EQ(VERIFY_FAILURE, + verify_file(reinterpret_cast(altered1.data()), altered1.size(), + certs)); + + std::string altered2(package); + altered2[10] += 1; + ASSERT_EQ(VERIFY_FAILURE, + verify_file(reinterpret_cast(altered2.data()), altered2.size(), + certs)); +} + TEST(VerifierTest, BadPackage_SignatureStartOutOfBounds) { std::string testkey_v3; ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("testkey_v3.txt"), &testkey_v3)); @@ -174,6 +219,4 @@ INSTANTIATE_TEST_CASE_P(WrongHash, VerifierFailureTest, INSTANTIATE_TEST_CASE_P(BadPackage, VerifierFailureTest, ::testing::Values( std::vector({"random.zip", "v1"}), - std::vector({"fake-eocd.zip", "v1"}), - std::vector({"alter-metadata.zip", "v1"}), - std::vector({"alter-footer.zip", "v1"}))); + std::vector({"fake-eocd.zip", "v1"}))); -- cgit v1.2.3 From f7eb760fe76cb66c5d5341b03d6a66cc1f06d795 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 27 Mar 2017 15:12:48 -0700 Subject: applypatch: Change the ssize_t length parameters to size_t. Mostly for applypatch family APIs like ApplyBSDiffPatch() and ApplyImagePatch(). Changing to size_t doesn't indicate they would necessarily work with very large size_t (e.g. > ssize_t), just similar to write(2). But otherwise accepting negative length doesn't make much sense. Also change the return type of SinkFn from ssize_t to size_t. Callers tell a successful sink by comparing the number of written bytes against the desired value. Negative return values like -1 are not needed. This also makes it consistent with bsdiff::bspatch interface. Test: recovery_component_test Test: Apply an incremental with the new updater. Change-Id: I7ff1615203a5c9854134f75d019e266f4ea6e714 --- tests/component/imgdiff_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/component') diff --git a/tests/component/imgdiff_test.cpp b/tests/component/imgdiff_test.cpp index 2f648501c..64e1f2990 100644 --- a/tests/component/imgdiff_test.cpp +++ b/tests/component/imgdiff_test.cpp @@ -27,7 +27,7 @@ using android::base::get_unaligned; -static ssize_t MemorySink(const unsigned char* data, ssize_t len, void* token) { +static size_t MemorySink(const unsigned char* data, size_t len, void* token) { std::string* s = static_cast(token); s->append(reinterpret_cast(data), len); return len; -- cgit v1.2.3 From c0e1c46a707370952ea1ddeb71b176d04fe71bb9 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 1 Feb 2017 10:20:10 -0800 Subject: applypatch: Let Apply{BSDiff,Image}Patch accept std::function. Test: mmma bootable/recovery system/update_engine Test: recovery_component_test Change-Id: I93c2caa87bf94a53509bb37f98f2c02bcadb6f5c --- tests/component/imgdiff_test.cpp | 80 ++++++++++++---------------------------- 1 file changed, 24 insertions(+), 56 deletions(-) (limited to 'tests/component') diff --git a/tests/component/imgdiff_test.cpp b/tests/component/imgdiff_test.cpp index 64e1f2990..7d00a3d53 100644 --- a/tests/component/imgdiff_test.cpp +++ b/tests/component/imgdiff_test.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #include #include @@ -27,12 +29,6 @@ using android::base::get_unaligned; -static size_t MemorySink(const unsigned char* data, size_t len, void* token) { - std::string* s = static_cast(token); - s->append(reinterpret_cast(data), len); - return len; -} - // Sanity check for the given imgdiff patch header. static void verify_patch_header(const std::string& patch, size_t* num_normal, size_t* num_raw, size_t* num_deflate) { @@ -79,6 +75,18 @@ static void verify_patch_header(const std::string& patch, size_t* num_normal, si if (num_deflate != nullptr) *num_deflate = deflate; } +static void verify_patched_image(const std::string& src, const std::string& patch, + const std::string& tgt) { + std::string patched; + ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), + reinterpret_cast(patch.data()), patch.size(), + [&patched](const unsigned char* data, size_t len) { + patched.append(reinterpret_cast(data), len); + return len; + })); + ASSERT_EQ(tgt, patched); +} + TEST(ImgdiffTest, invalid_args) { // Insufficient inputs. ASSERT_EQ(2, imgdiff(1, (const char* []){ "imgdiff" })); @@ -124,11 +132,7 @@ TEST(ImgdiffTest, image_mode_smoke) { ASSERT_EQ(0U, num_deflate); ASSERT_EQ(1U, num_raw); - std::string patched; - ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), - reinterpret_cast(patch.data()), patch.size(), - MemorySink, &patched)); - ASSERT_EQ(tgt, patched); + verify_patched_image(src, patch, tgt); } TEST(ImgdiffTest, zip_mode_smoke_store) { @@ -177,11 +181,7 @@ TEST(ImgdiffTest, zip_mode_smoke_store) { ASSERT_EQ(0U, num_deflate); ASSERT_EQ(1U, num_raw); - std::string patched; - ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), - reinterpret_cast(patch.data()), patch.size(), - MemorySink, &patched)); - ASSERT_EQ(tgt, patched); + verify_patched_image(src, patch, tgt); } TEST(ImgdiffTest, zip_mode_smoke_compressed) { @@ -230,11 +230,7 @@ TEST(ImgdiffTest, zip_mode_smoke_compressed) { ASSERT_EQ(1U, num_deflate); ASSERT_EQ(2U, num_raw); - std::string patched; - ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), - reinterpret_cast(patch.data()), patch.size(), - MemorySink, &patched)); - ASSERT_EQ(tgt, patched); + verify_patched_image(src, patch, tgt); } TEST(ImgdiffTest, zip_mode_smoke_trailer_zeros) { @@ -286,11 +282,7 @@ TEST(ImgdiffTest, zip_mode_smoke_trailer_zeros) { ASSERT_EQ(1U, num_deflate); ASSERT_EQ(2U, num_raw); - std::string patched; - ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), - reinterpret_cast(patch.data()), patch.size(), - MemorySink, &patched)); - ASSERT_EQ(tgt, patched); + verify_patched_image(src, patch, tgt); } TEST(ImgdiffTest, image_mode_simple) { @@ -333,11 +325,7 @@ TEST(ImgdiffTest, image_mode_simple) { ASSERT_EQ(1U, num_deflate); ASSERT_EQ(2U, num_raw); - std::string patched; - ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), - reinterpret_cast(patch.data()), patch.size(), - MemorySink, &patched)); - ASSERT_EQ(tgt, patched); + verify_patched_image(src, patch, tgt); } TEST(ImgdiffTest, image_mode_different_num_chunks) { @@ -413,11 +401,7 @@ TEST(ImgdiffTest, image_mode_merge_chunks) { ASSERT_EQ(1U, num_deflate); ASSERT_EQ(2U, num_raw); - std::string patched; - ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), - reinterpret_cast(patch.data()), patch.size(), - MemorySink, &patched)); - ASSERT_EQ(tgt, patched); + verify_patched_image(src, patch, tgt); } TEST(ImgdiffTest, image_mode_spurious_magic) { @@ -454,11 +438,7 @@ TEST(ImgdiffTest, image_mode_spurious_magic) { ASSERT_EQ(0U, num_deflate); ASSERT_EQ(1U, num_raw); - std::string patched; - ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), - reinterpret_cast(patch.data()), patch.size(), - MemorySink, &patched)); - ASSERT_EQ(tgt, patched); + verify_patched_image(src, patch, tgt); } TEST(ImgdiffTest, image_mode_short_input1) { @@ -494,11 +474,7 @@ TEST(ImgdiffTest, image_mode_short_input1) { ASSERT_EQ(0U, num_deflate); ASSERT_EQ(1U, num_raw); - std::string patched; - ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), - reinterpret_cast(patch.data()), patch.size(), - MemorySink, &patched)); - ASSERT_EQ(tgt, patched); + verify_patched_image(src, patch, tgt); } TEST(ImgdiffTest, image_mode_short_input2) { @@ -534,11 +510,7 @@ TEST(ImgdiffTest, image_mode_short_input2) { ASSERT_EQ(0U, num_deflate); ASSERT_EQ(1U, num_raw); - std::string patched; - ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), - reinterpret_cast(patch.data()), patch.size(), - MemorySink, &patched)); - ASSERT_EQ(tgt, patched); + verify_patched_image(src, patch, tgt); } TEST(ImgdiffTest, image_mode_single_entry_long) { @@ -577,9 +549,5 @@ TEST(ImgdiffTest, image_mode_single_entry_long) { ASSERT_EQ(0U, num_deflate); ASSERT_EQ(0U, num_raw); - std::string patched; - ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), - reinterpret_cast(patch.data()), patch.size(), - MemorySink, &patched)); - ASSERT_EQ(tgt, patched); + verify_patched_image(src, patch, tgt); } -- cgit v1.2.3 From bdc8c1a264ace01fa2b1e6bcd1b417ab7218d169 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Fri, 24 Mar 2017 10:39:05 -0700 Subject: tests: Add a test for --wipe_ab into UncryptTest. Also factor out the common parts in {setup,clear}_bcb into a separate function. Test: recovery_component_test Change-Id: I7b95cced925c8135e020dcb791ca2425d4f28449 --- tests/component/uncrypt_test.cpp | 185 +++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 103 deletions(-) (limited to 'tests/component') diff --git a/tests/component/uncrypt_test.cpp b/tests/component/uncrypt_test.cpp index 4f2b8164f..5e057e129 100644 --- a/tests/component/uncrypt_test.cpp +++ b/tests/component/uncrypt_test.cpp @@ -25,12 +25,15 @@ #include #include #include +#include #include #include #include #include "common/component_test_util.h" +using namespace std::string_literals; + static const std::string UNCRYPT_SOCKET = "/dev/socket/uncrypt"; static const std::string INIT_SVC_SETUP_BCB = "init.svc.setup-bcb"; static const std::string INIT_SVC_CLEAR_BCB = "init.svc.clear-bcb"; @@ -65,128 +68,104 @@ class UncryptTest : public ::testing::Test { has_misc = parse_misc(); } - bool has_misc; -}; - -TEST_F(UncryptTest, setup_bcb) { - if (!has_misc) { - GTEST_LOG_(INFO) << "Test skipped due to no /misc partition found on the device."; - return; - } - - // Trigger the setup-bcb service. - ASSERT_TRUE(android::base::SetProperty("ctl.start", "setup-bcb")); - - // Test tends to be flaky if proceeding immediately ("Transport endpoint is not connected"). - sleep(1); - - struct sockaddr_un un = {}; - un.sun_family = AF_UNIX; - strlcpy(un.sun_path, UNCRYPT_SOCKET.c_str(), sizeof(un.sun_path)); - - int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - ASSERT_NE(-1, sockfd); - - // Connect to the uncrypt socket. - bool success = false; - for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) { - if (connect(sockfd, reinterpret_cast(&un), sizeof(struct sockaddr_un)) != 0) { - success = true; - break; + void SetupOrClearBcb(bool isSetup, const std::string& message, + const std::string& message_in_bcb) const { + if (!has_misc) { + GTEST_LOG_(INFO) << "Test skipped due to no /misc partition found on the device."; + return; } - sleep(1); - } - ASSERT_TRUE(success); - - // Send out the BCB message. - std::string message = "--update_message=abc value"; - std::string message_in_bcb = "recovery\n--update_message=abc value\n"; - int length = static_cast(message.size()); - int length_out = htonl(length); - ASSERT_TRUE(android::base::WriteFully(sockfd, &length_out, sizeof(int))) - << "Failed to write length: " << strerror(errno); - ASSERT_TRUE(android::base::WriteFully(sockfd, message.data(), length)) - << "Failed to write message: " << strerror(errno); - - // Check the status code from uncrypt. - int status; - ASSERT_TRUE(android::base::ReadFully(sockfd, &status, sizeof(int))); - ASSERT_EQ(100U, ntohl(status)); - // Ack having received the status code. - int code = 0; - ASSERT_TRUE(android::base::WriteFully(sockfd, &code, sizeof(int))); + // Trigger the setup-bcb service. + ASSERT_TRUE(android::base::SetProperty("ctl.start", isSetup ? "setup-bcb" : "clear-bcb")); - ASSERT_EQ(0, close(sockfd)); + // Test tends to be flaky if proceeding immediately ("Transport endpoint is not connected"). + sleep(1); - ASSERT_TRUE(android::base::SetProperty("ctl.stop", "setup-bcb")); + sockaddr_un un = {}; + un.sun_family = AF_UNIX; + strlcpy(un.sun_path, UNCRYPT_SOCKET.c_str(), sizeof(un.sun_path)); - // Verify the message by reading from BCB directly. - bootloader_message boot; - std::string err; - ASSERT_TRUE(read_bootloader_message(&boot, &err)) << "Failed to read BCB: " << err; + int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + ASSERT_NE(-1, sockfd); - ASSERT_EQ("boot-recovery", std::string(boot.command)); - ASSERT_EQ(message_in_bcb, std::string(boot.recovery)); + // Connect to the uncrypt socket. + bool success = false; + for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) { + if (connect(sockfd, reinterpret_cast(&un), sizeof(sockaddr_un)) != 0) { + success = true; + break; + } + sleep(1); + } + ASSERT_TRUE(success); + + if (isSetup) { + // Send out the BCB message. + int length = static_cast(message.size()); + int length_out = htonl(length); + ASSERT_TRUE(android::base::WriteFully(sockfd, &length_out, sizeof(int))) + << "Failed to write length: " << strerror(errno); + ASSERT_TRUE(android::base::WriteFully(sockfd, message.data(), length)) + << "Failed to write message: " << strerror(errno); + } - // The rest of the boot.recovery message should be zero'd out. - ASSERT_LE(message_in_bcb.size(), sizeof(boot.recovery)); - size_t left = sizeof(boot.recovery) - message_in_bcb.size(); - ASSERT_EQ(std::string(left, '\0'), std::string(&boot.recovery[message_in_bcb.size()], left)); + // Check the status code from uncrypt. + int status; + ASSERT_TRUE(android::base::ReadFully(sockfd, &status, sizeof(int))); + ASSERT_EQ(100U, ntohl(status)); - // Clear the BCB. - ASSERT_TRUE(clear_bootloader_message(&err)) << "Failed to clear BCB: " << err; -} + // Ack having received the status code. + int code = 0; + ASSERT_TRUE(android::base::WriteFully(sockfd, &code, sizeof(int))); -TEST_F(UncryptTest, clear_bcb) { - if (!has_misc) { - GTEST_LOG_(INFO) << "Test skipped due to no /misc partition found on the device."; - return; - } + ASSERT_EQ(0, close(sockfd)); - // Trigger the clear-bcb service. - ASSERT_TRUE(android::base::SetProperty("ctl.start", "clear-bcb")); + ASSERT_TRUE(android::base::SetProperty("ctl.stop", isSetup ? "setup-bcb" : "clear-bcb")); - // Test tends to be flaky if proceeding immediately ("Transport endpoint is not connected"). - sleep(1); + // Verify the message by reading from BCB directly. + bootloader_message boot; + std::string err; + ASSERT_TRUE(read_bootloader_message(&boot, &err)) << "Failed to read BCB: " << err; - struct sockaddr_un un = {}; - un.sun_family = AF_UNIX; - strlcpy(un.sun_path, UNCRYPT_SOCKET.c_str(), sizeof(un.sun_path)); + if (isSetup) { + ASSERT_EQ("boot-recovery", std::string(boot.command)); + ASSERT_EQ(message_in_bcb, std::string(boot.recovery)); - int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - ASSERT_NE(-1, sockfd); + // The rest of the boot.recovery message should be zero'd out. + ASSERT_LE(message_in_bcb.size(), sizeof(boot.recovery)); + size_t left = sizeof(boot.recovery) - message_in_bcb.size(); + ASSERT_EQ(std::string(left, '\0'), std::string(&boot.recovery[message_in_bcb.size()], left)); - // Connect to the uncrypt socket. - bool success = false; - for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) { - if (connect(sockfd, reinterpret_cast(&un), sizeof(struct sockaddr_un)) != 0) { - success = true; - break; + // Clear the BCB. + ASSERT_TRUE(clear_bootloader_message(&err)) << "Failed to clear BCB: " << err; + } else { + // All the bytes should be cleared. + ASSERT_EQ(std::string(sizeof(boot), '\0'), + std::string(reinterpret_cast(&boot), sizeof(boot))); } - sleep(1); } - ASSERT_TRUE(success); - // Check the status code from uncrypt. - int status; - ASSERT_TRUE(android::base::ReadFully(sockfd, &status, sizeof(int))); - ASSERT_EQ(100U, ntohl(status)); - - // Ack having received the status code. - int code = 0; - ASSERT_TRUE(android::base::WriteFully(sockfd, &code, sizeof(int))); + bool has_misc; +}; - ASSERT_EQ(0, close(sockfd)); +TEST_F(UncryptTest, setup_bcb) { + std::string message = "--update_message=abc value"; + std::string message_in_bcb = "recovery\n--update_message=abc value\n"; + SetupOrClearBcb(true, message, message_in_bcb); +} - ASSERT_TRUE(android::base::SetProperty("ctl.stop", "clear-bcb")); +TEST_F(UncryptTest, clear_bcb) { + SetupOrClearBcb(false, "", ""); +} - // Verify the content by reading from BCB directly. - bootloader_message boot; - std::string err; - ASSERT_TRUE(read_bootloader_message(&boot, &err)) << "Failed to read BCB: " << err; +TEST_F(UncryptTest, setup_bcb_wipe_ab) { + TemporaryFile wipe_package; + ASSERT_TRUE(android::base::WriteStringToFile(std::string(345, 'a'), wipe_package.path)); - // All the bytes should be cleared. - ASSERT_EQ(std::string(sizeof(boot), '\0'), - std::string(reinterpret_cast(&boot), sizeof(boot))); + // It's expected to store a wipe package in /misc, with the package size passed to recovery. + std::string message = + "--wipe_ab\n--wipe_package="s + wipe_package.path + "\n--reason=wipePackage"s; + std::string message_in_bcb = + "recovery\n--wipe_ab\n--wipe_package_size=345\n--reason=wipePackage\n"; + SetupOrClearBcb(true, message, message_in_bcb); } -- cgit v1.2.3 From 28b79f797c1aacfffff89bf509f585d1f65287fa Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 28 Mar 2017 19:06:26 -0700 Subject: Fix the bad merge (duplicate tests). Test: mmma bootable/recovery Change-Id: I909164fed84fb17a7e1cb2427cb88208a69dc052 --- tests/component/verifier_test.cpp | 45 --------------------------------------- 1 file changed, 45 deletions(-) (limited to 'tests/component') diff --git a/tests/component/verifier_test.cpp b/tests/component/verifier_test.cpp index ce5b075cf..4a3a981f7 100644 --- a/tests/component/verifier_test.cpp +++ b/tests/component/verifier_test.cpp @@ -177,51 +177,6 @@ TEST(VerifierTest, BadPackage_SignatureStartOutOfBounds) { package.size(), certs)); } -TEST(VerifierTest, BadPackage_AlteredFooter) { - std::string testkey_v3; - ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("testkey_v3.txt"), &testkey_v3)); - TemporaryFile key_file1; - ASSERT_TRUE(android::base::WriteStringToFile(testkey_v3, key_file1.path)); - std::vector certs; - ASSERT_TRUE(load_keys(key_file1.path, certs)); - - std::string package; - ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("otasigned_v3.zip"), &package)); - ASSERT_EQ(std::string("\xc0\x06\xff\xff\xd2\x06", 6), package.substr(package.size() - 6, 6)); - - // Alter the footer. - package[package.size() - 5] = '\x05'; - ASSERT_EQ(VERIFY_FAILURE, - verify_file(reinterpret_cast(package.data()), package.size(), - certs)); -} - -TEST(VerifierTest, BadPackage_AlteredContent) { - std::string testkey_v3; - ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("testkey_v3.txt"), &testkey_v3)); - TemporaryFile key_file1; - ASSERT_TRUE(android::base::WriteStringToFile(testkey_v3, key_file1.path)); - std::vector certs; - ASSERT_TRUE(load_keys(key_file1.path, certs)); - - std::string package; - ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("otasigned_v3.zip"), &package)); - ASSERT_GT(package.size(), static_cast(100)); - - // Alter the content. - std::string altered1(package); - altered1[50] += 1; - ASSERT_EQ(VERIFY_FAILURE, - verify_file(reinterpret_cast(altered1.data()), altered1.size(), - certs)); - - std::string altered2(package); - altered2[10] += 1; - ASSERT_EQ(VERIFY_FAILURE, - verify_file(reinterpret_cast(altered2.data()), altered2.size(), - certs)); -} - TEST_P(VerifierSuccessTest, VerifySucceed) { ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs, nullptr), VERIFY_SUCCESS); } -- cgit v1.2.3 From ad87d9dc7823d74f067a4d82a8884f39d523acc9 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 4 Apr 2017 19:59:40 -0700 Subject: tests: Use get_bootloader_message_blk_device() to find /misc. Since commit fb00d82f32446804f7149bc6846dcc580cf0db1d has added get_bootloader_message_blk_device() as an API, switch the tests-local implementation to it. Test: recovery_component_test on angler. Test: recovery_component_test on a local build that doesn't have /misc. Change-Id: I4f5f542cb9ef58292c587a677da73d8822db7262 --- tests/component/bootloader_message_test.cpp | 5 ++--- tests/component/uncrypt_test.cpp | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'tests/component') diff --git a/tests/component/bootloader_message_test.cpp b/tests/component/bootloader_message_test.cpp index 0357accfe..b38bc7134 100644 --- a/tests/component/bootloader_message_test.cpp +++ b/tests/component/bootloader_message_test.cpp @@ -21,14 +21,13 @@ #include #include -#include "common/component_test_util.h" - class BootloaderMessageTest : public ::testing::Test { protected: BootloaderMessageTest() : has_misc(true) {} virtual void SetUp() override { - has_misc = parse_misc(); + std::string err; + has_misc = !get_bootloader_message_blk_device(&err).empty(); } virtual void TearDown() override { diff --git a/tests/component/uncrypt_test.cpp b/tests/component/uncrypt_test.cpp index 5e057e129..3925236a5 100644 --- a/tests/component/uncrypt_test.cpp +++ b/tests/component/uncrypt_test.cpp @@ -30,8 +30,6 @@ #include #include -#include "common/component_test_util.h" - using namespace std::string_literals; static const std::string UNCRYPT_SOCKET = "/dev/socket/uncrypt"; @@ -65,7 +63,8 @@ class UncryptTest : public ::testing::Test { ASSERT_TRUE(success) << "uncrypt service is not available."; - has_misc = parse_misc(); + std::string err; + has_misc = !get_bootloader_message_blk_device(&err).empty(); } void SetupOrClearBcb(bool isSetup, const std::string& message, -- cgit v1.2.3 From 3a8d98dd902da8b69cff731b3db03c75b176b751 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Mon, 3 Apr 2017 20:01:17 -0700 Subject: Abort the update if there's not enough new data Right now the update stuck in a deadlock if there's less new data than expection. Add some checkers and abort the update if such case happens. Also add a corresponding test. Bug: 36787146 Test: update aborts correctly on bullhead && recovery_component_test passes Change-Id: I914e4a2a4cf157b99ef2fc65bd21c6981e38ca47 --- tests/component/updater_test.cpp | 66 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'tests/component') diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp index 5652ddf46..dc4b5d724 100644 --- a/tests/component/updater_test.cpp +++ b/tests/component/updater_test.cpp @@ -607,3 +607,69 @@ TEST_F(UpdaterTest, block_image_update) { ASSERT_EQ(0, fclose(updater_info.cmd_pipe)); CloseArchive(handle); } + +TEST_F(UpdaterTest, new_data_short_write) { + // Create a zip file with new_data. + TemporaryFile zip_file; + FILE* zip_file_ptr = fdopen(zip_file.fd, "wb"); + ZipWriter zip_writer(zip_file_ptr); + + // Add the empty new data. + ASSERT_EQ(0, zip_writer.StartEntry("empty_new_data", 0)); + ASSERT_EQ(0, zip_writer.FinishEntry()); + // Add the short written new data. + ASSERT_EQ(0, zip_writer.StartEntry("short_new_data", 0)); + std::string new_data_short = std::string(10, 'a'); + ASSERT_EQ(0, zip_writer.WriteBytes(new_data_short.data(), new_data_short.size())); + ASSERT_EQ(0, zip_writer.FinishEntry()); + // Add the data of exactly one block. + ASSERT_EQ(0, zip_writer.StartEntry("exact_new_data", 0)); + std::string new_data_exact = std::string(4096, 'a'); + ASSERT_EQ(0, zip_writer.WriteBytes(new_data_exact.data(), new_data_exact.size())); + ASSERT_EQ(0, zip_writer.FinishEntry()); + // Add a dummy patch data. + ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0)); + ASSERT_EQ(0, zip_writer.FinishEntry()); + + std::vector transfer_list = { + "4", + "1", + "0", + "0", + "new 2,0,1", + }; + ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0)); + std::string commands = android::base::Join(transfer_list, '\n'); + ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size())); + ASSERT_EQ(0, zip_writer.FinishEntry()); + ASSERT_EQ(0, zip_writer.Finish()); + ASSERT_EQ(0, fclose(zip_file_ptr)); + + MemMapping map; + ASSERT_EQ(0, sysMapFile(zip_file.path, &map)); + ZipArchiveHandle handle; + ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle)); + + // Set up the handler, command_pipe, patch offset & length. + UpdaterInfo updater_info; + updater_info.package_zip = handle; + TemporaryFile temp_pipe; + updater_info.cmd_pipe = fopen(temp_pipe.path, "wb"); + updater_info.package_zip_addr = map.addr; + updater_info.package_zip_len = map.length; + + // Updater should report the failure gracefully rather than stuck in deadlock. + TemporaryFile update_file; + std::string script_empty_data = "block_image_update(\"" + std::string(update_file.path) + + R"(", package_extract_file("transfer_list"), "empty_new_data", "patch_data"))"; + expect("", script_empty_data.c_str(), kNoCause, &updater_info); + + std::string script_short_data = "block_image_update(\"" + std::string(update_file.path) + + R"(", package_extract_file("transfer_list"), "short_new_data", "patch_data"))"; + expect("", script_short_data.c_str(), kNoCause, &updater_info); + + // Expect to write 1 block of new data successfully. + std::string script_exact_data = "block_image_update(\"" + std::string(update_file.path) + + R"(", package_extract_file("transfer_list"), "exact_new_data", "patch_data"))"; + expect("t", script_exact_data.c_str(), kNoCause, &updater_info); +} -- cgit v1.2.3 From 1d866050eba7614109a1edec42529d4d80b0998f Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 10 Apr 2017 16:55:57 -0700 Subject: Verify the package compatibility with libvintf. verify_package_compatibility() is added to parse the compatibility entry (compatibility.zip) in a given OTA package. If entry is present, the information is sent to libvintf to check the compatibility. This CL doesn't actually call libvintf, since the API there is not available yet. Bug: 36597505 Test: Doesn't break the install with existing packages (i.e. w/o the compatibility entry). Test: recovery_component_test Change-Id: I3903ffa5f6ba33a5c0d761602ade6290c6752596 (cherry picked from commit 62e0bc7586077b3bde82759fb34b51b982cea20f) --- tests/component/install_test.cpp | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/component/install_test.cpp (limited to 'tests/component') diff --git a/tests/component/install_test.cpp b/tests/component/install_test.cpp new file mode 100644 index 000000000..3b6fbc301 --- /dev/null +++ b/tests/component/install_test.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agree to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include "install.h" + +TEST(InstallTest, verify_package_compatibility_no_entry) { + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + // The archive must have something to be opened correctly. + ASSERT_EQ(0, writer.StartEntry("dummy_entry", 0)); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + // Doesn't contain compatibility zip entry. + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + ASSERT_TRUE(verify_package_compatibility(zip)); + CloseArchive(zip); +} + +TEST(InstallTest, verify_package_compatibility_invalid_entry) { + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + ASSERT_EQ(0, writer.StartEntry("compatibility.zip", 0)); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + // Empty compatibility zip entry. + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + ASSERT_FALSE(verify_package_compatibility(zip)); + CloseArchive(zip); +} -- cgit v1.2.3 From bc4b1fe4c4305ebf0fbfc891b9b508c14b5c8ef8 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 17 Apr 2017 16:46:05 -0700 Subject: Add tests for update_binary_command(). Expose update_binary_command() through private/install.h for testing purpose. Also make minor clean-ups to install.cpp: a) adding more verbose logging on ExtractToMemory failures; b) update_binary_command() taking std::string instead of const char*; c) moving a few macro and global constants into update_binary_command(). Bug: 37300957 Test: recovery_component_test on marlin Test: Build new recovery and adb sideload on angler and sailfish. Change-Id: Ib2d9068af3fee038f01c90940ccaeb0a7da374fc --- tests/component/install_test.cpp | 87 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'tests/component') diff --git a/tests/component/install_test.cpp b/tests/component/install_test.cpp index 3b6fbc301..fd3b28b07 100644 --- a/tests/component/install_test.cpp +++ b/tests/component/install_test.cpp @@ -16,12 +16,18 @@ #include +#include +#include + +#include +#include #include #include #include #include #include "install.h" +#include "private/install.h" TEST(InstallTest, verify_package_compatibility_no_entry) { TemporaryFile temp_file; @@ -55,3 +61,84 @@ TEST(InstallTest, verify_package_compatibility_invalid_entry) { ASSERT_FALSE(verify_package_compatibility(zip)); CloseArchive(zip); } + +TEST(InstallTest, update_binary_command_smoke) { +#ifdef AB_OTA_UPDATER + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + ASSERT_EQ(0, writer.StartEntry("payload.bin", kCompressStored)); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.StartEntry("payload_properties.txt", kCompressStored)); + const std::string properties = "some_properties"; + ASSERT_EQ(0, writer.WriteBytes(properties.data(), properties.size())); + ASSERT_EQ(0, writer.FinishEntry()); + // A metadata entry is mandatory. + ASSERT_EQ(0, writer.StartEntry("META-INF/com/android/metadata", kCompressStored)); + std::string device = android::base::GetProperty("ro.product.device", ""); + ASSERT_NE("", device); + std::string timestamp = android::base::GetProperty("ro.build.date.utc", ""); + ASSERT_NE("", timestamp); + std::string metadata = android::base::Join( + std::vector{ + "ota-type=AB", "pre-device=" + device, "post-timestamp=" + timestamp, + }, + "\n"); + ASSERT_EQ(0, writer.WriteBytes(metadata.data(), metadata.size())); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + int status_fd = 10; + std::string path = "/path/to/update.zip"; + std::vector cmd; + ASSERT_EQ(0, update_binary_command(path, zip, 0, status_fd, &cmd)); + ASSERT_EQ("/sbin/update_engine_sideload", cmd[0]); + ASSERT_EQ("--payload=file://" + path, cmd[1]); + ASSERT_EQ("--headers=" + properties, cmd[3]); + ASSERT_EQ("--status_fd=" + std::to_string(status_fd), cmd[4]); + CloseArchive(zip); +#else + // Cannot test update_binary_command() because it tries to extract update-binary to /tmp. + GTEST_LOG_(INFO) << "Test skipped on non-A/B device."; +#endif // AB_OTA_UPDATER +} + +TEST(InstallTest, update_binary_command_invalid) { +#ifdef AB_OTA_UPDATER + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + // Missing payload_properties.txt. + ASSERT_EQ(0, writer.StartEntry("payload.bin", kCompressStored)); + ASSERT_EQ(0, writer.FinishEntry()); + // A metadata entry is mandatory. + ASSERT_EQ(0, writer.StartEntry("META-INF/com/android/metadata", kCompressStored)); + std::string device = android::base::GetProperty("ro.product.device", ""); + ASSERT_NE("", device); + std::string timestamp = android::base::GetProperty("ro.build.date.utc", ""); + ASSERT_NE("", timestamp); + std::string metadata = android::base::Join( + std::vector{ + "ota-type=AB", "pre-device=" + device, "post-timestamp=" + timestamp, + }, + "\n"); + ASSERT_EQ(0, writer.WriteBytes(metadata.data(), metadata.size())); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + int status_fd = 10; + std::string path = "/path/to/update.zip"; + std::vector cmd; + ASSERT_EQ(INSTALL_CORRUPT, update_binary_command(path, zip, 0, status_fd, &cmd)); + CloseArchive(zip); +#else + // Cannot test update_binary_command() because it tries to extract update-binary to /tmp. + GTEST_LOG_(INFO) << "Test skipped on non-A/B device."; +#endif // AB_OTA_UPDATER +} -- cgit v1.2.3 From 8a7afcc6ed5467dd2e9800244d10a88cd359a0a3 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 18 Apr 2017 22:05:50 -0700 Subject: Add tests for read_metadata_from_package(). Test: recovery_component_test Change-Id: I672a6a4f101c72e82b9f25f165dccd1c9520627b --- tests/component/install_test.cpp | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'tests/component') diff --git a/tests/component/install_test.cpp b/tests/component/install_test.cpp index fd3b28b07..2143dd7bb 100644 --- a/tests/component/install_test.cpp +++ b/tests/component/install_test.cpp @@ -62,6 +62,56 @@ TEST(InstallTest, verify_package_compatibility_invalid_entry) { CloseArchive(zip); } +TEST(InstallTest, read_metadata_from_package_smoke) { + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + ASSERT_EQ(0, writer.StartEntry("META-INF/com/android/metadata", kCompressStored)); + const std::string content("abcdefg"); + ASSERT_EQ(0, writer.WriteBytes(content.data(), content.size())); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + std::string metadata; + ASSERT_TRUE(read_metadata_from_package(zip, &metadata)); + ASSERT_EQ(content, metadata); + CloseArchive(zip); + + TemporaryFile temp_file2; + FILE* zip_file2 = fdopen(temp_file2.fd, "w"); + ZipWriter writer2(zip_file2); + ASSERT_EQ(0, writer2.StartEntry("META-INF/com/android/metadata", kCompressDeflated)); + ASSERT_EQ(0, writer2.WriteBytes(content.data(), content.size())); + ASSERT_EQ(0, writer2.FinishEntry()); + ASSERT_EQ(0, writer2.Finish()); + ASSERT_EQ(0, fclose(zip_file2)); + + ASSERT_EQ(0, OpenArchive(temp_file2.path, &zip)); + metadata.clear(); + ASSERT_TRUE(read_metadata_from_package(zip, &metadata)); + ASSERT_EQ(content, metadata); + CloseArchive(zip); +} + +TEST(InstallTest, read_metadata_from_package_no_entry) { + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + ASSERT_EQ(0, writer.StartEntry("dummy_entry", kCompressStored)); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + std::string metadata; + ASSERT_FALSE(read_metadata_from_package(zip, &metadata)); + CloseArchive(zip); +} + TEST(InstallTest, update_binary_command_smoke) { #ifdef AB_OTA_UPDATER TemporaryFile temp_file; -- cgit v1.2.3 From f2784b6a43e54ed67bc30ac456f66f11bd16bc74 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 19 Apr 2017 12:37:12 -0700 Subject: Add more tests for verify_package_compatibility(). This now covers the actual calls to libvintf, and asserts we're getting identical results through verify_package_compatibility() and by calling libvintf directly. We were missing the coverage and introduced the double free bug (fixed by commit f978278995d02a58e311fe017bdbb2c3702dd3bc). Bug: 37413730 Test: recovery_component_test passes. Test: recovery_component_test fails w/o commit f978278995d02a58e311fe017bdbb2c3702dd3bc. Change-Id: If5195ea1c583fd7c440a1de289da82145e80e23c --- tests/component/install_test.cpp | 84 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) (limited to 'tests/component') diff --git a/tests/component/install_test.cpp b/tests/component/install_test.cpp index 2143dd7bb..40201d76f 100644 --- a/tests/component/install_test.cpp +++ b/tests/component/install_test.cpp @@ -15,14 +15,17 @@ */ #include +#include #include #include +#include #include #include #include #include +#include #include #include @@ -112,6 +115,87 @@ TEST(InstallTest, read_metadata_from_package_no_entry) { CloseArchive(zip); } +TEST(InstallTest, verify_package_compatibility_with_libvintf_malformed_xml) { + TemporaryFile compatibility_zip_file; + FILE* compatibility_zip = fdopen(compatibility_zip_file.fd, "w"); + ZipWriter compatibility_zip_writer(compatibility_zip); + ASSERT_EQ(0, compatibility_zip_writer.StartEntry("system_manifest.xml", kCompressDeflated)); + std::string malformed_xml = "malformed"; + ASSERT_EQ(0, compatibility_zip_writer.WriteBytes(malformed_xml.data(), malformed_xml.size())); + ASSERT_EQ(0, compatibility_zip_writer.FinishEntry()); + ASSERT_EQ(0, compatibility_zip_writer.Finish()); + ASSERT_EQ(0, fclose(compatibility_zip)); + + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + ASSERT_EQ(0, writer.StartEntry("compatibility.zip", kCompressStored)); + std::string compatibility_zip_content; + ASSERT_TRUE( + android::base::ReadFileToString(compatibility_zip_file.path, &compatibility_zip_content)); + ASSERT_EQ(0, + writer.WriteBytes(compatibility_zip_content.data(), compatibility_zip_content.size())); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + std::vector compatibility_info; + compatibility_info.push_back(malformed_xml); + // Malformed compatibility zip is expected to be rejected by libvintf. But we defer that to + // libvintf. + std::string err; + bool result = + android::vintf::VintfObjectRecovery::CheckCompatibility(compatibility_info, &err) == 0; + ASSERT_EQ(result, verify_package_compatibility(zip)); + CloseArchive(zip); +} + +TEST(InstallTest, verify_package_compatibility_with_libvintf_system_manifest_xml) { + static constexpr const char* system_manifest_xml_path = "/system/manifest.xml"; + if (access(system_manifest_xml_path, R_OK) == -1) { + GTEST_LOG_(INFO) << "Test skipped on devices w/o /system/manifest.xml."; + return; + } + std::string system_manifest_xml_content; + ASSERT_TRUE( + android::base::ReadFileToString(system_manifest_xml_path, &system_manifest_xml_content)); + TemporaryFile compatibility_zip_file; + FILE* compatibility_zip = fdopen(compatibility_zip_file.fd, "w"); + ZipWriter compatibility_zip_writer(compatibility_zip); + ASSERT_EQ(0, compatibility_zip_writer.StartEntry("system_manifest.xml", kCompressDeflated)); + ASSERT_EQ(0, compatibility_zip_writer.WriteBytes(system_manifest_xml_content.data(), + system_manifest_xml_content.size())); + ASSERT_EQ(0, compatibility_zip_writer.FinishEntry()); + ASSERT_EQ(0, compatibility_zip_writer.Finish()); + ASSERT_EQ(0, fclose(compatibility_zip)); + + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + ASSERT_EQ(0, writer.StartEntry("compatibility.zip", kCompressStored)); + std::string compatibility_zip_content; + ASSERT_TRUE( + android::base::ReadFileToString(compatibility_zip_file.path, &compatibility_zip_content)); + ASSERT_EQ(0, + writer.WriteBytes(compatibility_zip_content.data(), compatibility_zip_content.size())); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + std::vector compatibility_info; + compatibility_info.push_back(system_manifest_xml_content); + std::string err; + bool result = + android::vintf::VintfObjectRecovery::CheckCompatibility(compatibility_info, &err) == 0; + // Make sure the result is consistent with libvintf library. + ASSERT_EQ(result, verify_package_compatibility(zip)); + CloseArchive(zip); +} + TEST(InstallTest, update_binary_command_smoke) { #ifdef AB_OTA_UPDATER TemporaryFile temp_file; -- cgit v1.2.3 From 0a3e4dca5847bec8a0e0e7f67c8bccf208d01b80 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Fri, 21 Apr 2017 09:26:48 -0700 Subject: tests: Remove obsolete classes in applypatch_test. ApplyPatchFullTest and ApplyPatchDoubleCacheTest were used for defining testcases for file-based OTA. The testcases have already been removed by commit 40e144dae877654f75e65242535036058ea48f58. This CL removes the obsolete class defnitions. Bug: 37559618 Test: recovery_component_test on angler and marlin respectively. Change-Id: I3f4f1dfc8580cf010365e671de256f68bbc0d99a --- tests/component/applypatch_test.cpp | 51 ++----------------------------------- 1 file changed, 2 insertions(+), 49 deletions(-) (limited to 'tests/component') diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp index 5cba68f8a..6fdf78e47 100644 --- a/tests/component/applypatch_test.cpp +++ b/tests/component/applypatch_test.cpp @@ -105,9 +105,6 @@ class ApplyPatchTest : public ::testing::Test { static size_t new_size; }; -std::string ApplyPatchTest::old_file; -std::string ApplyPatchTest::new_file; - static void cp(const std::string& src, const std::string& tgt) { std::string cmd = "cp " + src + " " + tgt; system(cmd.c_str()); @@ -132,48 +129,8 @@ class ApplyPatchCacheTest : public ApplyPatchTest { } }; -class ApplyPatchFullTest : public ApplyPatchCacheTest { - public: - static void SetUpTestCase() { - ApplyPatchTest::SetUpTestCase(); - - output_f = new TemporaryFile(); - output_loc = std::string(output_f->path); - - struct FileContents fc; - - ASSERT_EQ(0, LoadFileContents(&rand_file[0], &fc)); - patches.push_back( - std::make_unique(VAL_BLOB, std::string(fc.data.begin(), fc.data.end()))); - - ASSERT_EQ(0, LoadFileContents(&patch_file[0], &fc)); - patches.push_back( - std::make_unique(VAL_BLOB, std::string(fc.data.begin(), fc.data.end()))); - } - - static void TearDownTestCase() { - delete output_f; - patches.clear(); - } - - static std::vector> patches; - static TemporaryFile* output_f; - static std::string output_loc; -}; - -class ApplyPatchDoubleCacheTest : public ApplyPatchFullTest { - public: - virtual void SetUp() { - ApplyPatchCacheTest::SetUp(); - cp(cache_file, "/cache/reallysaved.file"); - } - - virtual void TearDown() { - cp("/cache/reallysaved.file", cache_file); - ApplyPatchCacheTest::TearDown(); - } -}; - +std::string ApplyPatchTest::old_file; +std::string ApplyPatchTest::new_file; std::string ApplyPatchTest::rand_file; std::string ApplyPatchTest::patch_file; std::string ApplyPatchTest::cache_file; @@ -184,10 +141,6 @@ std::string ApplyPatchTest::bad_sha1_b; size_t ApplyPatchTest::old_size; size_t ApplyPatchTest::new_size; -std::vector> ApplyPatchFullTest::patches; -TemporaryFile* ApplyPatchFullTest::output_f; -std::string ApplyPatchFullTest::output_loc; - TEST_F(ApplyPatchTest, CheckModeSkip) { std::vector sha1s; ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); -- cgit v1.2.3 From 8ab28082b77767cab144c3eeaee358598d8e3007 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 25 Apr 2017 21:13:21 -0700 Subject: applypatch: Remove the obsolete support for "applypatch -s". The SpaceMode (applypatch -s) was used in amend script (cupcake) only, which has been removed since commit 9ce2ebf5d300eba5f6086583b0941ef68a3e4b42 (platform/build). The later (and current) edify script uses apply_patch_space(). Note that other modes (PatchMode, CheckMode) of applypatch executable are mostly used by install-recovery.sh script. Test: No active user of "applypatch -s". Test: recovery_component_test Change-Id: I1d689b7fedd3884077e88ed1d6c22f7a2198859d --- tests/component/applypatch_test.cpp | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'tests/component') diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp index 6fdf78e47..016fed9b1 100644 --- a/tests/component/applypatch_test.cpp +++ b/tests/component/applypatch_test.cpp @@ -377,20 +377,6 @@ TEST(ApplyPatchModesTest, CheckModeInvalidArgs) { ASSERT_EQ(2, applypatch_modes(2, (const char* []){ "applypatch", "-c" })); } -TEST(ApplyPatchModesTest, SpaceModeInvalidArgs) { - // Insufficient args. - ASSERT_EQ(2, applypatch_modes(2, (const char* []){ "applypatch", "-s" })); - - // Invalid bytes arg. - ASSERT_EQ(1, applypatch_modes(3, (const char* []){ "applypatch", "-s", "x" })); - - // 0 is invalid. - ASSERT_EQ(1, applypatch_modes(3, (const char* []){ "applypatch", "-s", "0" })); - - // 0x10 is fine. - ASSERT_EQ(0, applypatch_modes(3, (const char* []){ "applypatch", "-s", "0x10" })); -} - TEST(ApplyPatchModesTest, ShowLicenses) { ASSERT_EQ(0, applypatch_modes(2, (const char* []){ "applypatch", "-l" })); } -- cgit v1.2.3 From 83b0780dddcaddd661ac48f277f51f7cb6ac13f6 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 26 Apr 2017 14:30:56 -0700 Subject: Separate libupdate_verifier module and add testcases. Enable -Wall and expose verify_image() for testing purpose. Test: mmma bootable/recovery Test: recovery_component_test Change-Id: I1ee1db2a775bafdc1112e25a1bc7194d8d6aee4f --- tests/component/update_verifier_test.cpp | 83 ++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/component/update_verifier_test.cpp (limited to 'tests/component') diff --git a/tests/component/update_verifier_test.cpp b/tests/component/update_verifier_test.cpp new file mode 100644 index 000000000..73b4478aa --- /dev/null +++ b/tests/component/update_verifier_test.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +class UpdateVerifierTest : public ::testing::Test { + protected: + void SetUp() override { +#ifdef PRODUCT_SUPPORTS_VERITY + verity_supported = true; +#else + verity_supported = false; +#endif + } + + bool verity_supported; +}; + +TEST_F(UpdateVerifierTest, verify_image_no_care_map) { + // Non-existing care_map is allowed. + ASSERT_TRUE(verify_image("/doesntexist")); +} + +TEST_F(UpdateVerifierTest, verify_image_smoke) { + // This test relies on dm-verity support. + if (!verity_supported) { + GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support."; + return; + } + + // The care map file can have only two or four lines. + TemporaryFile temp_file; + std::string content = "system\n2,0,1"; + ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path)); + ASSERT_TRUE(verify_image(temp_file.path)); + + // Leading and trailing newlines should be accepted. + ASSERT_TRUE(android::base::WriteStringToFile("\n" + content + "\n\n", temp_file.path)); + ASSERT_TRUE(verify_image(temp_file.path)); +} + +TEST_F(UpdateVerifierTest, verify_image_wrong_lines) { + // The care map file can have only two or four lines. + TemporaryFile temp_file; + ASSERT_FALSE(verify_image(temp_file.path)); + + ASSERT_TRUE(android::base::WriteStringToFile("line1", temp_file.path)); + ASSERT_FALSE(verify_image(temp_file.path)); + + ASSERT_TRUE(android::base::WriteStringToFile("line1\nline2\nline3", temp_file.path)); + ASSERT_FALSE(verify_image(temp_file.path)); +} + +TEST_F(UpdateVerifierTest, verify_image_malformed_care_map) { + // This test relies on dm-verity support. + if (!verity_supported) { + GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support."; + return; + } + + TemporaryFile temp_file; + std::string content = "system\n2,1,0"; + ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path)); + ASSERT_FALSE(verify_image(temp_file.path)); +} -- cgit v1.2.3 From b656a154ea497c1a179079f082b0a0701453bec5 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 18 Apr 2017 23:54:29 -0700 Subject: Move sysMapFile and sysReleaseMap into MemMapping class. Test: recovery_component_test Test: recovery_unit_test Test: Apply an OTA on angler. Change-Id: I7170f03e4ce1fe06184ca1d7bcce0a695f33ac4d --- tests/component/updater_test.cpp | 4 ++-- tests/component/verifier_test.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/component') diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp index dc4b5d724..35e87fd56 100644 --- a/tests/component/updater_test.cpp +++ b/tests/component/updater_test.cpp @@ -570,7 +570,7 @@ TEST_F(UpdaterTest, block_image_update) { ASSERT_EQ(0, fclose(zip_file_ptr)); MemMapping map; - ASSERT_EQ(0, sysMapFile(zip_file.path, &map)); + ASSERT_TRUE(map.MapFile(zip_file.path)); ZipArchiveHandle handle; ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle)); @@ -646,7 +646,7 @@ TEST_F(UpdaterTest, new_data_short_write) { ASSERT_EQ(0, fclose(zip_file_ptr)); MemMapping map; - ASSERT_EQ(0, sysMapFile(zip_file.path, &map)); + ASSERT_TRUE(map.MapFile(zip_file.path)); ZipArchiveHandle handle; ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle)); diff --git a/tests/component/verifier_test.cpp b/tests/component/verifier_test.cpp index 2cfb6d301..5338f05c6 100644 --- a/tests/component/verifier_test.cpp +++ b/tests/component/verifier_test.cpp @@ -38,7 +38,7 @@ class VerifierTest : public testing::TestWithParam> { void SetUp() override { std::vector args = GetParam(); std::string package = from_testdata_base(args[0]); - if (sysMapFile(package.c_str(), &memmap) != 0) { + if (!memmap.MapFile(package)) { FAIL() << "Failed to mmap " << package << ": " << strerror(errno) << "\n"; } -- cgit v1.2.3 From ed13819a0d197d6851dca623707344ef2cad850b Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 1 May 2017 22:30:39 -0700 Subject: fuse_sideload: Change the minimal block size to 4096. run_fuse_sideload() is passing the block size as the max_read option, so it will only handle a request that involves at most two blocks at a time. However, the minimal allowed value was set to 1024 prior to this CL, which is inconsistent with the kernel code (fs/fuse/inode.c) that sets it to the greater of 4096 and the passed-in max_read option. This would fail the calls with a block size / max_read less than 4096 due to the wrongly computed block indices. Note that we didn't observe real issue in practice, because we have been using 64 KiB block sizes for both of adb and sdcard sideload calls. The issue only shows up in my local CL (to come later) that uses 1024 block size in run_fuse_sideload() tests. Test: recovery_component_test Test: adb sideload with the new recovery image on angler Change-Id: Id9f0cfea13d0d193dcb7cd41a1553a23739545f2 --- tests/component/sideload_test.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'tests/component') diff --git a/tests/component/sideload_test.cpp b/tests/component/sideload_test.cpp index ea93e9b84..40cfc6975 100644 --- a/tests/component/sideload_test.cpp +++ b/tests/component/sideload_test.cpp @@ -13,9 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include + #include -TEST(SideloadTest, fusedevice) { - ASSERT_NE(-1, access("/dev/fuse", R_OK | W_OK)); +#include "fuse_sideload.h" + +TEST(SideloadTest, fuse_device) { + ASSERT_EQ(0, access("/dev/fuse", R_OK | W_OK)); +} + +TEST(SideloadTest, run_fuse_sideload_wrong_parameters) { + provider_vtab vtab; + vtab.close = [](void*) {}; + + ASSERT_EQ(-1, run_fuse_sideload(&vtab, nullptr, 4096, 4095)); + ASSERT_EQ(-1, run_fuse_sideload(&vtab, nullptr, 4096, (1 << 22) + 1)); + + // Too many blocks. + ASSERT_EQ(-1, run_fuse_sideload(&vtab, nullptr, ((1 << 18) + 1) * 4096, 4096)); } -- cgit v1.2.3 From 00d5757186c279ba5e8a52a6f5209be3e7152025 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 2 May 2017 15:48:54 -0700 Subject: Add a binary path param to update_binary_command(). This allows writing native tests for non-A/B update_binary_command(). Prior to this CL, it was extracting the updater to a hard-coded location (/tmp/update_binary) that's not available under the test environment. Test: recovery_component_test on angler and marlin respectively. Test: Sideload OTA packages on angler and marlin respectively. Change-Id: I78b9cc211d90c0a16a84e94e339b65759300e2a8 --- tests/component/install_test.cpp | 84 +++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 10 deletions(-) (limited to 'tests/component') diff --git a/tests/component/install_test.cpp b/tests/component/install_test.cpp index 40201d76f..968196fc0 100644 --- a/tests/component/install_test.cpp +++ b/tests/component/install_test.cpp @@ -15,6 +15,8 @@ */ #include +#include +#include #include #include @@ -225,18 +227,62 @@ TEST(InstallTest, update_binary_command_smoke) { ZipArchiveHandle zip; ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + ZipString payload_name("payload.bin"); + ZipEntry payload_entry; + ASSERT_EQ(0, FindEntry(zip, payload_name, &payload_entry)); int status_fd = 10; - std::string path = "/path/to/update.zip"; + std::string package = "/path/to/update.zip"; + std::string binary_path = "/sbin/update_engine_sideload"; std::vector cmd; - ASSERT_EQ(0, update_binary_command(path, zip, 0, status_fd, &cmd)); - ASSERT_EQ("/sbin/update_engine_sideload", cmd[0]); - ASSERT_EQ("--payload=file://" + path, cmd[1]); + ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); + ASSERT_EQ(5U, cmd.size()); + ASSERT_EQ(binary_path, cmd[0]); + ASSERT_EQ("--payload=file://" + package, cmd[1]); + ASSERT_EQ("--offset=" + std::to_string(payload_entry.offset), cmd[2]); ASSERT_EQ("--headers=" + properties, cmd[3]); ASSERT_EQ("--status_fd=" + std::to_string(status_fd), cmd[4]); CloseArchive(zip); #else - // Cannot test update_binary_command() because it tries to extract update-binary to /tmp. - GTEST_LOG_(INFO) << "Test skipped on non-A/B device."; + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + static constexpr const char* UPDATE_BINARY_NAME = "META-INF/com/google/android/update-binary"; + ASSERT_EQ(0, writer.StartEntry(UPDATE_BINARY_NAME, kCompressStored)); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + int status_fd = 10; + std::string package = "/path/to/update.zip"; + TemporaryDir td; + std::string binary_path = std::string(td.path) + "/update_binary"; + std::vector cmd; + ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); + ASSERT_EQ(4U, cmd.size()); + ASSERT_EQ(binary_path, cmd[0]); + ASSERT_EQ("3", cmd[1]); // RECOVERY_API_VERSION + ASSERT_EQ(std::to_string(status_fd), cmd[2]); + ASSERT_EQ(package, cmd[3]); + struct stat sb; + ASSERT_EQ(0, stat(binary_path.c_str(), &sb)); + ASSERT_EQ(static_cast(0755), sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); + + // With non-zero retry count. update_binary will be removed automatically. + cmd.clear(); + ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 2, status_fd, &cmd)); + ASSERT_EQ(5U, cmd.size()); + ASSERT_EQ(binary_path, cmd[0]); + ASSERT_EQ("3", cmd[1]); // RECOVERY_API_VERSION + ASSERT_EQ(std::to_string(status_fd), cmd[2]); + ASSERT_EQ(package, cmd[3]); + ASSERT_EQ("retry", cmd[4]); + sb = {}; + ASSERT_EQ(0, stat(binary_path.c_str(), &sb)); + ASSERT_EQ(static_cast(0755), sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); + + CloseArchive(zip); #endif // AB_OTA_UPDATER } @@ -267,12 +313,30 @@ TEST(InstallTest, update_binary_command_invalid) { ZipArchiveHandle zip; ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); int status_fd = 10; - std::string path = "/path/to/update.zip"; + std::string package = "/path/to/update.zip"; + std::string binary_path = "/sbin/update_engine_sideload"; std::vector cmd; - ASSERT_EQ(INSTALL_CORRUPT, update_binary_command(path, zip, 0, status_fd, &cmd)); + ASSERT_EQ(INSTALL_CORRUPT, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); CloseArchive(zip); #else - // Cannot test update_binary_command() because it tries to extract update-binary to /tmp. - GTEST_LOG_(INFO) << "Test skipped on non-A/B device."; + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.fd, "w"); + ZipWriter writer(zip_file); + // The archive must have something to be opened correctly. + ASSERT_EQ(0, writer.StartEntry("dummy_entry", 0)); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + // Missing update binary. + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + int status_fd = 10; + std::string package = "/path/to/update.zip"; + TemporaryDir td; + std::string binary_path = std::string(td.path) + "/update_binary"; + std::vector cmd; + ASSERT_EQ(INSTALL_CORRUPT, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); + CloseArchive(zip); #endif // AB_OTA_UPDATER } -- cgit v1.2.3 From ce5fa5e5384508655c804519d428a402bb3df1d9 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Mon, 15 May 2017 12:32:33 -0700 Subject: Print SHA1 of the patch if bsdiff fails with data error This will help us to identify the patch corruption. Meanwhile fix a wrong size parameter passed to bspatch. (patch->data.size() into patch->data.size() - patch_offset). Also remove the only usage of "ApplyBSDiffPatchMem()" and inline its Sink function for simplicity. Bug: 37855643 Test: Prints SHA1 for corrupted patch in imgdiff_test. Change-Id: Ibf2db8c08b0ded1409bb7c91a3547a6bf99c601d --- tests/component/imgdiff_test.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'tests/component') diff --git a/tests/component/imgdiff_test.cpp b/tests/component/imgdiff_test.cpp index 7d00a3d53..6f5960bbd 100644 --- a/tests/component/imgdiff_test.cpp +++ b/tests/component/imgdiff_test.cpp @@ -551,3 +551,42 @@ TEST(ImgdiffTest, image_mode_single_entry_long) { verify_patched_image(src, patch, tgt); } + +TEST(ImgpatchTest, image_mode_patch_corruption) { + // src: "abcdefgh" + gzipped "xyz" (echo -n "xyz" | gzip -f | hd). + const std::vector src_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', '\x1f', '\x8b', '\x08', '\x00', '\xc4', '\x1e', + '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xac', + '\x02', '\x00', '\x67', '\xba', '\x8e', '\xeb', '\x03', + '\x00', '\x00', '\x00' }; + const std::string src(src_data.cbegin(), src_data.cend()); + TemporaryFile src_file; + ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path)); + + // tgt: "abcdefgxyz" + gzipped "xxyyzz". + const std::vector tgt_data = { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z', '\x1f', '\x8b', + '\x08', '\x00', '\x62', '\x1f', '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xa8', '\xac', + '\xac', '\xaa', '\x02', '\x00', '\x96', '\x30', '\x06', '\xb7', '\x06', '\x00', '\x00', '\x00' + }; + const std::string tgt(tgt_data.cbegin(), tgt_data.cend()); + TemporaryFile tgt_file; + ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path)); + + TemporaryFile patch_file; + std::vector args = { + "imgdiff", src_file.path, tgt_file.path, patch_file.path, + }; + ASSERT_EQ(0, imgdiff(args.size(), args.data())); + + // Verify. + std::string patch; + ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch)); + verify_patched_image(src, patch, tgt); + + // Corrupt the end of the patch and expect the ApplyImagePatch to fail. + patch.insert(patch.end() - 10, 10, '0'); + ASSERT_EQ(-1, ApplyImagePatch(reinterpret_cast(src.data()), src.size(), + reinterpret_cast(patch.data()), patch.size(), + [](const unsigned char* /*data*/, size_t len) { return len; })); +} -- cgit v1.2.3 From 8ed9738b62b075205a81489b01ec882520da183a Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Mon, 8 May 2017 13:41:28 -0400 Subject: update_verifier: Support AVB. When using AVB, PRODUCT_SUPPORTS_VERITY is not set so check for BOARD_ENABLE_AVB as well. Also AVB sets up the root filesystem as 'vroot' so map that to 'system' since this is what is expected. Managed to test at least that the code is at least compiled in: $ fastboot --set-active=_a Setting current slot to 'a'... OKAY [ 0.023s] finished. total time: 0.023s $ fastboot reboot rebooting... finished. total time: 0.050s $ adb wait-for-device $ adb logcat |grep update_verifier 03-04 05:28:56.773 630 630 I /system/bin/update_verifier: Started with arg 1: nonencrypted 03-04 05:28:56.776 630 630 I /system/bin/update_verifier: Booting slot 0: isSlotMarkedSuccessful=0 03-04 05:28:56.776 630 630 W /system/bin/update_verifier: Failed to open /data/ota_package/care_map.txt: No such file or directory 03-04 05:28:56.788 630 630 I /system/bin/update_verifier: Marked slot 0 as booted successfully. 03-04 05:28:56.788 630 630 I /system/bin/update_verifier: Leaving update_verifier. Bug: None Test: Manually tested on device using AVB bootloader. Change-Id: I13c0fe1cc5d0f397e36f5e62fcc05c8dfee5fd85 --- tests/component/update_verifier_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/component') diff --git a/tests/component/update_verifier_test.cpp b/tests/component/update_verifier_test.cpp index 73b4478aa..5fc7ef63f 100644 --- a/tests/component/update_verifier_test.cpp +++ b/tests/component/update_verifier_test.cpp @@ -24,7 +24,7 @@ class UpdateVerifierTest : public ::testing::Test { protected: void SetUp() override { -#ifdef PRODUCT_SUPPORTS_VERITY +#if defined(PRODUCT_SUPPORTS_VERITY) || defined(BOARD_AVB_ENABLE) verity_supported = true; #else verity_supported = false; -- cgit v1.2.3 From bb7e005a7906b02857ba328c5dfb11f1f3cb938e Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Thu, 22 Jun 2017 17:35:06 -0700 Subject: Remove the obsolete package_extract_dir() test package_extract_dir() was removed in go/aog/402383, and the corresponding UpdaterTest should be removed as well. Bug: 62918308 Test: mma && code search Change-Id: Ibe9c473a5d41d2fa4d26abca5684e71b104891b0 --- tests/component/updater_test.cpp | 96 ---------------------------------------- 1 file changed, 96 deletions(-) (limited to 'tests/component') diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp index 35e87fd56..0298a7645 100644 --- a/tests/component/updater_test.cpp +++ b/tests/component/updater_test.cpp @@ -224,102 +224,6 @@ TEST_F(UpdaterTest, file_getprop) { expect("", script6.c_str(), kNoCause); } -TEST_F(UpdaterTest, package_extract_dir) { - // package_extract_dir expects 2 arguments. - expect(nullptr, "package_extract_dir()", kArgsParsingFailure); - expect(nullptr, "package_extract_dir(\"arg1\")", kArgsParsingFailure); - expect(nullptr, "package_extract_dir(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); - - std::string zip_path = from_testdata_base("ziptest_valid.zip"); - ZipArchiveHandle handle; - ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle)); - - // Need to set up the ziphandle. - UpdaterInfo updater_info; - updater_info.package_zip = handle; - - // Extract "b/c.txt" and "b/d.txt" with package_extract_dir("b", ""). - TemporaryDir td; - std::string temp_dir(td.path); - std::string script("package_extract_dir(\"b\", \"" + temp_dir + "\")"); - expect("t", script.c_str(), kNoCause, &updater_info); - - // Verify. - std::string data; - std::string file_c = temp_dir + "/c.txt"; - ASSERT_TRUE(android::base::ReadFileToString(file_c, &data)); - ASSERT_EQ(kCTxtContents, data); - - std::string file_d = temp_dir + "/d.txt"; - ASSERT_TRUE(android::base::ReadFileToString(file_d, &data)); - ASSERT_EQ(kDTxtContents, data); - - // Modify the contents in order to retry. It's expected to be overwritten. - ASSERT_TRUE(android::base::WriteStringToFile("random", file_c)); - ASSERT_TRUE(android::base::WriteStringToFile("random", file_d)); - - // Extract again and verify. - expect("t", script.c_str(), kNoCause, &updater_info); - - ASSERT_TRUE(android::base::ReadFileToString(file_c, &data)); - ASSERT_EQ(kCTxtContents, data); - ASSERT_TRUE(android::base::ReadFileToString(file_d, &data)); - ASSERT_EQ(kDTxtContents, data); - - // Clean up the temp files under td. - ASSERT_EQ(0, unlink(file_c.c_str())); - ASSERT_EQ(0, unlink(file_d.c_str())); - - // Extracting "b/" (with slash) should give the same result. - script = "package_extract_dir(\"b/\", \"" + temp_dir + "\")"; - expect("t", script.c_str(), kNoCause, &updater_info); - - ASSERT_TRUE(android::base::ReadFileToString(file_c, &data)); - ASSERT_EQ(kCTxtContents, data); - ASSERT_TRUE(android::base::ReadFileToString(file_d, &data)); - ASSERT_EQ(kDTxtContents, data); - - ASSERT_EQ(0, unlink(file_c.c_str())); - ASSERT_EQ(0, unlink(file_d.c_str())); - - // Extracting "" is allowed. The entries will carry the path name. - script = "package_extract_dir(\"\", \"" + temp_dir + "\")"; - expect("t", script.c_str(), kNoCause, &updater_info); - - std::string file_a = temp_dir + "/a.txt"; - ASSERT_TRUE(android::base::ReadFileToString(file_a, &data)); - ASSERT_EQ(kATxtContents, data); - std::string file_b = temp_dir + "/b.txt"; - ASSERT_TRUE(android::base::ReadFileToString(file_b, &data)); - ASSERT_EQ(kBTxtContents, data); - std::string file_b_c = temp_dir + "/b/c.txt"; - ASSERT_TRUE(android::base::ReadFileToString(file_b_c, &data)); - ASSERT_EQ(kCTxtContents, data); - std::string file_b_d = temp_dir + "/b/d.txt"; - ASSERT_TRUE(android::base::ReadFileToString(file_b_d, &data)); - ASSERT_EQ(kDTxtContents, data); - - ASSERT_EQ(0, unlink(file_a.c_str())); - ASSERT_EQ(0, unlink(file_b.c_str())); - ASSERT_EQ(0, unlink(file_b_c.c_str())); - ASSERT_EQ(0, unlink(file_b_d.c_str())); - ASSERT_EQ(0, rmdir((temp_dir + "/b").c_str())); - - // Extracting non-existent entry should still give "t". - script = "package_extract_dir(\"doesntexist\", \"" + temp_dir + "\")"; - expect("t", script.c_str(), kNoCause, &updater_info); - - // Only relative zip_path is allowed. - script = "package_extract_dir(\"/b\", \"" + temp_dir + "\")"; - expect("", script.c_str(), kNoCause, &updater_info); - - // Only absolute dest_path is allowed. - script = "package_extract_dir(\"b\", \"path\")"; - expect("", script.c_str(), kNoCause, &updater_info); - - CloseArchive(handle); -} - // TODO: Test extracting to block device. TEST_F(UpdaterTest, package_extract_file) { // package_extract_file expects 1 or 2 arguments. -- cgit v1.2.3 From 14ebc1e5ae6968424eb242f3b0330f82e475a1e4 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Wed, 5 Jul 2017 12:04:07 -0700 Subject: Fix a rare failure for imgdiff when random data equals gzip header In a rare case, a random chunk will pass both the gzip header check and the inflation process; but fail the uncompressed length check in the footer. This leads to a imgdiff failure. So, we should treat this chunk as 'normal' instead of 'inflated' while generating the patch. Bug: 63334984 Test: imgdiff generates patch successfully on previous failing images. Change-Id: Ice84f22d3653bce9756bda91e70528c0d2f264a0 --- tests/component/imgdiff_test.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'tests/component') diff --git a/tests/component/imgdiff_test.cpp b/tests/component/imgdiff_test.cpp index 6f5960bbd..bf25aebb0 100644 --- a/tests/component/imgdiff_test.cpp +++ b/tests/component/imgdiff_test.cpp @@ -328,6 +328,39 @@ TEST(ImgdiffTest, image_mode_simple) { verify_patched_image(src, patch, tgt); } +TEST(ImgdiffTest, image_mode_bad_gzip) { + // Modify the uncompressed length in the gzip footer. + const std::vector src_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', '\x1f', '\x8b', '\x08', '\x00', '\xc4', '\x1e', + '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xac', + '\x02', '\x00', '\x67', '\xba', '\x8e', '\xeb', '\x03', + '\xff', '\xff', '\xff' }; + const std::string src(src_data.cbegin(), src_data.cend()); + TemporaryFile src_file; + ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path)); + + // Modify the uncompressed length in the gzip footer. + const std::vector tgt_data = { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z', '\x1f', '\x8b', + '\x08', '\x00', '\x62', '\x1f', '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xa8', '\xac', + '\xac', '\xaa', '\x02', '\x00', '\x96', '\x30', '\x06', '\xb7', '\x06', '\xff', '\xff', '\xff' + }; + const std::string tgt(tgt_data.cbegin(), tgt_data.cend()); + TemporaryFile tgt_file; + ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path)); + + TemporaryFile patch_file; + std::vector args = { + "imgdiff", src_file.path, tgt_file.path, patch_file.path, + }; + ASSERT_EQ(0, imgdiff(args.size(), args.data())); + + // Verify. + std::string patch; + ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch)); + verify_patched_image(src, patch, tgt); +} + TEST(ImgdiffTest, image_mode_different_num_chunks) { // src: "abcdefgh" + gzipped "xyz" (echo -n "xyz" | gzip -f | hd) + gzipped "test". const std::vector src_data = { -- cgit v1.2.3 From 107a34f9fc2cb2cfbb1ff83631f778c2c147db22 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Thu, 29 Jun 2017 17:04:21 -0700 Subject: Add support to decompress brotli compressed new data Add a new writer that can decode the brotli-compressed system/vendor new data stored in the OTA zip. Brotli generally gives better compression rate at the cost of slightly increased time consumption. The patch.dat is already compressed by BZ; so there's no point to further compress it. For the given 1.9G bullhead system image: Size: 875M -> 787M; ~10% reduction of package size. Time: 147s -> 153s; ~4% increase of the block_image_update execution time. (I guess I/O takes much longer time than decompression.) Also it takes 4 minutes to compress the system image on my local machine, 3 more minutes than zip. Test: recovery tests pass && apply a full OTA with brotli compressed system/vendor.new.dat on bullhead Change-Id: I232335ebf662a9c55579ca073ad45265700a621e --- tests/component/updater_test.cpp | 67 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'tests/component') diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp index 0298a7645..357a39ef7 100644 --- a/tests/component/updater_test.cpp +++ b/tests/component/updater_test.cpp @@ -15,10 +15,12 @@ */ #include +#include #include #include #include +#include #include #include #include @@ -29,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -576,4 +579,68 @@ TEST_F(UpdaterTest, new_data_short_write) { std::string script_exact_data = "block_image_update(\"" + std::string(update_file.path) + R"(", package_extract_file("transfer_list"), "exact_new_data", "patch_data"))"; expect("t", script_exact_data.c_str(), kNoCause, &updater_info); + CloseArchive(handle); +} + +TEST_F(UpdaterTest, brotli_new_data) { + // Create a zip file with new_data. + TemporaryFile zip_file; + FILE* zip_file_ptr = fdopen(zip_file.fd, "wb"); + ZipWriter zip_writer(zip_file_ptr); + + // Add a brotli compressed new data entry. + ASSERT_EQ(0, zip_writer.StartEntry("new.dat.br", 0)); + + auto generator = []() { return rand() % 128; }; + // Generate 2048 blocks of random data. + std::string brotli_new_data; + brotli_new_data.reserve(4096 * 2048); + generate_n(back_inserter(brotli_new_data), 4096 * 2048, generator); + + size_t encoded_size = BrotliEncoderMaxCompressedSize(brotli_new_data.size()); + std::vector encoded_data(encoded_size); + ASSERT_TRUE(BrotliEncoderCompress( + BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, brotli_new_data.size(), + reinterpret_cast(brotli_new_data.data()), &encoded_size, encoded_data.data())); + + ASSERT_EQ(0, zip_writer.WriteBytes(encoded_data.data(), encoded_size)); + ASSERT_EQ(0, zip_writer.FinishEntry()); + // Add a dummy patch data. + ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0)); + ASSERT_EQ(0, zip_writer.FinishEntry()); + + std::vector transfer_list = { + "4", "2048", "0", "0", "new 4,0,512,512,1024", "new 2,1024,2048", + }; + ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0)); + std::string commands = android::base::Join(transfer_list, '\n'); + ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size())); + ASSERT_EQ(0, zip_writer.FinishEntry()); + ASSERT_EQ(0, zip_writer.Finish()); + ASSERT_EQ(0, fclose(zip_file_ptr)); + + MemMapping map; + ASSERT_TRUE(map.MapFile(zip_file.path)); + ZipArchiveHandle handle; + ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle)); + + // Set up the handler, command_pipe, patch offset & length. + UpdaterInfo updater_info; + updater_info.package_zip = handle; + TemporaryFile temp_pipe; + updater_info.cmd_pipe = fopen(temp_pipe.path, "wb"); + updater_info.package_zip_addr = map.addr; + updater_info.package_zip_len = map.length; + + // Check if we can decompress the new data correctly. + TemporaryFile update_file; + std::string script_new_data = + "block_image_update(\"" + std::string(update_file.path) + + R"(", package_extract_file("transfer_list"), "new.dat.br", "patch_data"))"; + expect("t", script_new_data.c_str(), kNoCause, &updater_info); + + std::string updated_content; + ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_content)); + ASSERT_EQ(brotli_new_data, updated_content); + CloseArchive(handle); } -- cgit v1.2.3 From de6735e80cc65be50381388640d94f1b1d0f20fa Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Mon, 10 Jul 2017 15:13:33 -0700 Subject: Fix the android-cloexec-* warnings in bootable/recovery Add the O_CLOEXEC or 'e' accordingly. Bug: 63510015 Test: recovery tests pass Change-Id: I7094bcc6af22c9687eb535116b2ca6a59178b303 --- tests/component/updater_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests/component') diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp index 357a39ef7..01b86f224 100644 --- a/tests/component/updater_test.cpp +++ b/tests/component/updater_test.cpp @@ -485,7 +485,7 @@ TEST_F(UpdaterTest, block_image_update) { UpdaterInfo updater_info; updater_info.package_zip = handle; TemporaryFile temp_pipe; - updater_info.cmd_pipe = fopen(temp_pipe.path, "wb"); + updater_info.cmd_pipe = fopen(temp_pipe.path, "wbe"); updater_info.package_zip_addr = map.addr; updater_info.package_zip_len = map.length; @@ -561,7 +561,7 @@ TEST_F(UpdaterTest, new_data_short_write) { UpdaterInfo updater_info; updater_info.package_zip = handle; TemporaryFile temp_pipe; - updater_info.cmd_pipe = fopen(temp_pipe.path, "wb"); + updater_info.cmd_pipe = fopen(temp_pipe.path, "wbe"); updater_info.package_zip_addr = map.addr; updater_info.package_zip_len = map.length; -- cgit v1.2.3 From d9759e8a7ba89d7005d86cf8c8e3e561d04e56a4 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Fri, 21 Jul 2017 21:06:52 +0000 Subject: Fix a case when brotli writer fails to write last few blocks of data receive_new_data may exit too early if the zip processor has sent all the raw data. As a result, the last few 'new' commands will fail even though the brotli decoder has more output in its buffer. Restruct the code so that 'NewThreadInfo' owns the decoder state solely; and receive_brotli_new_data is responsible for the decompression. Also reduce the test data size to 100 blocks to avoid the test timeout. Bug: 63802629 Test: recovery_component_test. on bullhead, apply full updates with and w/o brotli compressed entries, apply an incremental update. Change-Id: Id429b2c2f31951897961525609fa12c3657216b7 (cherry picked from commit 6ed175d5412deeaec9691f85757e45452407b8e3) --- tests/component/updater_test.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'tests/component') diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp index 01b86f224..6c341c111 100644 --- a/tests/component/updater_test.cpp +++ b/tests/component/updater_test.cpp @@ -592,10 +592,10 @@ TEST_F(UpdaterTest, brotli_new_data) { ASSERT_EQ(0, zip_writer.StartEntry("new.dat.br", 0)); auto generator = []() { return rand() % 128; }; - // Generate 2048 blocks of random data. + // Generate 100 blocks of random data. std::string brotli_new_data; - brotli_new_data.reserve(4096 * 2048); - generate_n(back_inserter(brotli_new_data), 4096 * 2048, generator); + brotli_new_data.reserve(4096 * 100); + generate_n(back_inserter(brotli_new_data), 4096 * 100, generator); size_t encoded_size = BrotliEncoderMaxCompressedSize(brotli_new_data.size()); std::vector encoded_data(encoded_size); @@ -609,8 +609,19 @@ TEST_F(UpdaterTest, brotli_new_data) { ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0)); ASSERT_EQ(0, zip_writer.FinishEntry()); + // Write a few small chunks of new data, then a large chunk, and finally a few small chunks. + // This helps us to catch potential short writes. std::vector transfer_list = { - "4", "2048", "0", "0", "new 4,0,512,512,1024", "new 2,1024,2048", + "4", + "100", + "0", + "0", + "new 2,0,1", + "new 2,1,2", + "new 4,2,50,50,97", + "new 2,97,98", + "new 2,98,99", + "new 2,99,100", }; ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0)); std::string commands = android::base::Join(transfer_list, '\n'); -- cgit v1.2.3 From 5cee24f4f1aa3f53c0b386abb2797c1e0f3088eb Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 24 Jul 2017 09:22:39 -0700 Subject: tests: Add a test to cover legacy care_map.txt handling. This is to cover the code added by commit 5a1dee01df3af346729b5791606b72d59b8e9815, where an O update_verifier should not reject N care_map.txt. Bug: 63544345 Test: recovery_component_test passes on marlin. Change-Id: Ia944e16cba3cc635098b3ffd92842d725b570fec (cherry picked from commit c319613e06f996aed32da3a1c3e93bf9b04ffa95) --- tests/component/update_verifier_test.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tests/component') diff --git a/tests/component/update_verifier_test.cpp b/tests/component/update_verifier_test.cpp index 5fc7ef63f..b04e1185e 100644 --- a/tests/component/update_verifier_test.cpp +++ b/tests/component/update_verifier_test.cpp @@ -81,3 +81,16 @@ TEST_F(UpdateVerifierTest, verify_image_malformed_care_map) { ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path)); ASSERT_FALSE(verify_image(temp_file.path)); } + +TEST_F(UpdateVerifierTest, verify_image_legacy_care_map) { + // This test relies on dm-verity support. + if (!verity_supported) { + GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support."; + return; + } + + TemporaryFile temp_file; + std::string content = "/dev/block/bootdevice/by-name/system\n2,1,0"; + ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path)); + ASSERT_TRUE(verify_image(temp_file.path)); +} -- cgit v1.2.3