diff options
author | Tianjie Xu <xunchang@google.com> | 2018-04-25 17:19:20 -0700 |
---|---|---|
committer | Tianjie Xu <xunchang@google.com> | 2018-04-25 20:00:56 -0700 |
commit | 9e1ccd47b49199b728afb06b28aa7987b5d65960 (patch) | |
tree | d9f64a67bd53fc014c562e34d726f8f3b9fca1a8 | |
parent | 4816fc1c46d1e2baacccbb8a335d03abdfd98800 (diff) | |
download | android_bootable_recovery-9e1ccd47b49199b728afb06b28aa7987b5d65960.tar.gz android_bootable_recovery-9e1ccd47b49199b728afb06b28aa7987b5d65960.tar.bz2 android_bootable_recovery-9e1ccd47b49199b728afb06b28aa7987b5d65960.zip |
Dump the uncompressed data's SHA1 to debug flaky tests
Dump the SHA1 of the uncompressed data in applypatch to confirm if we
are at least doing the bspatch part correctly. (I expect so since the actual
length of the uncompressed data matches the expected length).
Also try to decompress the deflate chunk inside the recovery image for
these two flacky tests. In theory, there shouldn't be randomness in
zlib; so we would know if we process the data wrongly if the deflate fails
to decompress.
Bug: 67849209
Test: recovery_component_test
Change-Id: Id947522153b1eeb0d10d161298a96fb045f92018
-rw-r--r-- | applypatch/imgpatch.cpp | 24 | ||||
-rw-r--r-- | tests/component/applypatch_test.cpp | 54 |
2 files changed, 75 insertions, 3 deletions
diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp index 9794a487..b06a64f2 100644 --- a/applypatch/imgpatch.cpp +++ b/applypatch/imgpatch.cpp @@ -38,6 +38,7 @@ #include <zlib.h> #include "edify/expr.h" +#include "otautil/print_sha1.h" static inline int64_t Read8(const void *address) { return android::base::get_unaligned<int64_t>(address); @@ -76,8 +77,10 @@ static bool ApplyBSDiffPatchAndStreamOutput(const uint8_t* src_data, size_t src_ size_t actual_target_length = 0; size_t total_written = 0; static constexpr size_t buffer_size = 32768; + SHA_CTX sha_ctx; + SHA1_Init(&sha_ctx); auto compression_sink = [&strm, &actual_target_length, &expected_target_length, &total_written, - &ret, &sink](const uint8_t* data, size_t len) -> size_t { + &ret, &sink, &sha_ctx](const uint8_t* data, size_t len) -> size_t { // The input patch length for an update never exceeds INT_MAX. strm.avail_in = len; strm.next_in = data; @@ -98,6 +101,20 @@ static bool ApplyBSDiffPatchAndStreamOutput(const uint8_t* src_data, size_t src_ size_t have = buffer_size - strm.avail_out; total_written += have; + + // TODO(b/67849209) Remove after debugging the unit test flakiness. + if (android::base::GetMinimumLogSeverity() <= android::base::LogSeverity::DEBUG && + have != 0) { + SHA1_Update(&sha_ctx, data, len - strm.avail_in); + SHA_CTX temp_ctx; + memcpy(&temp_ctx, &sha_ctx, sizeof(SHA_CTX)); + uint8_t digest_so_far[SHA_DIGEST_LENGTH]; + SHA1_Final(digest_so_far, &temp_ctx); + LOG(DEBUG) << "Processed " << actual_target_length + len - strm.avail_in + << " bytes input data in the sink function, sha1 so far: " + << short_sha1(digest_so_far); + } + if (sink(buffer.data(), have) != have) { LOG(ERROR) << "Failed to write " << have << " compressed bytes to output."; return 0; @@ -111,6 +128,11 @@ static bool ApplyBSDiffPatchAndStreamOutput(const uint8_t* src_data, size_t src_ int bspatch_result = ApplyBSDiffPatch(src_data, src_len, patch, patch_offset, compression_sink); deflateEnd(&strm); + if (android::base::GetMinimumLogSeverity() <= android::base::LogSeverity::DEBUG) { + uint8_t digest[SHA_DIGEST_LENGTH]; + SHA1_Final(digest, &sha_ctx); + LOG(DEBUG) << "sha1 of " << actual_target_length << " bytes input data: " << short_sha1(digest); + } if (bspatch_result != 0) { return false; } diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp index 292d76e4..04055b9f 100644 --- a/tests/component/applypatch_test.cpp +++ b/tests/component/applypatch_test.cpp @@ -37,6 +37,7 @@ #include <android-base/unique_fd.h> #include <bsdiff/bsdiff.h> #include <openssl/sha.h> +#include <zlib.h> #include "applypatch/applypatch.h" #include "applypatch/applypatch_modes.h" @@ -46,6 +47,47 @@ using namespace std::string_literals; +// TODO(b/67849209) Remove after debug the flakiness. +static void DecompressAndDumpRecoveryImage(const std::string& image_path) { + // Expected recovery_image structure + // chunk normal: 45066 bytes + // chunk deflate: 479442 bytes + // chunk normal: 5199 bytes + std::string recovery_content; + ASSERT_TRUE(android::base::ReadFileToString(image_path, &recovery_content)); + ASSERT_GT(recovery_content.size(), 45066 + 5199); + + z_stream strm = {}; + strm.avail_in = recovery_content.size() - 45066 - 5199; + strm.next_in = + const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(recovery_content.data())) + 45066; + + ASSERT_EQ(Z_OK, inflateInit2(&strm, -15)); + + constexpr unsigned int BUFFER_SIZE = 32768; + std::vector<uint8_t> uncompressed_data(BUFFER_SIZE); + size_t uncompressed_length = 0; + SHA_CTX ctx; + SHA1_Init(&ctx); + int ret; + do { + strm.avail_out = BUFFER_SIZE; + strm.next_out = uncompressed_data.data(); + + ret = inflate(&strm, Z_NO_FLUSH); + ASSERT_GE(ret, 0); + + SHA1_Update(&ctx, uncompressed_data.data(), BUFFER_SIZE - strm.avail_out); + uncompressed_length += BUFFER_SIZE - strm.avail_out; + } while (ret != Z_STREAM_END); + inflateEnd(&strm); + + uint8_t digest[SHA_DIGEST_LENGTH]; + SHA1_Final(digest, &ctx); + GTEST_LOG_(INFO) << "uncompressed length " << uncompressed_length + << " sha1: " << short_sha1(digest); +} + static void sha1sum(const std::string& fname, std::string* sha1, size_t* fsize = nullptr) { ASSERT_TRUE(sha1 != nullptr); @@ -317,7 +359,11 @@ TEST_F(ApplyPatchModesTest, PatchModeEmmcTargetWithoutBonusFile) { recovery_img_sha1.c_str(), recovery_img_size_arg.c_str(), patch_arg.c_str() }; - ASSERT_EQ(0, applypatch_modes(args.size(), args.data())); + + if (applypatch_modes(args.size(), args.data()) != 0) { + DecompressAndDumpRecoveryImage(tgt_file.path); + FAIL(); + } } TEST_F(ApplyPatchModesTest, PatchModeEmmcTargetWithMultiplePatches) { @@ -360,7 +406,11 @@ TEST_F(ApplyPatchModesTest, PatchModeEmmcTargetWithMultiplePatches) { for (const auto& arg : args) { printf(" %s\n", arg); } - ASSERT_EQ(0, applypatch_modes(args.size(), args.data())); + + if (applypatch_modes(args.size(), args.data()) != 0) { + DecompressAndDumpRecoveryImage(tgt_file.path); + FAIL(); + } } // Ensures that applypatch works with a bsdiff based recovery-from-boot.p. |