aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorTianjie Xu2017-10-20 16:11:20 -0500
committerandroid-build-merger2017-10-20 16:11:20 -0500
commit85fca1fc57dc0d67ee7417a106d03a1996690c10 (patch)
treecf5670c73c771763f045047217059e635da57795 /tests
parent9bc56553dd63b3f8fa6662f03c75a825c79ff6f4 (diff)
parent9831ef389b3beaa7a8d23cc77d76888a3021a2f9 (diff)
downloadplatform-bootable-recovery-85fca1fc57dc0d67ee7417a106d03a1996690c10.tar.gz
platform-bootable-recovery-85fca1fc57dc0d67ee7417a106d03a1996690c10.tar.xz
platform-bootable-recovery-85fca1fc57dc0d67ee7417a106d03a1996690c10.zip
Merge "Finish the new data receiver when update fails"
am: 9831ef389b Change-Id: I62be2406eede1f9e02ee4ca45ffca6fd2283ef0a
Diffstat (limited to 'tests')
-rw-r--r--tests/component/updater_test.cpp220
1 files changed, 133 insertions, 87 deletions
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp
index e6aec4ad..266657d3 100644
--- a/tests/component/updater_test.cpp
+++ b/tests/component/updater_test.cpp
@@ -23,6 +23,7 @@
23#include <algorithm> 23#include <algorithm>
24#include <memory> 24#include <memory>
25#include <string> 25#include <string>
26#include <unordered_map>
26#include <vector> 27#include <vector>
27 28
28#include <android-base/file.h> 29#include <android-base/file.h>
@@ -74,6 +75,23 @@ static void expect(const char* expected, const char* expr_str, CauseCode cause_c
74 ASSERT_EQ(cause_code, state.cause_code); 75 ASSERT_EQ(cause_code, state.cause_code);
75} 76}
76 77
78static void BuildUpdatePackage(const std::unordered_map<std::string, std::string>& entries,
79 int fd) {
80 FILE* zip_file_ptr = fdopen(fd, "wb");
81 ZipWriter zip_writer(zip_file_ptr);
82
83 for (const auto& entry : entries) {
84 ASSERT_EQ(0, zip_writer.StartEntry(entry.first.c_str(), 0));
85 if (!entry.second.empty()) {
86 ASSERT_EQ(0, zip_writer.WriteBytes(entry.second.data(), entry.second.size()));
87 }
88 ASSERT_EQ(0, zip_writer.FinishEntry());
89 }
90
91 ASSERT_EQ(0, zip_writer.Finish());
92 ASSERT_EQ(0, fclose(zip_file_ptr));
93}
94
77static std::string get_sha1(const std::string& content) { 95static std::string get_sha1(const std::string& content) {
78 uint8_t digest[SHA_DIGEST_LENGTH]; 96 uint8_t digest[SHA_DIGEST_LENGTH];
79 SHA1(reinterpret_cast<const uint8_t*>(content.c_str()), content.size(), digest); 97 SHA1(reinterpret_cast<const uint8_t*>(content.c_str()), content.size(), digest);
@@ -420,30 +438,19 @@ TEST_F(UpdaterTest, show_progress) {
420 ASSERT_EQ(0, fclose(updater_info.cmd_pipe)); 438 ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
421} 439}
422 440
423TEST_F(UpdaterTest, block_image_update) { 441TEST_F(UpdaterTest, block_image_update_patch_data) {
424 // Create a zip file with new_data and patch_data.
425 TemporaryFile zip_file;
426 FILE* zip_file_ptr = fdopen(zip_file.release(), "wb");
427 ZipWriter zip_writer(zip_file_ptr);
428
429 // Add a dummy new data.
430 ASSERT_EQ(0, zip_writer.StartEntry("new_data", 0));
431 ASSERT_EQ(0, zip_writer.FinishEntry());
432
433 // Generate and add the patch data.
434 std::string src_content = std::string(4096, 'a') + std::string(4096, 'c'); 442 std::string src_content = std::string(4096, 'a') + std::string(4096, 'c');
435 std::string tgt_content = std::string(4096, 'b') + std::string(4096, 'd'); 443 std::string tgt_content = std::string(4096, 'b') + std::string(4096, 'd');
444
445 // Generate the patch data.
436 TemporaryFile patch_file; 446 TemporaryFile patch_file;
437 ASSERT_EQ(0, bsdiff::bsdiff(reinterpret_cast<const uint8_t*>(src_content.data()), 447 ASSERT_EQ(0, bsdiff::bsdiff(reinterpret_cast<const uint8_t*>(src_content.data()),
438 src_content.size(), reinterpret_cast<const uint8_t*>(tgt_content.data()), 448 src_content.size(), reinterpret_cast<const uint8_t*>(tgt_content.data()),
439 tgt_content.size(), patch_file.path, nullptr)); 449 tgt_content.size(), patch_file.path, nullptr));
440 std::string patch_content; 450 std::string patch_content;
441 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch_content)); 451 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch_content));
442 ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0));
443 ASSERT_EQ(0, zip_writer.WriteBytes(patch_content.data(), patch_content.size()));
444 ASSERT_EQ(0, zip_writer.FinishEntry());
445 452
446 // Add two transfer lists. The first one contains a bsdiff; and we expect the update to succeed. 453 // Create the transfer list that contains a bsdiff.
447 std::string src_hash = get_sha1(src_content); 454 std::string src_hash = get_sha1(src_content);
448 std::string tgt_hash = get_sha1(tgt_content); 455 std::string tgt_hash = get_sha1(tgt_content);
449 std::vector<std::string> transfer_list = { 456 std::vector<std::string> transfer_list = {
@@ -456,27 +463,16 @@ TEST_F(UpdaterTest, block_image_update) {
456 src_hash.c_str(), tgt_hash.c_str(), src_hash.c_str()), 463 src_hash.c_str(), tgt_hash.c_str(), src_hash.c_str()),
457 "free " + src_hash, 464 "free " + src_hash,
458 }; 465 };
459 ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0));
460 std::string commands = android::base::Join(transfer_list, '\n');
461 ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size()));
462 ASSERT_EQ(0, zip_writer.FinishEntry());
463 466
464 // Stash and free some blocks, then fail the 2nd update intentionally. 467 std::unordered_map<std::string, std::string> entries = {
465 std::vector<std::string> fail_transfer_list = { 468 { "new_data", "" },
466 "4", 469 { "patch_data", patch_content },
467 "2", 470 { "transfer_list", android::base::Join(transfer_list, '\n') },
468 "0",
469 "2",
470 "stash " + tgt_hash + " 2,0,2",
471 "free " + tgt_hash,
472 "fail",
473 }; 471 };
474 ASSERT_EQ(0, zip_writer.StartEntry("fail_transfer_list", 0)); 472
475 std::string fail_commands = android::base::Join(fail_transfer_list, '\n'); 473 // Build the update package.
476 ASSERT_EQ(0, zip_writer.WriteBytes(fail_commands.data(), fail_commands.size())); 474 TemporaryFile zip_file;
477 ASSERT_EQ(0, zip_writer.FinishEntry()); 475 BuildUpdatePackage(entries, zip_file.release());
478 ASSERT_EQ(0, zip_writer.Finish());
479 ASSERT_EQ(0, fclose(zip_file_ptr));
480 476
481 MemMapping map; 477 MemMapping map;
482 ASSERT_TRUE(map.MapFile(zip_file.path)); 478 ASSERT_TRUE(map.MapFile(zip_file.path));
@@ -491,7 +487,7 @@ TEST_F(UpdaterTest, block_image_update) {
491 updater_info.package_zip_addr = map.addr; 487 updater_info.package_zip_addr = map.addr;
492 updater_info.package_zip_len = map.length; 488 updater_info.package_zip_len = map.length;
493 489
494 // Execute the commands in the 1st transfer list. 490 // Execute the commands in the transfer list.
495 TemporaryFile update_file; 491 TemporaryFile update_file;
496 ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path)); 492 ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path));
497 std::string script = "block_image_update(\"" + std::string(update_file.path) + 493 std::string script = "block_image_update(\"" + std::string(update_file.path) +
@@ -502,44 +498,98 @@ TEST_F(UpdaterTest, block_image_update) {
502 ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_content)); 498 ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_content));
503 ASSERT_EQ(tgt_hash, get_sha1(updated_content)); 499 ASSERT_EQ(tgt_hash, get_sha1(updated_content));
504 500
505 // Expect the 2nd update to fail, but expect the stashed blocks to be freed. 501 ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
506 script = "block_image_update(\"" + std::string(update_file.path) + 502 CloseArchive(handle);
507 R"(", package_extract_file("fail_transfer_list"), "new_data", "patch_data"))"; 503}
504
505TEST_F(UpdaterTest, block_image_update_fail) {
506 std::string src_content(4096 * 2, 'e');
507 std::string src_hash = get_sha1(src_content);
508 // Stash and free some blocks, then fail the update intentionally.
509 std::vector<std::string> transfer_list = {
510 "4", "2", "0", "2", "stash " + src_hash + " 2,0,2", "free " + src_hash, "fail",
511 };
512
513 // Add a new data of 10 bytes to test the deadlock.
514 std::unordered_map<std::string, std::string> entries = {
515 { "new_data", std::string(10, 0) },
516 { "patch_data", "" },
517 { "transfer_list", android::base::Join(transfer_list, '\n') },
518 };
519
520 // Build the update package.
521 TemporaryFile zip_file;
522 BuildUpdatePackage(entries, zip_file.release());
523
524 MemMapping map;
525 ASSERT_TRUE(map.MapFile(zip_file.path));
526 ZipArchiveHandle handle;
527 ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
528
529 // Set up the handler, command_pipe, patch offset & length.
530 UpdaterInfo updater_info;
531 updater_info.package_zip = handle;
532 TemporaryFile temp_pipe;
533 updater_info.cmd_pipe = fdopen(temp_pipe.release(), "wbe");
534 updater_info.package_zip_addr = map.addr;
535 updater_info.package_zip_len = map.length;
536
537 TemporaryFile update_file;
538 ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path));
539 // Expect the stashed blocks to be freed.
540 std::string script = "block_image_update(\"" + std::string(update_file.path) +
541 R"(", package_extract_file("transfer_list"), "new_data", "patch_data"))";
508 expect("", script.c_str(), kNoCause, &updater_info); 542 expect("", script.c_str(), kNoCause, &updater_info);
509 // Updater generates the stash name based on the input file name. 543 // Updater generates the stash name based on the input file name.
510 std::string name_digest = get_sha1(update_file.path); 544 std::string name_digest = get_sha1(update_file.path);
511 std::string stash_base = "/cache/recovery/" + name_digest; 545 std::string stash_base = "/cache/recovery/" + name_digest;
512 ASSERT_EQ(0, access(stash_base.c_str(), F_OK)); 546 ASSERT_EQ(0, access(stash_base.c_str(), F_OK));
513 ASSERT_EQ(-1, access((stash_base + tgt_hash).c_str(), F_OK)); 547 ASSERT_EQ(-1, access((stash_base + src_hash).c_str(), F_OK));
514 ASSERT_EQ(0, rmdir(stash_base.c_str())); 548 ASSERT_EQ(0, rmdir(stash_base.c_str()));
515 549
516 ASSERT_EQ(0, fclose(updater_info.cmd_pipe)); 550 ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
517 CloseArchive(handle); 551 CloseArchive(handle);
518} 552}
519 553
520TEST_F(UpdaterTest, new_data_short_write) { 554TEST_F(UpdaterTest, new_data_over_write) {
521 // Create a zip file with new_data. 555 std::vector<std::string> transfer_list = {
556 "4", "1", "0", "0", "new 2,0,1",
557 };
558
559 // Write 4096 + 100 bytes of new data.
560 std::unordered_map<std::string, std::string> entries = {
561 { "new_data", std::string(4196, 0) },
562 { "patch_data", "" },
563 { "transfer_list", android::base::Join(transfer_list, '\n') },
564 };
565
566 // Build the update package.
522 TemporaryFile zip_file; 567 TemporaryFile zip_file;
523 FILE* zip_file_ptr = fdopen(zip_file.release(), "wb"); 568 BuildUpdatePackage(entries, zip_file.release());
524 ZipWriter zip_writer(zip_file_ptr); 569
570 MemMapping map;
571 ASSERT_TRUE(map.MapFile(zip_file.path));
572 ZipArchiveHandle handle;
573 ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
525 574
526 // Add the empty new data. 575 // Set up the handler, command_pipe, patch offset & length.
527 ASSERT_EQ(0, zip_writer.StartEntry("empty_new_data", 0)); 576 UpdaterInfo updater_info;
528 ASSERT_EQ(0, zip_writer.FinishEntry()); 577 updater_info.package_zip = handle;
529 // Add the short written new data. 578 TemporaryFile temp_pipe;
530 ASSERT_EQ(0, zip_writer.StartEntry("short_new_data", 0)); 579 updater_info.cmd_pipe = fdopen(temp_pipe.release(), "wbe");
531 std::string new_data_short = std::string(10, 'a'); 580 updater_info.package_zip_addr = map.addr;
532 ASSERT_EQ(0, zip_writer.WriteBytes(new_data_short.data(), new_data_short.size())); 581 updater_info.package_zip_len = map.length;
533 ASSERT_EQ(0, zip_writer.FinishEntry());
534 // Add the data of exactly one block.
535 ASSERT_EQ(0, zip_writer.StartEntry("exact_new_data", 0));
536 std::string new_data_exact = std::string(4096, 'a');
537 ASSERT_EQ(0, zip_writer.WriteBytes(new_data_exact.data(), new_data_exact.size()));
538 ASSERT_EQ(0, zip_writer.FinishEntry());
539 // Add a dummy patch data.
540 ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0));
541 ASSERT_EQ(0, zip_writer.FinishEntry());
542 582
583 TemporaryFile update_file;
584 std::string script = "block_image_update(\"" + std::string(update_file.path) +
585 R"(", package_extract_file("transfer_list"), "new_data", "patch_data"))";
586 expect("t", script.c_str(), kNoCause, &updater_info);
587
588 ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
589 CloseArchive(handle);
590}
591
592TEST_F(UpdaterTest, new_data_short_write) {
543 std::vector<std::string> transfer_list = { 593 std::vector<std::string> transfer_list = {
544 "4", 594 "4",
545 "1", 595 "1",
@@ -547,12 +597,17 @@ TEST_F(UpdaterTest, new_data_short_write) {
547 "0", 597 "0",
548 "new 2,0,1", 598 "new 2,0,1",
549 }; 599 };
550 ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0)); 600
551 std::string commands = android::base::Join(transfer_list, '\n'); 601 std::unordered_map<std::string, std::string> entries = {
552 ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size())); 602 { "empty_new_data", "" },
553 ASSERT_EQ(0, zip_writer.FinishEntry()); 603 { "short_new_data", std::string(10, 'a') },
554 ASSERT_EQ(0, zip_writer.Finish()); 604 { "exact_new_data", std::string(4096, 'a') },
555 ASSERT_EQ(0, fclose(zip_file_ptr)); 605 { "patch_data", "" },
606 { "transfer_list", android::base::Join(transfer_list, '\n') },
607 };
608
609 TemporaryFile zip_file;
610 BuildUpdatePackage(entries, zip_file.release());
556 611
557 MemMapping map; 612 MemMapping map;
558 ASSERT_TRUE(map.MapFile(zip_file.path)); 613 ASSERT_TRUE(map.MapFile(zip_file.path));
@@ -587,14 +642,6 @@ TEST_F(UpdaterTest, new_data_short_write) {
587} 642}
588 643
589TEST_F(UpdaterTest, brotli_new_data) { 644TEST_F(UpdaterTest, brotli_new_data) {
590 // Create a zip file with new_data.
591 TemporaryFile zip_file;
592 FILE* zip_file_ptr = fdopen(zip_file.release(), "wb");
593 ZipWriter zip_writer(zip_file_ptr);
594
595 // Add a brotli compressed new data entry.
596 ASSERT_EQ(0, zip_writer.StartEntry("new.dat.br", 0));
597
598 auto generator = []() { return rand() % 128; }; 645 auto generator = []() { return rand() % 128; };
599 // Generate 100 blocks of random data. 646 // Generate 100 blocks of random data.
600 std::string brotli_new_data; 647 std::string brotli_new_data;
@@ -602,16 +649,12 @@ TEST_F(UpdaterTest, brotli_new_data) {
602 generate_n(back_inserter(brotli_new_data), 4096 * 100, generator); 649 generate_n(back_inserter(brotli_new_data), 4096 * 100, generator);
603 650
604 size_t encoded_size = BrotliEncoderMaxCompressedSize(brotli_new_data.size()); 651 size_t encoded_size = BrotliEncoderMaxCompressedSize(brotli_new_data.size());
605 std::vector<uint8_t> encoded_data(encoded_size); 652 std::string encoded_data(encoded_size, 0);
606 ASSERT_TRUE(BrotliEncoderCompress( 653 ASSERT_TRUE(BrotliEncoderCompress(
607 BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, brotli_new_data.size(), 654 BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, brotli_new_data.size(),
608 reinterpret_cast<const uint8_t*>(brotli_new_data.data()), &encoded_size, encoded_data.data())); 655 reinterpret_cast<const uint8_t*>(brotli_new_data.data()), &encoded_size,
609 656 reinterpret_cast<uint8_t*>(const_cast<char*>(encoded_data.data()))));
610 ASSERT_EQ(0, zip_writer.WriteBytes(encoded_data.data(), encoded_size)); 657 encoded_data.resize(encoded_size);
611 ASSERT_EQ(0, zip_writer.FinishEntry());
612 // Add a dummy patch data.
613 ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0));
614 ASSERT_EQ(0, zip_writer.FinishEntry());
615 658
616 // Write a few small chunks of new data, then a large chunk, and finally a few small chunks. 659 // Write a few small chunks of new data, then a large chunk, and finally a few small chunks.
617 // This helps us to catch potential short writes. 660 // This helps us to catch potential short writes.
@@ -627,12 +670,15 @@ TEST_F(UpdaterTest, brotli_new_data) {
627 "new 2,98,99", 670 "new 2,98,99",
628 "new 2,99,100", 671 "new 2,99,100",
629 }; 672 };
630 ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0)); 673
631 std::string commands = android::base::Join(transfer_list, '\n'); 674 std::unordered_map<std::string, std::string> entries = {
632 ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size())); 675 { "new.dat.br", std::move(encoded_data) },
633 ASSERT_EQ(0, zip_writer.FinishEntry()); 676 { "patch_data", "" },
634 ASSERT_EQ(0, zip_writer.Finish()); 677 { "transfer_list", android::base::Join(transfer_list, '\n') },
635 ASSERT_EQ(0, fclose(zip_file_ptr)); 678 };
679
680 TemporaryFile zip_file;
681 BuildUpdatePackage(entries, zip_file.release());
636 682
637 MemMapping map; 683 MemMapping map;
638 ASSERT_TRUE(map.MapFile(zip_file.path)); 684 ASSERT_TRUE(map.MapFile(zip_file.path));