Merge "updater: Add testcase for package_extract_dir()." am: 23e785935e

am: d109c788ad

Change-Id: Ia682f518ef8f2a651d0ecbef37a87b52d40a0f35
This commit is contained in:
Tao Bao 2016-11-18 17:49:00 +00:00 committed by android-build-merger
commit 9b1a791e3c
3 changed files with 119 additions and 17 deletions

View file

@ -22,6 +22,8 @@
// Zip entries in ziptest_valid.zip.
static const std::string kATxtContents("abcdefghabcdefgh\n");
static const std::string kBTxtContents("abcdefgh\n");
static const std::string kCTxtContents("abcdefghabcdefgh\n");
static const std::string kDTxtContents("abcdefgh\n");
// echo -n -e "abcdefghabcdefgh\n" | sha1sum
static const std::string kATxtSha1Sum("32c96a03dc8cd20097940f351bca6261ee5a1643");

View file

@ -270,6 +270,102 @@ TEST_F(UpdaterTest, symlink) {
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.

View file

@ -454,28 +454,32 @@ Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
return StringValue(frac_str);
}
// package_extract_dir(package_path, destination_path)
Value* PackageExtractDirFn(const char* name, State* state,
int argc, Expr* argv[]) {
if (argc != 2) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
// package_extract_dir(package_dir, dest_dir)
// Extracts all files from the package underneath package_dir and writes them to the
// corresponding tree beneath dest_dir. Any existing files are overwritten.
// Example: package_extract_dir("system", "/system")
//
// Note: package_dir needs to be a relative path; dest_dir needs to be an absolute path.
Value* PackageExtractDirFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 2) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
std::vector<std::string> args;
if (!ReadArgs(state, 2, argv, &args)) {
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
}
const std::string& zip_path = args[0];
const std::string& dest_path = args[1];
std::vector<std::string> args;
if (!ReadArgs(state, 2, argv, &args)) {
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
}
const std::string& zip_path = args[0];
const std::string& dest_path = args[1];
ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip;
ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
// To create a consistent system image, never use the clock for timestamps.
struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default
// To create a consistent system image, never use the clock for timestamps.
constexpr struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default
bool success = ExtractPackageRecursive(za, zip_path, dest_path, &timestamp, sehandle);
bool success = ExtractPackageRecursive(za, zip_path, dest_path, &timestamp, sehandle);
return StringValue(success ? "t" : "");
return StringValue(success ? "t" : "");
}
// package_extract_file(package_file[, dest_file])