summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tests/Android.mk3
-rw-r--r--tests/component/install_test.cpp71
-rw-r--r--tests/component/update_verifier_test.cpp13
-rw-r--r--tests/component/updater_test.cpp23
-rw-r--r--tests/component/verifier_test.cpp17
-rw-r--r--tests/manual/recovery_test.cpp2
-rw-r--r--tests/unit/dirutil_test.cpp64
-rw-r--r--tests/unit/rangeset_test.cpp49
8 files changed, 167 insertions, 75 deletions
diff --git a/tests/Android.mk b/tests/Android.mk
index 8b1dc1099..f2497b8b3 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -111,7 +111,8 @@ LOCAL_SRC_FILES := \
component/update_verifier_test.cpp \
component/verifier_test.cpp
-LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_SHARED_LIBRARIES := \
+ libhidlbase
tune2fs_static_libraries := \
libext2_com_err \
diff --git a/tests/component/install_test.cpp b/tests/component/install_test.cpp
index 968196fc0..7bb496066 100644
--- a/tests/component/install_test.cpp
+++ b/tests/component/install_test.cpp
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include <algorithm>
#include <string>
#include <vector>
@@ -198,8 +199,8 @@ TEST(InstallTest, verify_package_compatibility_with_libvintf_system_manifest_xml
CloseArchive(zip);
}
-TEST(InstallTest, update_binary_command_smoke) {
#ifdef AB_OTA_UPDATER
+static void VerifyAbUpdateBinaryCommand(const std::string& serialno, bool success = true) {
TemporaryFile temp_file;
FILE* zip_file = fdopen(temp_file.fd, "w");
ZipWriter writer(zip_file);
@@ -215,11 +216,13 @@ TEST(InstallTest, update_binary_command_smoke) {
ASSERT_NE("", device);
std::string timestamp = android::base::GetProperty("ro.build.date.utc", "");
ASSERT_NE("", timestamp);
- std::string metadata = android::base::Join(
- std::vector<std::string>{
- "ota-type=AB", "pre-device=" + device, "post-timestamp=" + timestamp,
- },
- "\n");
+
+ std::vector<std::string> meta{ "ota-type=AB", "pre-device=" + device,
+ "post-timestamp=" + timestamp };
+ if (!serialno.empty()) {
+ meta.push_back("serialno=" + serialno);
+ }
+ std::string metadata = android::base::Join(meta, "\n");
ASSERT_EQ(0, writer.WriteBytes(metadata.data(), metadata.size()));
ASSERT_EQ(0, writer.FinishEntry());
ASSERT_EQ(0, writer.Finish());
@@ -234,14 +237,25 @@ TEST(InstallTest, update_binary_command_smoke) {
std::string package = "/path/to/update.zip";
std::string binary_path = "/sbin/update_engine_sideload";
std::vector<std::string> cmd;
- 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]);
+ if (success) {
+ 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]);
+ } else {
+ ASSERT_EQ(INSTALL_ERROR, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd));
+ }
CloseArchive(zip);
+}
+#endif // AB_OTA_UPDATER
+
+TEST(InstallTest, update_binary_command_smoke) {
+#ifdef AB_OTA_UPDATER
+ // Empty serialno will pass the verification.
+ VerifyAbUpdateBinaryCommand({});
#else
TemporaryFile temp_file;
FILE* zip_file = fdopen(temp_file.fd, "w");
@@ -340,3 +354,34 @@ TEST(InstallTest, update_binary_command_invalid) {
CloseArchive(zip);
#endif // AB_OTA_UPDATER
}
+
+#ifdef AB_OTA_UPDATER
+TEST(InstallTest, update_binary_command_multiple_serialno) {
+ std::string serialno = android::base::GetProperty("ro.serialno", "");
+ ASSERT_NE("", serialno);
+
+ // Single matching serialno will pass the verification.
+ VerifyAbUpdateBinaryCommand(serialno);
+
+ static constexpr char alphabet[] =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ auto generator = []() { return alphabet[rand() % (sizeof(alphabet) - 1)]; };
+
+ // Generate 900 random serial numbers.
+ std::string random_serial;
+ for (size_t i = 0; i < 900; i++) {
+ generate_n(back_inserter(random_serial), serialno.size(), generator);
+ random_serial.append("|");
+ }
+ // Random serialnos should fail the verification.
+ VerifyAbUpdateBinaryCommand(random_serial, false);
+
+ std::string long_serial = random_serial + serialno + "|";
+ for (size_t i = 0; i < 99; i++) {
+ generate_n(back_inserter(long_serial), serialno.size(), generator);
+ long_serial.append("|");
+ }
+ // String with the matching serialno should pass the verification.
+ VerifyAbUpdateBinaryCommand(long_serial);
+}
+#endif // AB_OTA_UPDATER
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));
+}
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp
index 357a39ef7..6c341c111 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;
@@ -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<uint8_t> 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<std::string> 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');
diff --git a/tests/component/verifier_test.cpp b/tests/component/verifier_test.cpp
index 5338f05c6..e520f5028 100644
--- a/tests/component/verifier_test.cpp
+++ b/tests/component/verifier_test.cpp
@@ -33,6 +33,8 @@
#include "otautil/SysUtil.h"
#include "verifier.h"
+using namespace std::string_literals;
+
class VerifierTest : public testing::TestWithParam<std::vector<std::string>> {
protected:
void SetUp() override {
@@ -115,6 +117,21 @@ TEST(VerifierTest, load_keys_invalid_keys) {
ASSERT_FALSE(load_keys(key_file5.path, certs));
}
+TEST(VerifierTest, BadPackage_SignatureStartOutOfBounds) {
+ std::string testkey_v3;
+ ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("testkey_v3.txt"), &testkey_v3));
+
+ TemporaryFile key_file;
+ ASSERT_TRUE(android::base::WriteStringToFile(testkey_v3, key_file.path));
+ std::vector<Certificate> certs;
+ ASSERT_TRUE(load_keys(key_file.path, certs));
+
+ // Signature start is 65535 (0xffff) while comment size is 0 (Bug: 31914369).
+ std::string package = "\x50\x4b\x05\x06"s + std::string(12, '\0') + "\xff\xff\xff\xff\x00\x00"s;
+ ASSERT_EQ(VERIFY_FAILURE, verify_file(reinterpret_cast<const unsigned char*>(package.data()),
+ package.size(), certs));
+}
+
TEST(VerifierTest, BadPackage_AlteredFooter) {
std::string testkey_v3;
ASSERT_TRUE(android::base::ReadFileToString(from_testdata_base("testkey_v3.txt"), &testkey_v3));
diff --git a/tests/manual/recovery_test.cpp b/tests/manual/recovery_test.cpp
index d36dd331e..92c6ef2d4 100644
--- a/tests/manual/recovery_test.cpp
+++ b/tests/manual/recovery_test.cpp
@@ -141,7 +141,7 @@ class ResourceTest : public testing::TestWithParam<std::string> {
// under recovery.
void SetUp() override {
std::string file_path = GetParam();
- fp = fopen(file_path.c_str(), "rb");
+ fp = fopen(file_path.c_str(), "rbe");
ASSERT_NE(nullptr, fp);
unsigned char header[8];
diff --git a/tests/unit/dirutil_test.cpp b/tests/unit/dirutil_test.cpp
index 5e2ae4fb5..7f85d13ea 100644
--- a/tests/unit/dirutil_test.cpp
+++ b/tests/unit/dirutil_test.cpp
@@ -26,23 +26,23 @@
TEST(DirUtilTest, create_invalid) {
// Requesting to create an empty dir is invalid.
- ASSERT_EQ(-1, dirCreateHierarchy("", 0755, nullptr, false, nullptr));
+ ASSERT_EQ(-1, mkdir_recursively("", 0755, false, nullptr));
ASSERT_EQ(ENOENT, errno);
// Requesting to strip the name with no slash present.
- ASSERT_EQ(-1, dirCreateHierarchy("abc", 0755, nullptr, true, nullptr));
+ ASSERT_EQ(-1, mkdir_recursively("abc", 0755, true, nullptr));
ASSERT_EQ(ENOENT, errno);
// Creating a dir that already exists.
TemporaryDir td;
- ASSERT_EQ(0, dirCreateHierarchy(td.path, 0755, nullptr, false, nullptr));
+ ASSERT_EQ(0, mkdir_recursively(td.path, 0755, false, nullptr));
// "///" is a valid dir.
- ASSERT_EQ(0, dirCreateHierarchy("///", 0755, nullptr, false, nullptr));
+ ASSERT_EQ(0, mkdir_recursively("///", 0755, false, nullptr));
// Request to create a dir, but a file with the same name already exists.
TemporaryFile tf;
- ASSERT_EQ(-1, dirCreateHierarchy(tf.path, 0755, nullptr, false, nullptr));
+ ASSERT_EQ(-1, mkdir_recursively(tf.path, 0755, false, nullptr));
ASSERT_EQ(ENOTDIR, errno);
}
@@ -51,7 +51,7 @@ TEST(DirUtilTest, create_smoke) {
std::string prefix(td.path);
std::string path = prefix + "/a/b";
constexpr mode_t mode = 0755;
- ASSERT_EQ(0, dirCreateHierarchy(path.c_str(), mode, nullptr, false, nullptr));
+ ASSERT_EQ(0, mkdir_recursively(path, mode, false, nullptr));
// Verify.
struct stat sb;
@@ -69,7 +69,7 @@ TEST(DirUtilTest, create_strip_filename) {
TemporaryDir td;
std::string prefix(td.path);
std::string path = prefix + "/a/b";
- ASSERT_EQ(0, dirCreateHierarchy(path.c_str(), 0755, nullptr, true, nullptr));
+ ASSERT_EQ(0, mkdir_recursively(path, 0755, true, nullptr));
// Verify that "../a" exists but not "../a/b".
struct stat sb;
@@ -83,31 +83,21 @@ TEST(DirUtilTest, create_strip_filename) {
ASSERT_EQ(0, rmdir((prefix + "/a").c_str()));
}
-TEST(DirUtilTest, create_mode_and_timestamp) {
+TEST(DirUtilTest, create_mode) {
TemporaryDir td;
std::string prefix(td.path);
std::string path = prefix + "/a/b";
- // Set the timestamp to 8/1/2008.
- constexpr struct utimbuf timestamp = { 1217592000, 1217592000 };
constexpr mode_t mode = 0751;
- ASSERT_EQ(0, dirCreateHierarchy(path.c_str(), mode, &timestamp, false, nullptr));
+ ASSERT_EQ(0, mkdir_recursively(path, mode, false, nullptr));
- // Verify the mode and timestamp for "../a/b".
+ // Verify the mode for "../a/b".
struct stat sb;
ASSERT_EQ(0, stat(path.c_str(), &sb)) << strerror(errno);
ASSERT_TRUE(S_ISDIR(sb.st_mode));
constexpr mode_t mask = S_IRWXU | S_IRWXG | S_IRWXO;
ASSERT_EQ(mode, sb.st_mode & mask);
- timespec time;
- time.tv_sec = 1217592000;
- time.tv_nsec = 0;
-
- ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_atime));
- ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_mtime));
-
- // Verify the mode for "../a". Note that the timestamp for intermediate directories (e.g. "../a")
- // may not be 'timestamp' according to the current implementation.
+ // Verify the mode for "../a".
ASSERT_EQ(0, stat((prefix + "/a").c_str(), &sb)) << strerror(errno);
ASSERT_TRUE(S_ISDIR(sb.st_mode));
ASSERT_EQ(mode, sb.st_mode & mask);
@@ -116,35 +106,3 @@ TEST(DirUtilTest, create_mode_and_timestamp) {
ASSERT_EQ(0, rmdir((prefix + "/a/b").c_str()));
ASSERT_EQ(0, rmdir((prefix + "/a").c_str()));
}
-
-TEST(DirUtilTest, unlink_invalid) {
- // File doesn't exist.
- ASSERT_EQ(-1, dirUnlinkHierarchy("doesntexist"));
-
- // Nonexistent directory.
- TemporaryDir td;
- std::string path(td.path);
- ASSERT_EQ(-1, dirUnlinkHierarchy((path + "/a").c_str()));
- ASSERT_EQ(ENOENT, errno);
-}
-
-TEST(DirUtilTest, unlink_smoke) {
- // Unlink a file.
- TemporaryFile tf;
- ASSERT_EQ(0, dirUnlinkHierarchy(tf.path));
- ASSERT_EQ(-1, access(tf.path, F_OK));
-
- TemporaryDir td;
- std::string path(td.path);
- constexpr mode_t mode = 0700;
- ASSERT_EQ(0, mkdir((path + "/a").c_str(), mode));
- ASSERT_EQ(0, mkdir((path + "/a/b").c_str(), mode));
- ASSERT_EQ(0, mkdir((path + "/a/b/c").c_str(), mode));
- ASSERT_EQ(0, mkdir((path + "/a/d").c_str(), mode));
-
- // Remove "../a" recursively.
- ASSERT_EQ(0, dirUnlinkHierarchy((path + "/a").c_str()));
-
- // Verify it's gone.
- ASSERT_EQ(-1, access((path + "/a").c_str(), F_OK));
-}
diff --git a/tests/unit/rangeset_test.cpp b/tests/unit/rangeset_test.cpp
index 3c6d77ef5..15bcec855 100644
--- a/tests/unit/rangeset_test.cpp
+++ b/tests/unit/rangeset_test.cpp
@@ -21,7 +21,7 @@
#include <gtest/gtest.h>
-#include "updater/rangeset.h"
+#include "rangeset.h"
TEST(RangeSetTest, Parse_smoke) {
RangeSet rs = RangeSet::Parse("2,1,10");
@@ -110,3 +110,50 @@ TEST(RangeSetTest, iterators) {
}
ASSERT_EQ((std::vector<Range>{ Range{ 8, 10 }, Range{ 1, 5 } }), ranges);
}
+
+TEST(RangeSetTest, tostring) {
+ ASSERT_EQ("2,1,6", RangeSet::Parse("2,1,6").ToString());
+ ASSERT_EQ("4,1,5,8,10", RangeSet::Parse("4,1,5,8,10").ToString());
+ ASSERT_EQ("6,1,3,4,6,15,22", RangeSet::Parse("6,1,3,4,6,15,22").ToString());
+}
+
+TEST(SortedRangeSetTest, insertion) {
+ SortedRangeSet rs({ { 2, 3 }, { 4, 6 }, { 8, 14 } });
+ rs.Insert({ 1, 2 });
+ ASSERT_EQ(SortedRangeSet({ { 1, 3 }, { 4, 6 }, { 8, 14 } }), rs);
+ ASSERT_EQ(static_cast<size_t>(10), rs.blocks());
+ rs.Insert({ 3, 5 });
+ ASSERT_EQ(SortedRangeSet({ { 1, 6 }, { 8, 14 } }), rs);
+ ASSERT_EQ(static_cast<size_t>(11), rs.blocks());
+
+ SortedRangeSet r1({ { 20, 22 }, { 15, 18 } });
+ rs.Insert(r1);
+ ASSERT_EQ(SortedRangeSet({ { 1, 6 }, { 8, 14 }, { 15, 18 }, { 20, 22 } }), rs);
+ ASSERT_EQ(static_cast<size_t>(16), rs.blocks());
+
+ SortedRangeSet r2({ { 2, 7 }, { 15, 21 }, { 20, 25 } });
+ rs.Insert(r2);
+ ASSERT_EQ(SortedRangeSet({ { 1, 7 }, { 8, 14 }, { 15, 25 } }), rs);
+ ASSERT_EQ(static_cast<size_t>(22), rs.blocks());
+}
+
+TEST(SortedRangeSetTest, file_range) {
+ SortedRangeSet rs;
+ rs.Insert(4096, 4096);
+ ASSERT_EQ(SortedRangeSet({ { 1, 2 } }), rs);
+ // insert block 2-9
+ rs.Insert(4096 * 3 - 1, 4096 * 7);
+ ASSERT_EQ(SortedRangeSet({ { 1, 10 } }), rs);
+ // insert block 15-19
+ rs.Insert(4096 * 15 + 1, 4096 * 4);
+ ASSERT_EQ(SortedRangeSet({ { 1, 10 }, { 15, 20 } }), rs);
+
+ // rs overlaps block 2-2
+ ASSERT_TRUE(rs.Overlaps(4096 * 2 - 1, 10));
+ ASSERT_FALSE(rs.Overlaps(4096 * 10, 4096 * 5));
+
+ ASSERT_EQ(static_cast<size_t>(10), rs.GetOffsetInRangeSet(4106));
+ ASSERT_EQ(static_cast<size_t>(40970), rs.GetOffsetInRangeSet(4096 * 16 + 10));
+ // block#10 not in range.
+ ASSERT_EXIT(rs.GetOffsetInRangeSet(40970), ::testing::KilledBySignal(SIGABRT), "");
+} \ No newline at end of file