summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Android.mk5
-rw-r--r--tests/component/updater_test.cpp209
-rw-r--r--tests/unit/zip_test.cpp37
-rw-r--r--tests/unit/ziputil_test.cpp191
4 files changed, 440 insertions, 2 deletions
diff --git a/tests/Android.mk b/tests/Android.mk
index b3584fe87..f19ca36c0 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -40,8 +40,9 @@ LOCAL_SRC_FILES := \
unit/rangeset_test.cpp \
unit/sysutil_test.cpp \
unit/zip_test.cpp \
+ unit/ziputil_test.cpp
-LOCAL_C_INCLUDES := bootable/recovery
+LOCAL_C_INCLUDES := $(commands_recovery_local_path)
LOCAL_SHARED_LIBRARIES := liblog
include $(BUILD_NATIVE_TEST)
@@ -101,7 +102,7 @@ endif
LOCAL_MODULE := recovery_component_test
LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_C_INCLUDES := bootable/recovery
+LOCAL_C_INCLUDES := $(commands_recovery_local_path)
LOCAL_SRC_FILES := \
component/applypatch_test.cpp \
component/bootloader_message_test.cpp \
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp
index 5bfd7cb40..50e0a6345 100644
--- a/tests/component/updater_test.cpp
+++ b/tests/component/updater_test.cpp
@@ -255,6 +255,215 @@ TEST_F(UpdaterTest, file_getprop) {
expect("", script6.c_str(), kNoCause);
}
+TEST_F(UpdaterTest, delete) {
+ // Delete none.
+ expect("0", "delete()", kNoCause);
+ expect("0", "delete(\"/doesntexist\")", kNoCause);
+ expect("0", "delete(\"/doesntexist1\", \"/doesntexist2\")", kNoCause);
+ expect("0", "delete(\"/doesntexist1\", \"/doesntexist2\", \"/doesntexist3\")", kNoCause);
+
+ // Delete one file.
+ TemporaryFile temp_file1;
+ ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file1.path));
+ std::string script1("delete(\"" + std::string(temp_file1.path) + "\")");
+ expect("1", script1.c_str(), kNoCause);
+
+ // Delete two files.
+ TemporaryFile temp_file2;
+ ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file2.path));
+ TemporaryFile temp_file3;
+ ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file3.path));
+ std::string script2("delete(\"" + std::string(temp_file2.path) + "\", \"" +
+ std::string(temp_file3.path) + "\")");
+ expect("2", script2.c_str(), kNoCause);
+
+ // Delete already deleted files.
+ expect("0", script2.c_str(), kNoCause);
+
+ // Delete one out of three.
+ TemporaryFile temp_file4;
+ ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file4.path));
+ std::string script3("delete(\"/doesntexist1\", \"" + std::string(temp_file4.path) +
+ "\", \"/doesntexist2\")");
+ expect("1", script3.c_str(), kNoCause);
+}
+
+TEST_F(UpdaterTest, rename) {
+ // rename() expects two arguments.
+ expect(nullptr, "rename()", kArgsParsingFailure);
+ expect(nullptr, "rename(\"arg1\")", kArgsParsingFailure);
+ expect(nullptr, "rename(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
+
+ // src_name or dst_name cannot be empty.
+ expect(nullptr, "rename(\"\", \"arg2\")", kArgsParsingFailure);
+ expect(nullptr, "rename(\"arg1\", \"\")", kArgsParsingFailure);
+
+ // File doesn't exist (both of src and dst).
+ expect(nullptr, "rename(\"/doesntexist\", \"/doesntexisteither\")" , kFileRenameFailure);
+
+ // Can't create parent directory.
+ TemporaryFile temp_file1;
+ ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file1.path));
+ std::string script1("rename(\"" + std::string(temp_file1.path) + "\", \"/proc/0/file1\")");
+ expect(nullptr, script1.c_str(), kFileRenameFailure);
+
+ // Rename.
+ TemporaryFile temp_file2;
+ std::string script2("rename(\"" + std::string(temp_file1.path) + "\", \"" +
+ std::string(temp_file2.path) + "\")");
+ expect(temp_file2.path, script2.c_str(), kNoCause);
+
+ // Already renamed.
+ expect(temp_file2.path, script2.c_str(), kNoCause);
+
+ // Parents create successfully.
+ TemporaryFile temp_file3;
+ TemporaryDir td;
+ std::string temp_dir(td.path);
+ std::string dst_file = temp_dir + "/aaa/bbb/a.txt";
+ std::string script3("rename(\"" + std::string(temp_file3.path) + "\", \"" + dst_file + "\")");
+ expect(dst_file.c_str(), script3.c_str(), kNoCause);
+
+ // Clean up the temp files under td.
+ ASSERT_EQ(0, unlink(dst_file.c_str()));
+ ASSERT_EQ(0, rmdir((temp_dir + "/aaa/bbb").c_str()));
+ ASSERT_EQ(0, rmdir((temp_dir + "/aaa").c_str()));
+}
+
+TEST_F(UpdaterTest, symlink) {
+ // symlink expects 1+ argument.
+ expect(nullptr, "symlink()", kArgsParsingFailure);
+
+ // symlink should fail if src is an empty string.
+ TemporaryFile temp_file1;
+ std::string script1("symlink(\"" + std::string(temp_file1.path) + "\", \"\")");
+ expect(nullptr, script1.c_str(), kSymlinkFailure);
+
+ std::string script2("symlink(\"" + std::string(temp_file1.path) + "\", \"src1\", \"\")");
+ expect(nullptr, script2.c_str(), kSymlinkFailure);
+
+ // symlink failed to remove old src.
+ std::string script3("symlink(\"" + std::string(temp_file1.path) + "\", \"/proc\")");
+ expect(nullptr, script3.c_str(), kSymlinkFailure);
+
+ // symlink can create symlinks.
+ TemporaryFile temp_file;
+ std::string content = "magicvalue";
+ ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path));
+
+ TemporaryDir td;
+ std::string src1 = std::string(td.path) + "/symlink1";
+ std::string src2 = std::string(td.path) + "/symlink2";
+ std::string script4("symlink(\"" + std::string(temp_file.path) + "\", \"" +
+ src1 + "\", \"" + src2 + "\")");
+ expect("t", script4.c_str(), kNoCause);
+
+ // Verify the created symlinks.
+ struct stat sb;
+ ASSERT_TRUE(lstat(src1.c_str(), &sb) == 0 && S_ISLNK(sb.st_mode));
+ ASSERT_TRUE(lstat(src2.c_str(), &sb) == 0 && S_ISLNK(sb.st_mode));
+
+ // Clean up the leftovers.
+ ASSERT_EQ(0, unlink(src1.c_str()));
+ ASSERT_EQ(0, unlink(src2.c_str()));
+}
+
+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", "<dir>").
+ 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.
diff --git a/tests/unit/zip_test.cpp b/tests/unit/zip_test.cpp
index 827668521..df4e38cae 100644
--- a/tests/unit/zip_test.cpp
+++ b/tests/unit/zip_test.cpp
@@ -24,10 +24,47 @@
#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include <otautil/SysUtil.h>
+#include <otautil/ZipUtil.h>
#include <ziparchive/zip_archive.h>
#include "common/test_constants.h"
+TEST(ZipTest, ExtractPackageRecursive) {
+ std::string zip_path = from_testdata_base("ziptest_valid.zip");
+ ZipArchiveHandle handle;
+ ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
+
+ // Extract the whole package into a temp directory.
+ TemporaryDir td;
+ ASSERT_NE(nullptr, td.path);
+ ExtractPackageRecursive(handle, "", td.path, nullptr, nullptr);
+
+ // Make sure all the files are extracted correctly.
+ std::string path(td.path);
+ ASSERT_EQ(0, access((path + "/a.txt").c_str(), F_OK));
+ ASSERT_EQ(0, access((path + "/b.txt").c_str(), F_OK));
+ ASSERT_EQ(0, access((path + "/b/c.txt").c_str(), F_OK));
+ ASSERT_EQ(0, access((path + "/b/d.txt").c_str(), F_OK));
+
+ // The content of the file is the same as expected.
+ std::string content1;
+ ASSERT_TRUE(android::base::ReadFileToString(path + "/a.txt", &content1));
+ ASSERT_EQ(kATxtContents, content1);
+
+ std::string content2;
+ ASSERT_TRUE(android::base::ReadFileToString(path + "/b/d.txt", &content2));
+ ASSERT_EQ(kDTxtContents, content2);
+
+ CloseArchive(handle);
+
+ // Clean up.
+ ASSERT_EQ(0, unlink((path + "/a.txt").c_str()));
+ ASSERT_EQ(0, unlink((path + "/b.txt").c_str()));
+ ASSERT_EQ(0, unlink((path + "/b/c.txt").c_str()));
+ ASSERT_EQ(0, unlink((path + "/b/d.txt").c_str()));
+ ASSERT_EQ(0, rmdir((path + "/b").c_str()));
+}
+
TEST(ZipTest, OpenFromMemory) {
std::string zip_path = from_testdata_base("ziptest_dummy-update.zip");
MemMapping map;
diff --git a/tests/unit/ziputil_test.cpp b/tests/unit/ziputil_test.cpp
new file mode 100644
index 000000000..14e541690
--- /dev/null
+++ b/tests/unit/ziputil_test.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2016 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 <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/test_utils.h>
+#include <gtest/gtest.h>
+#include <otautil/ZipUtil.h>
+#include <ziparchive/zip_archive.h>
+
+#include "common/test_constants.h"
+
+TEST(ZipUtilTest, invalid_args) {
+ std::string zip_path = from_testdata_base("ziptest_valid.zip");
+ ZipArchiveHandle handle;
+ ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
+
+ // zip_path must be a relative path.
+ ASSERT_FALSE(ExtractPackageRecursive(handle, "/a/b", "/tmp", nullptr, nullptr));
+
+ // dest_path must be an absolute path.
+ ASSERT_FALSE(ExtractPackageRecursive(handle, "a/b", "tmp", nullptr, nullptr));
+ ASSERT_FALSE(ExtractPackageRecursive(handle, "a/b", "", nullptr, nullptr));
+
+ CloseArchive(handle);
+}
+
+TEST(ZipUtilTest, extract_all) {
+ std::string zip_path = from_testdata_base("ziptest_valid.zip");
+ ZipArchiveHandle handle;
+ ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
+
+ // Extract the whole package into a temp directory.
+ TemporaryDir td;
+ ExtractPackageRecursive(handle, "", td.path, nullptr, nullptr);
+
+ // Make sure all the files are extracted correctly.
+ std::string path(td.path);
+ ASSERT_EQ(0, access((path + "/a.txt").c_str(), F_OK));
+ ASSERT_EQ(0, access((path + "/b.txt").c_str(), F_OK));
+ ASSERT_EQ(0, access((path + "/b/c.txt").c_str(), F_OK));
+ ASSERT_EQ(0, access((path + "/b/d.txt").c_str(), F_OK));
+
+ // The content of the file is the same as expected.
+ std::string content1;
+ ASSERT_TRUE(android::base::ReadFileToString(path + "/a.txt", &content1));
+ ASSERT_EQ(kATxtContents, content1);
+
+ std::string content2;
+ ASSERT_TRUE(android::base::ReadFileToString(path + "/b/d.txt", &content2));
+ ASSERT_EQ(kDTxtContents, content2);
+
+ // Clean up the temp files under td.
+ ASSERT_EQ(0, unlink((path + "/a.txt").c_str()));
+ ASSERT_EQ(0, unlink((path + "/b.txt").c_str()));
+ ASSERT_EQ(0, unlink((path + "/b/c.txt").c_str()));
+ ASSERT_EQ(0, unlink((path + "/b/d.txt").c_str()));
+ ASSERT_EQ(0, rmdir((path + "/b").c_str()));
+
+ CloseArchive(handle);
+}
+
+TEST(ZipUtilTest, extract_prefix_with_slash) {
+ std::string zip_path = from_testdata_base("ziptest_valid.zip");
+ ZipArchiveHandle handle;
+ ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
+
+ // Extract all the entries starting with "b/".
+ TemporaryDir td;
+ ExtractPackageRecursive(handle, "b/", td.path, nullptr, nullptr);
+
+ // Make sure all the files with "b/" prefix are extracted correctly.
+ std::string path(td.path);
+ ASSERT_EQ(0, access((path + "/c.txt").c_str(), F_OK));
+ ASSERT_EQ(0, access((path + "/d.txt").c_str(), F_OK));
+
+ // And the rest are not extracted.
+ ASSERT_EQ(-1, access((path + "/a.txt").c_str(), F_OK));
+ ASSERT_EQ(ENOENT, errno);
+ ASSERT_EQ(-1, access((path + "/b.txt").c_str(), F_OK));
+ ASSERT_EQ(ENOENT, errno);
+
+ // The content of the file is the same as expected.
+ std::string content1;
+ ASSERT_TRUE(android::base::ReadFileToString(path + "/c.txt", &content1));
+ ASSERT_EQ(kCTxtContents, content1);
+
+ std::string content2;
+ ASSERT_TRUE(android::base::ReadFileToString(path + "/d.txt", &content2));
+ ASSERT_EQ(kDTxtContents, content2);
+
+ // Clean up the temp files under td.
+ ASSERT_EQ(0, unlink((path + "/c.txt").c_str()));
+ ASSERT_EQ(0, unlink((path + "/d.txt").c_str()));
+
+ CloseArchive(handle);
+}
+
+TEST(ZipUtilTest, extract_prefix_without_slash) {
+ std::string zip_path = from_testdata_base("ziptest_valid.zip");
+ ZipArchiveHandle handle;
+ ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
+
+ // Extract all the file entries starting with "b/".
+ TemporaryDir td;
+ ExtractPackageRecursive(handle, "b", td.path, nullptr, nullptr);
+
+ // Make sure all the files with "b/" prefix are extracted correctly.
+ std::string path(td.path);
+ ASSERT_EQ(0, access((path + "/c.txt").c_str(), F_OK));
+ ASSERT_EQ(0, access((path + "/d.txt").c_str(), F_OK));
+
+ // And the rest are not extracted.
+ ASSERT_EQ(-1, access((path + "/a.txt").c_str(), F_OK));
+ ASSERT_EQ(ENOENT, errno);
+ ASSERT_EQ(-1, access((path + "/b.txt").c_str(), F_OK));
+ ASSERT_EQ(ENOENT, errno);
+
+ // The content of the file is the same as expected.
+ std::string content1;
+ ASSERT_TRUE(android::base::ReadFileToString(path + "/c.txt", &content1));
+ ASSERT_EQ(kCTxtContents, content1);
+
+ std::string content2;
+ ASSERT_TRUE(android::base::ReadFileToString(path + "/d.txt", &content2));
+ ASSERT_EQ(kDTxtContents, content2);
+
+ // Clean up the temp files under td.
+ ASSERT_EQ(0, unlink((path + "/c.txt").c_str()));
+ ASSERT_EQ(0, unlink((path + "/d.txt").c_str()));
+
+ CloseArchive(handle);
+}
+
+TEST(ZipUtilTest, set_timestamp) {
+ std::string zip_path = from_testdata_base("ziptest_valid.zip");
+ ZipArchiveHandle handle;
+ ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
+
+ // Set the timestamp to 8/1/2008.
+ constexpr struct utimbuf timestamp = { 1217592000, 1217592000 };
+
+ // Extract all the entries starting with "b/".
+ TemporaryDir td;
+ ExtractPackageRecursive(handle, "b", td.path, &timestamp, nullptr);
+
+ // Make sure all the files with "b/" prefix are extracted correctly.
+ std::string path(td.path);
+ std::string file_c = path + "/c.txt";
+ std::string file_d = path + "/d.txt";
+ ASSERT_EQ(0, access(file_c.c_str(), F_OK));
+ ASSERT_EQ(0, access(file_d.c_str(), F_OK));
+
+ // Verify the timestamp.
+ timespec time;
+ time.tv_sec = 1217592000;
+ time.tv_nsec = 0;
+
+ struct stat sb;
+ ASSERT_EQ(0, stat(file_c.c_str(), &sb)) << strerror(errno);
+ ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_atime));
+ ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_mtime));
+
+ ASSERT_EQ(0, stat(file_d.c_str(), &sb)) << strerror(errno);
+ ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_atime));
+ ASSERT_EQ(time.tv_sec, static_cast<long>(sb.st_mtime));
+
+ // Clean up the temp files under td.
+ ASSERT_EQ(0, unlink(file_c.c_str()));
+ ASSERT_EQ(0, unlink(file_d.c_str()));
+
+ CloseArchive(handle);
+}