diff options
author | Treehugger Robot | 2016-11-02 12:19:45 -0500 |
---|---|---|
committer | Gerrit Code Review | 2016-11-02 12:19:45 -0500 |
commit | 5696526ba4810e14a4a68d5951d37cae1e1028ec (patch) | |
tree | 83fc6715016e1671b5fd4c1528c6f9b292675aed | |
parent | a9b252887c64e448dd141ede88a0fbe0c664b989 (diff) | |
parent | 36c35119526023c9e28ec22915b26b1bf7da6bc3 (diff) | |
download | platform-bootable-recovery-5696526ba4810e14a4a68d5951d37cae1e1028ec.tar.gz platform-bootable-recovery-5696526ba4810e14a4a68d5951d37cae1e1028ec.tar.xz platform-bootable-recovery-5696526ba4810e14a4a68d5951d37cae1e1028ec.zip |
Merge "applypatch: Add testcases for applypatch executable."
-rw-r--r-- | applypatch/Android.mk | 30 | ||||
-rw-r--r-- | applypatch/applypatch_main.cpp | 28 | ||||
-rw-r--r-- | applypatch/applypatch_modes.cpp (renamed from applypatch/main.cpp) | 52 | ||||
-rw-r--r-- | applypatch/applypatch_modes.h | 22 | ||||
-rw-r--r-- | tests/Android.mk | 3 | ||||
-rw-r--r-- | tests/component/applypatch_test.cpp | 578 | ||||
-rw-r--r-- | tests/testdata/bonus.file | bin | 0 -> 557334 bytes | |||
-rw-r--r-- | tests/testdata/boot.img | bin | 0 -> 783655 bytes | |||
-rw-r--r-- | tests/testdata/recovery-from-boot-with-bonus.p | bin | 0 -> 381615 bytes | |||
-rw-r--r-- | tests/testdata/recovery-from-boot.p | bin | 0 -> 5404 bytes | |||
-rw-r--r-- | tests/testdata/recovery.img | bin | 0 -> 529707 bytes |
11 files changed, 426 insertions, 287 deletions
diff --git a/applypatch/Android.mk b/applypatch/Android.mk index 9bbac441..fa0fe8a3 100644 --- a/applypatch/Android.mk +++ b/applypatch/Android.mk | |||
@@ -68,21 +68,41 @@ LOCAL_STATIC_LIBRARIES += libcrypto libbz libz | |||
68 | LOCAL_CFLAGS := -Werror | 68 | LOCAL_CFLAGS := -Werror |
69 | include $(BUILD_HOST_STATIC_LIBRARY) | 69 | include $(BUILD_HOST_STATIC_LIBRARY) |
70 | 70 | ||
71 | # applypatch (executable) | 71 | # libapplypatch_modes (static library) |
72 | # =============================== | 72 | # =============================== |
73 | include $(CLEAR_VARS) | 73 | include $(CLEAR_VARS) |
74 | LOCAL_CLANG := true | 74 | LOCAL_CLANG := true |
75 | LOCAL_SRC_FILES := main.cpp | 75 | LOCAL_SRC_FILES := \ |
76 | applypatch_modes.cpp | ||
77 | LOCAL_MODULE := libapplypatch_modes | ||
78 | LOCAL_C_INCLUDES := bootable/recovery | ||
79 | LOCAL_STATIC_LIBRARIES := \ | ||
80 | libapplypatch \ | ||
81 | libbase \ | ||
82 | libedify \ | ||
83 | libcrypto | ||
84 | LOCAL_CFLAGS := -Werror | ||
85 | include $(BUILD_STATIC_LIBRARY) | ||
86 | |||
87 | # applypatch (target executable) | ||
88 | # =============================== | ||
89 | include $(CLEAR_VARS) | ||
90 | LOCAL_CLANG := true | ||
91 | LOCAL_SRC_FILES := applypatch_main.cpp | ||
76 | LOCAL_MODULE := applypatch | 92 | LOCAL_MODULE := applypatch |
77 | LOCAL_C_INCLUDES += bootable/recovery | 93 | LOCAL_C_INCLUDES := bootable/recovery |
78 | LOCAL_STATIC_LIBRARIES += \ | 94 | LOCAL_STATIC_LIBRARIES := \ |
95 | libapplypatch_modes \ | ||
79 | libapplypatch \ | 96 | libapplypatch \ |
80 | libbase \ | 97 | libbase \ |
81 | libedify \ | 98 | libedify \ |
82 | libotafault \ | 99 | libotafault \ |
83 | libcrypto \ | 100 | libcrypto \ |
84 | libbz | 101 | libbz |
85 | LOCAL_SHARED_LIBRARIES += libbase libz libcutils libc | 102 | LOCAL_SHARED_LIBRARIES := \ |
103 | libbase \ | ||
104 | libz \ | ||
105 | libcutils | ||
86 | LOCAL_CFLAGS := -Werror | 106 | LOCAL_CFLAGS := -Werror |
87 | include $(BUILD_EXECUTABLE) | 107 | include $(BUILD_EXECUTABLE) |
88 | 108 | ||
diff --git a/applypatch/applypatch_main.cpp b/applypatch/applypatch_main.cpp new file mode 100644 index 00000000..197077c9 --- /dev/null +++ b/applypatch/applypatch_main.cpp | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include "applypatch_modes.h" | ||
18 | |||
19 | // This program (applypatch) applies binary patches to files in a way that | ||
20 | // is safe (the original file is not touched until we have the desired | ||
21 | // replacement for it) and idempotent (it's okay to run this program | ||
22 | // multiple times). | ||
23 | // | ||
24 | // See the comments to applypatch_modes() function. | ||
25 | |||
26 | int main(int argc, char** argv) { | ||
27 | return applypatch_modes(argc, const_cast<const char**>(argv)); | ||
28 | } | ||
diff --git a/applypatch/main.cpp b/applypatch/applypatch_modes.cpp index 988b6f9b..7b191a80 100644 --- a/applypatch/main.cpp +++ b/applypatch/applypatch_modes.cpp | |||
@@ -14,6 +14,8 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "applypatch_modes.h" | ||
18 | |||
17 | #include <stdio.h> | 19 | #include <stdio.h> |
18 | #include <stdlib.h> | 20 | #include <stdlib.h> |
19 | #include <string.h> | 21 | #include <string.h> |
@@ -23,12 +25,14 @@ | |||
23 | #include <string> | 25 | #include <string> |
24 | #include <vector> | 26 | #include <vector> |
25 | 27 | ||
28 | #include <android-base/parseint.h> | ||
29 | #include <android-base/strings.h> | ||
26 | #include <openssl/sha.h> | 30 | #include <openssl/sha.h> |
27 | 31 | ||
28 | #include "applypatch/applypatch.h" | 32 | #include "applypatch/applypatch.h" |
29 | #include "edify/expr.h" | 33 | #include "edify/expr.h" |
30 | 34 | ||
31 | static int CheckMode(int argc, char** argv) { | 35 | static int CheckMode(int argc, const char** argv) { |
32 | if (argc < 3) { | 36 | if (argc < 3) { |
33 | return 2; | 37 | return 2; |
34 | } | 38 | } |
@@ -40,44 +44,42 @@ static int CheckMode(int argc, char** argv) { | |||
40 | return applypatch_check(argv[2], sha1); | 44 | return applypatch_check(argv[2], sha1); |
41 | } | 45 | } |
42 | 46 | ||
43 | static int SpaceMode(int argc, char** argv) { | 47 | static int SpaceMode(int argc, const char** argv) { |
44 | if (argc != 3) { | 48 | if (argc != 3) { |
45 | return 2; | 49 | return 2; |
46 | } | 50 | } |
47 | char* endptr; | 51 | |
48 | size_t bytes = strtol(argv[2], &endptr, 10); | 52 | size_t bytes; |
49 | if (bytes == 0 && endptr == argv[2]) { | 53 | if (!android::base::ParseUint(argv[2], &bytes) || bytes == 0) { |
50 | printf("can't parse \"%s\" as byte count\n\n", argv[2]); | 54 | printf("can't parse \"%s\" as byte count\n\n", argv[2]); |
51 | return 1; | 55 | return 1; |
52 | } | 56 | } |
53 | return CacheSizeCheck(bytes); | 57 | return CacheSizeCheck(bytes); |
54 | } | 58 | } |
55 | 59 | ||
56 | // Parse arguments (which should be of the form "<sha1>:<filename>" | 60 | // Parse arguments (which should be of the form "<sha1>:<filename>" into the |
57 | // into the new parallel arrays *sha1s and *files.Returns true on | 61 | // new parallel arrays *sha1s and *files. Returns true on success. |
58 | // success. | 62 | static bool ParsePatchArgs(int argc, const char** argv, std::vector<std::string>* sha1s, |
59 | static bool ParsePatchArgs(int argc, char** argv, std::vector<std::string>* sha1s, | ||
60 | std::vector<FileContents>* files) { | 63 | std::vector<FileContents>* files) { |
61 | if (sha1s == nullptr) { | 64 | if (sha1s == nullptr) { |
62 | return false; | 65 | return false; |
63 | } | 66 | } |
64 | for (int i = 0; i < argc; ++i) { | 67 | for (int i = 0; i < argc; ++i) { |
65 | uint8_t digest[SHA_DIGEST_LENGTH]; | 68 | std::vector<std::string> pieces = android::base::Split(argv[i], ":"); |
66 | char* colon = strchr(argv[i], ':'); | 69 | if (pieces.size() != 2) { |
67 | if (colon == nullptr) { | 70 | printf("failed to parse patch argument \"%s\"\n", argv[i]); |
68 | printf("no ':' in patch argument \"%s\"\n", argv[i]); | ||
69 | return false; | 71 | return false; |
70 | } | 72 | } |
71 | *colon = '\0'; | 73 | |
72 | ++colon; | 74 | uint8_t digest[SHA_DIGEST_LENGTH]; |
73 | if (ParseSha1(argv[i], digest) != 0) { | 75 | if (ParseSha1(pieces[0].c_str(), digest) != 0) { |
74 | printf("failed to parse sha1 \"%s\"\n", argv[i]); | 76 | printf("failed to parse sha1 \"%s\"\n", argv[i]); |
75 | return false; | 77 | return false; |
76 | } | 78 | } |
77 | 79 | ||
78 | sha1s->push_back(argv[i]); | 80 | sha1s->push_back(pieces[0]); |
79 | FileContents fc; | 81 | FileContents fc; |
80 | if (LoadFileContents(colon, &fc) != 0) { | 82 | if (LoadFileContents(pieces[1].c_str(), &fc) != 0) { |
81 | return false; | 83 | return false; |
82 | } | 84 | } |
83 | files->push_back(std::move(fc)); | 85 | files->push_back(std::move(fc)); |
@@ -90,7 +92,7 @@ static int FlashMode(const char* src_filename, const char* tgt_filename, | |||
90 | return applypatch_flash(src_filename, tgt_filename, tgt_sha1, tgt_size); | 92 | return applypatch_flash(src_filename, tgt_filename, tgt_sha1, tgt_size); |
91 | } | 93 | } |
92 | 94 | ||
93 | static int PatchMode(int argc, char** argv) { | 95 | static int PatchMode(int argc, const char** argv) { |
94 | FileContents bonusFc; | 96 | FileContents bonusFc; |
95 | Value bonus(VAL_INVALID, ""); | 97 | Value bonus(VAL_INVALID, ""); |
96 | 98 | ||
@@ -109,9 +111,8 @@ static int PatchMode(int argc, char** argv) { | |||
109 | return 2; | 111 | return 2; |
110 | } | 112 | } |
111 | 113 | ||
112 | char* endptr; | 114 | size_t target_size; |
113 | size_t target_size = strtol(argv[4], &endptr, 10); | 115 | if (!android::base::ParseUint(argv[4], &target_size) || target_size == 0) { |
114 | if (target_size == 0 && endptr == argv[4]) { | ||
115 | printf("can't parse \"%s\" as byte count\n\n", argv[4]); | 116 | printf("can't parse \"%s\" as byte count\n\n", argv[4]); |
116 | return 1; | 117 | return 1; |
117 | } | 118 | } |
@@ -124,6 +125,7 @@ static int PatchMode(int argc, char** argv) { | |||
124 | } | 125 | } |
125 | return FlashMode(argv[1], argv[2], argv[3], target_size); | 126 | return FlashMode(argv[1], argv[2], argv[3], target_size); |
126 | } | 127 | } |
128 | |||
127 | std::vector<std::string> sha1s; | 129 | std::vector<std::string> sha1s; |
128 | std::vector<FileContents> files; | 130 | std::vector<FileContents> files; |
129 | if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &files)) { | 131 | if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &files)) { |
@@ -139,8 +141,8 @@ static int PatchMode(int argc, char** argv) { | |||
139 | return applypatch(argv[1], argv[2], argv[3], target_size, sha1s, patches, &bonus); | 141 | return applypatch(argv[1], argv[2], argv[3], target_size, sha1s, patches, &bonus); |
140 | } | 142 | } |
141 | 143 | ||
142 | // This program applies binary patches to files in a way that is safe | 144 | // This program (applypatch) applies binary patches to files in a way that |
143 | // (the original file is not touched until we have the desired | 145 | // is safe (the original file is not touched until we have the desired |
144 | // replacement for it) and idempotent (it's okay to run this program | 146 | // replacement for it) and idempotent (it's okay to run this program |
145 | // multiple times). | 147 | // multiple times). |
146 | // | 148 | // |
@@ -166,7 +168,7 @@ static int PatchMode(int argc, char** argv) { | |||
166 | // to read the source data. See the comments for the | 168 | // to read the source data. See the comments for the |
167 | // LoadPartitionContents() function for the format of such a filename. | 169 | // LoadPartitionContents() function for the format of such a filename. |
168 | 170 | ||
169 | int main(int argc, char** argv) { | 171 | int applypatch_modes(int argc, const char** argv) { |
170 | if (argc < 2) { | 172 | if (argc < 2) { |
171 | usage: | 173 | usage: |
172 | printf( | 174 | printf( |
diff --git a/applypatch/applypatch_modes.h b/applypatch/applypatch_modes.h new file mode 100644 index 00000000..3d9d08df --- /dev/null +++ b/applypatch/applypatch_modes.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef _APPLYPATCH_MODES_H | ||
18 | #define _APPLYPATCH_MODES_H | ||
19 | |||
20 | int applypatch_modes(int argc, const char** argv); | ||
21 | |||
22 | #endif // _APPLYPATCH_MODES_H | ||
diff --git a/tests/Android.mk b/tests/Android.mk index 3d05386b..461d6ef7 100644 --- a/tests/Android.mk +++ b/tests/Android.mk | |||
@@ -43,7 +43,7 @@ include $(BUILD_NATIVE_TEST) | |||
43 | # Component tests | 43 | # Component tests |
44 | include $(CLEAR_VARS) | 44 | include $(CLEAR_VARS) |
45 | LOCAL_CLANG := true | 45 | LOCAL_CLANG := true |
46 | LOCAL_CFLAGS += -Wno-unused-parameter -Werror | 46 | LOCAL_CFLAGS := -Werror |
47 | LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk | 47 | LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk |
48 | LOCAL_MODULE := recovery_component_test | 48 | LOCAL_MODULE := recovery_component_test |
49 | LOCAL_C_INCLUDES := bootable/recovery | 49 | LOCAL_C_INCLUDES := bootable/recovery |
@@ -63,6 +63,7 @@ tune2fs_static_libraries := \ | |||
63 | libext2fs | 63 | libext2fs |
64 | 64 | ||
65 | LOCAL_STATIC_LIBRARIES := \ | 65 | LOCAL_STATIC_LIBRARIES := \ |
66 | libapplypatch_modes \ | ||
66 | libapplypatch \ | 67 | libapplypatch \ |
67 | libedify \ | 68 | libedify \ |
68 | libotafault \ | 69 | libotafault \ |
diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp index e09c1e7b..f95ebed5 100644 --- a/tests/component/applypatch_test.cpp +++ b/tests/component/applypatch_test.cpp | |||
@@ -33,149 +33,155 @@ | |||
33 | #include <openssl/sha.h> | 33 | #include <openssl/sha.h> |
34 | 34 | ||
35 | #include "applypatch/applypatch.h" | 35 | #include "applypatch/applypatch.h" |
36 | #include "applypatch/applypatch_modes.h" | ||
36 | #include "common/test_constants.h" | 37 | #include "common/test_constants.h" |
37 | #include "print_sha1.h" | 38 | #include "print_sha1.h" |
38 | 39 | ||
39 | static const std::string DATA_PATH = getenv("ANDROID_DATA"); | 40 | static const std::string DATA_PATH = getenv("ANDROID_DATA"); |
40 | static const std::string TESTDATA_PATH = "/recovery/testdata"; | 41 | static const std::string TESTDATA_PATH = "/recovery/testdata"; |
41 | 42 | ||
42 | static void sha1sum(const std::string& fname, std::string* sha1) { | 43 | static void sha1sum(const std::string& fname, std::string* sha1, size_t* fsize = nullptr) { |
43 | ASSERT_NE(nullptr, sha1); | 44 | ASSERT_NE(nullptr, sha1); |
44 | 45 | ||
45 | std::string data; | 46 | std::string data; |
46 | ASSERT_TRUE(android::base::ReadFileToString(fname, &data)); | 47 | ASSERT_TRUE(android::base::ReadFileToString(fname, &data)); |
47 | 48 | ||
48 | uint8_t digest[SHA_DIGEST_LENGTH]; | 49 | if (fsize != nullptr) { |
49 | SHA1(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), digest); | 50 | *fsize = data.size(); |
50 | *sha1 = print_sha1(digest); | 51 | } |
52 | |||
53 | uint8_t digest[SHA_DIGEST_LENGTH]; | ||
54 | SHA1(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), digest); | ||
55 | *sha1 = print_sha1(digest); | ||
51 | } | 56 | } |
52 | 57 | ||
53 | static void mangle_file(const std::string& fname) { | 58 | static void mangle_file(const std::string& fname) { |
54 | std::string content; | 59 | std::string content; |
55 | content.reserve(1024); | 60 | content.reserve(1024); |
56 | for (size_t i = 0; i < 1024; i++) { | 61 | for (size_t i = 0; i < 1024; i++) { |
57 | content[i] = rand() % 256; | 62 | content[i] = rand() % 256; |
58 | } | 63 | } |
59 | ASSERT_TRUE(android::base::WriteStringToFile(content, fname)); | 64 | ASSERT_TRUE(android::base::WriteStringToFile(content, fname)); |
60 | } | 65 | } |
61 | 66 | ||
62 | static bool file_cmp(const std::string& f1, const std::string& f2) { | 67 | static bool file_cmp(const std::string& f1, const std::string& f2) { |
63 | std::string c1; | 68 | std::string c1; |
64 | android::base::ReadFileToString(f1, &c1); | 69 | android::base::ReadFileToString(f1, &c1); |
65 | std::string c2; | 70 | std::string c2; |
66 | android::base::ReadFileToString(f2, &c2); | 71 | android::base::ReadFileToString(f2, &c2); |
67 | return c1 == c2; | 72 | return c1 == c2; |
68 | } | 73 | } |
69 | 74 | ||
70 | static std::string from_testdata_base(const std::string& fname) { | 75 | static std::string from_testdata_base(const std::string& fname) { |
71 | return DATA_PATH + NATIVE_TEST_PATH + TESTDATA_PATH + "/" + fname; | 76 | return DATA_PATH + NATIVE_TEST_PATH + TESTDATA_PATH + "/" + fname; |
72 | } | 77 | } |
73 | 78 | ||
74 | class ApplyPatchTest : public ::testing::Test { | 79 | class ApplyPatchTest : public ::testing::Test { |
75 | public: | 80 | public: |
76 | static void SetUpTestCase() { | 81 | static void SetUpTestCase() { |
77 | // set up files | 82 | // set up files |
78 | old_file = from_testdata_base("old.file"); | 83 | old_file = from_testdata_base("old.file"); |
79 | new_file = from_testdata_base("new.file"); | 84 | new_file = from_testdata_base("new.file"); |
80 | patch_file = from_testdata_base("patch.bsdiff"); | 85 | patch_file = from_testdata_base("patch.bsdiff"); |
81 | rand_file = "/cache/applypatch_test_rand.file"; | 86 | rand_file = "/cache/applypatch_test_rand.file"; |
82 | cache_file = "/cache/saved.file"; | 87 | cache_file = "/cache/saved.file"; |
83 | 88 | ||
84 | // write stuff to rand_file | 89 | // write stuff to rand_file |
85 | ASSERT_TRUE(android::base::WriteStringToFile("hello", rand_file)); | 90 | ASSERT_TRUE(android::base::WriteStringToFile("hello", rand_file)); |
86 | 91 | ||
87 | // set up SHA constants | 92 | // set up SHA constants |
88 | sha1sum(old_file, &old_sha1); | 93 | sha1sum(old_file, &old_sha1); |
89 | sha1sum(new_file, &new_sha1); | 94 | sha1sum(new_file, &new_sha1); |
90 | srand(time(NULL)); | 95 | srand(time(nullptr)); |
91 | bad_sha1_a = android::base::StringPrintf("%040x", rand()); | 96 | bad_sha1_a = android::base::StringPrintf("%040x", rand()); |
92 | bad_sha1_b = android::base::StringPrintf("%040x", rand()); | 97 | bad_sha1_b = android::base::StringPrintf("%040x", rand()); |
93 | 98 | ||
94 | struct stat st; | 99 | struct stat st; |
95 | stat(&new_file[0], &st); | 100 | stat(&new_file[0], &st); |
96 | new_size = st.st_size; | 101 | new_size = st.st_size; |
97 | } | 102 | } |
98 | 103 | ||
99 | static std::string old_file; | 104 | static std::string old_file; |
100 | static std::string new_file; | 105 | static std::string new_file; |
101 | static std::string rand_file; | 106 | static std::string rand_file; |
102 | static std::string cache_file; | 107 | static std::string cache_file; |
103 | static std::string patch_file; | 108 | static std::string patch_file; |
104 | 109 | ||
105 | static std::string old_sha1; | 110 | static std::string old_sha1; |
106 | static std::string new_sha1; | 111 | static std::string new_sha1; |
107 | static std::string bad_sha1_a; | 112 | static std::string bad_sha1_a; |
108 | static std::string bad_sha1_b; | 113 | static std::string bad_sha1_b; |
109 | 114 | ||
110 | static size_t new_size; | 115 | static size_t new_size; |
111 | }; | 116 | }; |
112 | 117 | ||
113 | std::string ApplyPatchTest::old_file; | 118 | std::string ApplyPatchTest::old_file; |
114 | std::string ApplyPatchTest::new_file; | 119 | std::string ApplyPatchTest::new_file; |
115 | 120 | ||
116 | static void cp(const std::string& src, const std::string& tgt) { | 121 | static void cp(const std::string& src, const std::string& tgt) { |
117 | std::string cmd = "cp " + src + " " + tgt; | 122 | std::string cmd = "cp " + src + " " + tgt; |
118 | system(&cmd[0]); | 123 | system(cmd.c_str()); |
119 | } | 124 | } |
120 | 125 | ||
121 | static void backup_old() { | 126 | static void backup_old() { |
122 | cp(ApplyPatchTest::old_file, ApplyPatchTest::cache_file); | 127 | cp(ApplyPatchTest::old_file, ApplyPatchTest::cache_file); |
123 | } | 128 | } |
124 | 129 | ||
125 | static void restore_old() { | 130 | static void restore_old() { |
126 | cp(ApplyPatchTest::cache_file, ApplyPatchTest::old_file); | 131 | cp(ApplyPatchTest::cache_file, ApplyPatchTest::old_file); |
127 | } | 132 | } |
128 | 133 | ||
129 | class ApplyPatchCacheTest : public ApplyPatchTest { | 134 | class ApplyPatchCacheTest : public ApplyPatchTest { |
130 | public: | 135 | public: |
131 | virtual void SetUp() { | 136 | virtual void SetUp() { |
132 | backup_old(); | 137 | backup_old(); |
133 | } | 138 | } |
134 | 139 | ||
135 | virtual void TearDown() { | 140 | virtual void TearDown() { |
136 | restore_old(); | 141 | restore_old(); |
137 | } | 142 | } |
138 | }; | 143 | }; |
139 | 144 | ||
140 | class ApplyPatchFullTest : public ApplyPatchCacheTest { | 145 | class ApplyPatchFullTest : public ApplyPatchCacheTest { |
141 | public: | 146 | public: |
142 | static void SetUpTestCase() { | 147 | static void SetUpTestCase() { |
143 | ApplyPatchTest::SetUpTestCase(); | 148 | ApplyPatchTest::SetUpTestCase(); |
144 | 149 | ||
145 | output_f = new TemporaryFile(); | 150 | output_f = new TemporaryFile(); |
146 | output_loc = std::string(output_f->path); | 151 | output_loc = std::string(output_f->path); |
147 | 152 | ||
148 | struct FileContents fc; | 153 | struct FileContents fc; |
149 | 154 | ||
150 | ASSERT_EQ(0, LoadFileContents(&rand_file[0], &fc)); | 155 | ASSERT_EQ(0, LoadFileContents(&rand_file[0], &fc)); |
151 | patches.push_back( | 156 | patches.push_back( |
152 | std::make_unique<Value>(VAL_BLOB, std::string(fc.data.begin(), fc.data.end()))); | 157 | std::make_unique<Value>(VAL_BLOB, std::string(fc.data.begin(), fc.data.end()))); |
153 | 158 | ||
154 | ASSERT_EQ(0, LoadFileContents(&patch_file[0], &fc)); | 159 | ASSERT_EQ(0, LoadFileContents(&patch_file[0], &fc)); |
155 | patches.push_back( | 160 | patches.push_back( |
156 | std::make_unique<Value>(VAL_BLOB, std::string(fc.data.begin(), fc.data.end()))); | 161 | std::make_unique<Value>(VAL_BLOB, std::string(fc.data.begin(), fc.data.end()))); |
157 | } | 162 | } |
158 | 163 | ||
159 | static void TearDownTestCase() { | 164 | static void TearDownTestCase() { |
160 | delete output_f; | 165 | delete output_f; |
161 | } | 166 | patches.clear(); |
167 | } | ||
162 | 168 | ||
163 | static std::vector<std::unique_ptr<Value>> patches; | 169 | static std::vector<std::unique_ptr<Value>> patches; |
164 | static TemporaryFile* output_f; | 170 | static TemporaryFile* output_f; |
165 | static std::string output_loc; | 171 | static std::string output_loc; |
166 | }; | 172 | }; |
167 | 173 | ||
168 | class ApplyPatchDoubleCacheTest : public ApplyPatchFullTest { | 174 | class ApplyPatchDoubleCacheTest : public ApplyPatchFullTest { |
169 | public: | 175 | public: |
170 | virtual void SetUp() { | 176 | virtual void SetUp() { |
171 | ApplyPatchCacheTest::SetUp(); | 177 | ApplyPatchCacheTest::SetUp(); |
172 | cp(cache_file, "/cache/reallysaved.file"); | 178 | cp(cache_file, "/cache/reallysaved.file"); |
173 | } | 179 | } |
174 | 180 | ||
175 | virtual void TearDown() { | 181 | virtual void TearDown() { |
176 | cp("/cache/reallysaved.file", cache_file); | 182 | cp("/cache/reallysaved.file", cache_file); |
177 | ApplyPatchCacheTest::TearDown(); | 183 | ApplyPatchCacheTest::TearDown(); |
178 | } | 184 | } |
179 | }; | 185 | }; |
180 | 186 | ||
181 | std::string ApplyPatchTest::rand_file; | 187 | std::string ApplyPatchTest::rand_file; |
@@ -193,203 +199,263 @@ TemporaryFile* ApplyPatchFullTest::output_f; | |||
193 | std::string ApplyPatchFullTest::output_loc; | 199 | std::string ApplyPatchFullTest::output_loc; |
194 | 200 | ||
195 | TEST_F(ApplyPatchTest, CheckModeSkip) { | 201 | TEST_F(ApplyPatchTest, CheckModeSkip) { |
196 | std::vector<std::string> sha1s; | 202 | std::vector<std::string> sha1s; |
197 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); | 203 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); |
198 | } | 204 | } |
199 | 205 | ||
200 | TEST_F(ApplyPatchTest, CheckModeSingle) { | 206 | TEST_F(ApplyPatchTest, CheckModeSingle) { |
201 | std::vector<std::string> sha1s = { old_sha1 }; | 207 | std::vector<std::string> sha1s = { old_sha1 }; |
202 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); | 208 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); |
203 | } | 209 | } |
204 | 210 | ||
205 | TEST_F(ApplyPatchTest, CheckModeMultiple) { | 211 | TEST_F(ApplyPatchTest, CheckModeMultiple) { |
206 | std::vector<std::string> sha1s = { | 212 | std::vector<std::string> sha1s = { bad_sha1_a, old_sha1, bad_sha1_b }; |
207 | bad_sha1_a, | 213 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); |
208 | old_sha1, | ||
209 | bad_sha1_b | ||
210 | }; | ||
211 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); | ||
212 | } | 214 | } |
213 | 215 | ||
214 | TEST_F(ApplyPatchTest, CheckModeFailure) { | 216 | TEST_F(ApplyPatchTest, CheckModeFailure) { |
215 | std::vector<std::string> sha1s = { | 217 | std::vector<std::string> sha1s = { bad_sha1_a, bad_sha1_b }; |
216 | bad_sha1_a, | 218 | ASSERT_NE(0, applypatch_check(&old_file[0], sha1s)); |
217 | bad_sha1_b | ||
218 | }; | ||
219 | ASSERT_NE(0, applypatch_check(&old_file[0], sha1s)); | ||
220 | } | 219 | } |
221 | 220 | ||
222 | TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedSingle) { | 221 | TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedSingle) { |
223 | mangle_file(old_file); | 222 | mangle_file(old_file); |
224 | std::vector<std::string> sha1s = { old_sha1 }; | 223 | std::vector<std::string> sha1s = { old_sha1 }; |
225 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); | 224 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); |
226 | } | 225 | } |
227 | 226 | ||
228 | TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedMultiple) { | 227 | TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedMultiple) { |
229 | mangle_file(old_file); | 228 | mangle_file(old_file); |
230 | std::vector<std::string> sha1s = { | 229 | std::vector<std::string> sha1s = { bad_sha1_a, old_sha1, bad_sha1_b }; |
231 | bad_sha1_a, | 230 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); |
232 | old_sha1, | ||
233 | bad_sha1_b | ||
234 | }; | ||
235 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); | ||
236 | } | 231 | } |
237 | 232 | ||
238 | TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedFailure) { | 233 | TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedFailure) { |
239 | mangle_file(old_file); | 234 | mangle_file(old_file); |
240 | std::vector<std::string> sha1s = { | 235 | std::vector<std::string> sha1s = { bad_sha1_a, bad_sha1_b }; |
241 | bad_sha1_a, | 236 | ASSERT_NE(0, applypatch_check(&old_file[0], sha1s)); |
242 | bad_sha1_b | ||
243 | }; | ||
244 | ASSERT_NE(0, applypatch_check(&old_file[0], sha1s)); | ||
245 | } | 237 | } |
246 | 238 | ||
247 | TEST_F(ApplyPatchCacheTest, CheckCacheMissingSingle) { | 239 | TEST_F(ApplyPatchCacheTest, CheckCacheMissingSingle) { |
248 | unlink(&old_file[0]); | 240 | unlink(&old_file[0]); |
249 | std::vector<std::string> sha1s = { old_sha1 }; | 241 | std::vector<std::string> sha1s = { old_sha1 }; |
250 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); | 242 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); |
251 | } | 243 | } |
252 | 244 | ||
253 | TEST_F(ApplyPatchCacheTest, CheckCacheMissingMultiple) { | 245 | TEST_F(ApplyPatchCacheTest, CheckCacheMissingMultiple) { |
254 | unlink(&old_file[0]); | 246 | unlink(&old_file[0]); |
255 | std::vector<std::string> sha1s = { | 247 | std::vector<std::string> sha1s = { bad_sha1_a, old_sha1, bad_sha1_b }; |
256 | bad_sha1_a, | 248 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); |
257 | old_sha1, | ||
258 | bad_sha1_b | ||
259 | }; | ||
260 | ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); | ||
261 | } | 249 | } |
262 | 250 | ||
263 | TEST_F(ApplyPatchCacheTest, CheckCacheMissingFailure) { | 251 | TEST_F(ApplyPatchCacheTest, CheckCacheMissingFailure) { |
264 | unlink(&old_file[0]); | 252 | unlink(&old_file[0]); |
265 | std::vector<std::string> sha1s = { | 253 | std::vector<std::string> sha1s = { bad_sha1_a, bad_sha1_b }; |
266 | bad_sha1_a, | 254 | ASSERT_NE(0, applypatch_check(&old_file[0], sha1s)); |
267 | bad_sha1_b | ||
268 | }; | ||
269 | ASSERT_NE(0, applypatch_check(&old_file[0], sha1s)); | ||
270 | } | 255 | } |
271 | 256 | ||
272 | TEST_F(ApplyPatchFullTest, ApplyInPlace) { | 257 | TEST_F(ApplyPatchFullTest, ApplyInPlace) { |
273 | std::vector<std::string> sha1s = { | 258 | std::vector<std::string> sha1s = { bad_sha1_a, old_sha1 }; |
274 | bad_sha1_a, | 259 | ASSERT_EQ(0, applypatch(&old_file[0], "-", &new_sha1[0], new_size, sha1s, patches, nullptr)); |
275 | old_sha1 | 260 | ASSERT_TRUE(file_cmp(old_file, new_file)); |
276 | }; | 261 | |
277 | int ap_result = applypatch(&old_file[0], | 262 | // reapply, applypatch is idempotent so it should succeed |
278 | "-", | 263 | ASSERT_EQ(0, applypatch(&old_file[0], "-", &new_sha1[0], new_size, sha1s, patches, nullptr)); |
279 | &new_sha1[0], | 264 | ASSERT_TRUE(file_cmp(old_file, new_file)); |
280 | new_size, | ||
281 | sha1s, | ||
282 | patches, | ||
283 | nullptr); | ||
284 | ASSERT_EQ(0, ap_result); | ||
285 | ASSERT_TRUE(file_cmp(old_file, new_file)); | ||
286 | // reapply, applypatch is idempotent so it should succeed | ||
287 | ap_result = applypatch(&old_file[0], | ||
288 | "-", | ||
289 | &new_sha1[0], | ||
290 | new_size, | ||
291 | sha1s, | ||
292 | patches, | ||
293 | nullptr); | ||
294 | ASSERT_EQ(0, ap_result); | ||
295 | ASSERT_TRUE(file_cmp(old_file, new_file)); | ||
296 | } | 265 | } |
297 | 266 | ||
298 | TEST_F(ApplyPatchFullTest, ApplyInNewLocation) { | 267 | TEST_F(ApplyPatchFullTest, ApplyInNewLocation) { |
299 | std::vector<std::string> sha1s = { | 268 | std::vector<std::string> sha1s = { bad_sha1_a, old_sha1 }; |
300 | bad_sha1_a, | 269 | // Apply bsdiff patch to new location. |
301 | old_sha1 | 270 | ASSERT_EQ( |
302 | }; | 271 | 0, applypatch(&old_file[0], &output_loc[0], &new_sha1[0], new_size, sha1s, patches, nullptr)); |
303 | // Apply bsdiff patch to new location. | 272 | ASSERT_TRUE(file_cmp(output_loc, new_file)); |
304 | ASSERT_EQ(0, applypatch(&old_file[0], | 273 | |
305 | &output_loc[0], | 274 | // Reapply to the same location. |
306 | &new_sha1[0], | 275 | ASSERT_EQ( |
307 | new_size, | 276 | 0, applypatch(&old_file[0], &output_loc[0], &new_sha1[0], new_size, sha1s, patches, nullptr)); |
308 | sha1s, | 277 | ASSERT_TRUE(file_cmp(output_loc, new_file)); |
309 | patches, | ||
310 | nullptr)); | ||
311 | ASSERT_TRUE(file_cmp(output_loc, new_file)); | ||
312 | |||
313 | // Reapply to the same location. | ||
314 | ASSERT_EQ(0, applypatch(&old_file[0], | ||
315 | &output_loc[0], | ||
316 | &new_sha1[0], | ||
317 | new_size, | ||
318 | sha1s, | ||
319 | patches, | ||
320 | nullptr)); | ||
321 | ASSERT_TRUE(file_cmp(output_loc, new_file)); | ||
322 | } | 278 | } |
323 | 279 | ||
324 | TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) { | 280 | TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) { |
325 | std::vector<std::string> sha1s = { | 281 | std::vector<std::string> sha1s = { bad_sha1_a, old_sha1 }; |
326 | bad_sha1_a, | 282 | // Apply bsdiff patch to new location with corrupted source. |
327 | old_sha1 | 283 | mangle_file(old_file); |
328 | }; | 284 | ASSERT_EQ( |
329 | // Apply bsdiff patch to new location with corrupted source. | 285 | 0, applypatch(&old_file[0], &output_loc[0], &new_sha1[0], new_size, sha1s, patches, nullptr)); |
330 | mangle_file(old_file); | 286 | ASSERT_TRUE(file_cmp(output_loc, new_file)); |
331 | int ap_result = applypatch(&old_file[0], | 287 | |
332 | &output_loc[0], | 288 | // Reapply bsdiff patch to new location with corrupted source. |
333 | &new_sha1[0], | 289 | ASSERT_EQ( |
334 | new_size, | 290 | 0, applypatch(&old_file[0], &output_loc[0], &new_sha1[0], new_size, sha1s, patches, nullptr)); |
335 | sha1s, | 291 | ASSERT_TRUE(file_cmp(output_loc, new_file)); |
336 | patches, | ||
337 | nullptr); | ||
338 | ASSERT_EQ(0, ap_result); | ||
339 | ASSERT_TRUE(file_cmp(output_loc, new_file)); | ||
340 | |||
341 | // Reapply bsdiff patch to new location with corrupted source. | ||
342 | ap_result = applypatch(&old_file[0], | ||
343 | &output_loc[0], | ||
344 | &new_sha1[0], | ||
345 | new_size, | ||
346 | sha1s, | ||
347 | patches, | ||
348 | nullptr); | ||
349 | ASSERT_EQ(0, ap_result); | ||
350 | ASSERT_TRUE(file_cmp(output_loc, new_file)); | ||
351 | } | 292 | } |
352 | 293 | ||
353 | TEST_F(ApplyPatchDoubleCacheTest, ApplyDoubleCorruptedInNewLocation) { | 294 | TEST_F(ApplyPatchDoubleCacheTest, ApplyDoubleCorruptedInNewLocation) { |
354 | std::vector<std::string> sha1s = { | 295 | std::vector<std::string> sha1s = { bad_sha1_a, old_sha1 }; |
355 | bad_sha1_a, | 296 | |
356 | old_sha1 | 297 | // Apply bsdiff patch to new location with corrupted source and copy (no new file). |
357 | }; | 298 | // Expected to fail. |
358 | 299 | mangle_file(old_file); | |
359 | // Apply bsdiff patch to new location with corrupted source and copy (no new file). | 300 | mangle_file(cache_file); |
360 | // Expected to fail. | 301 | ASSERT_NE( |
361 | mangle_file(old_file); | 302 | 0, applypatch(&old_file[0], &output_loc[0], &new_sha1[0], new_size, sha1s, patches, nullptr)); |
362 | mangle_file(cache_file); | 303 | ASSERT_FALSE(file_cmp(output_loc, new_file)); |
363 | int ap_result = applypatch(&old_file[0], | 304 | |
364 | &output_loc[0], | 305 | // Expected to fail again on retry. |
365 | &new_sha1[0], | 306 | ASSERT_NE( |
366 | new_size, | 307 | 0, applypatch(&old_file[0], &output_loc[0], &new_sha1[0], new_size, sha1s, patches, nullptr)); |
367 | sha1s, | 308 | ASSERT_FALSE(file_cmp(output_loc, new_file)); |
368 | patches, | 309 | |
369 | nullptr); | 310 | // Expected to fail with incorrect new file. |
370 | ASSERT_NE(0, ap_result); | 311 | mangle_file(output_loc); |
371 | ASSERT_FALSE(file_cmp(output_loc, new_file)); | 312 | ASSERT_NE( |
372 | 313 | 0, applypatch(&old_file[0], &output_loc[0], &new_sha1[0], new_size, sha1s, patches, nullptr)); | |
373 | // Expected to fail again on retry. | 314 | ASSERT_FALSE(file_cmp(output_loc, new_file)); |
374 | ap_result = applypatch(&old_file[0], | 315 | } |
375 | &output_loc[0], | 316 | |
376 | &new_sha1[0], | 317 | TEST(ApplyPatchModes, InvalidArgs) { |
377 | new_size, | 318 | // At least two args (including the filename). |
378 | sha1s, | 319 | ASSERT_EQ(2, applypatch_modes(1, (const char* []){ "applypatch" })); |
379 | patches, | 320 | |
380 | nullptr); | 321 | // Unrecognized args. |
381 | ASSERT_NE(0, ap_result); | 322 | ASSERT_EQ(2, applypatch_modes(2, (const char* []){ "applypatch", "-x" })); |
382 | ASSERT_FALSE(file_cmp(output_loc, new_file)); | 323 | } |
383 | 324 | ||
384 | // Expected to fail with incorrect new file. | 325 | TEST(ApplyPatchModes, PatchMode) { |
385 | mangle_file(output_loc); | 326 | std::string boot_img = from_testdata_base("boot.img"); |
386 | ap_result = applypatch(&old_file[0], | 327 | size_t boot_img_size; |
387 | &output_loc[0], | 328 | std::string boot_img_sha1; |
388 | &new_sha1[0], | 329 | sha1sum(boot_img, &boot_img_sha1, &boot_img_size); |
389 | new_size, | 330 | |
390 | sha1s, | 331 | std::string recovery_img = from_testdata_base("recovery.img"); |
391 | patches, | 332 | size_t recovery_img_size; |
392 | nullptr); | 333 | std::string recovery_img_sha1; |
393 | ASSERT_NE(0, ap_result); | 334 | sha1sum(recovery_img, &recovery_img_sha1, &recovery_img_size); |
394 | ASSERT_FALSE(file_cmp(output_loc, new_file)); | 335 | |
336 | std::string bonus_file = from_testdata_base("bonus.file"); | ||
337 | |||
338 | // applypatch -b <bonus-file> <src-file> <tgt-file> <tgt-sha1> <tgt-size> <src-sha1>:<patch> | ||
339 | TemporaryFile tmp1; | ||
340 | std::vector<const char*> args = { | ||
341 | "applypatch", | ||
342 | "-b", | ||
343 | bonus_file.c_str(), | ||
344 | boot_img.c_str(), | ||
345 | tmp1.path, | ||
346 | recovery_img_sha1.c_str(), | ||
347 | std::to_string(recovery_img_size).c_str(), | ||
348 | (boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot.p")).c_str() | ||
349 | }; | ||
350 | ASSERT_EQ(0, applypatch_modes(args.size(), args.data())); | ||
351 | |||
352 | // applypatch <src-file> <tgt-file> <tgt-sha1> <tgt-size> <src-sha1>:<patch> | ||
353 | TemporaryFile tmp2; | ||
354 | std::vector<const char*> args2 = { | ||
355 | "applypatch", | ||
356 | boot_img.c_str(), | ||
357 | tmp2.path, | ||
358 | recovery_img_sha1.c_str(), | ||
359 | std::to_string(recovery_img_size).c_str(), | ||
360 | (boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot-with-bonus.p")).c_str() | ||
361 | }; | ||
362 | ASSERT_EQ(0, applypatch_modes(args2.size(), args2.data())); | ||
363 | |||
364 | // applypatch -b <bonus-file> <src-file> <tgt-file> <tgt-sha1> <tgt-size> \ | ||
365 | // <src-sha1-fake>:<patch1> <src-sha1>:<patch2> | ||
366 | TemporaryFile tmp3; | ||
367 | std::string bad_sha1_a = android::base::StringPrintf("%040x", rand()); | ||
368 | std::string bad_sha1_b = android::base::StringPrintf("%040x", rand()); | ||
369 | std::vector<const char*> args3 = { | ||
370 | "applypatch", | ||
371 | "-b", | ||
372 | bonus_file.c_str(), | ||
373 | boot_img.c_str(), | ||
374 | tmp3.path, | ||
375 | recovery_img_sha1.c_str(), | ||
376 | std::to_string(recovery_img_size).c_str(), | ||
377 | (bad_sha1_a + ":" + from_testdata_base("recovery-from-boot.p")).c_str(), | ||
378 | (boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot.p")).c_str(), | ||
379 | (bad_sha1_b + ":" + from_testdata_base("recovery-from-boot.p")).c_str(), | ||
380 | }; | ||
381 | ASSERT_EQ(0, applypatch_modes(args3.size(), args3.data())); | ||
382 | } | ||
383 | |||
384 | TEST(ApplyPatchModes, PatchModeInvalidArgs) { | ||
385 | // Invalid bonus file. | ||
386 | ASSERT_NE(0, applypatch_modes(3, (const char* []){ "applypatch", "-b", "/doesntexist" })); | ||
387 | |||
388 | std::string bonus_file = from_testdata_base("bonus.file"); | ||
389 | // With bonus file, but missing args. | ||
390 | ASSERT_EQ(2, applypatch_modes(3, (const char* []){ "applypatch", "-b", bonus_file.c_str() })); | ||
391 | |||
392 | std::string boot_img = from_testdata_base("boot.img"); | ||
393 | size_t boot_img_size; | ||
394 | std::string boot_img_sha1; | ||
395 | sha1sum(boot_img, &boot_img_sha1, &boot_img_size); | ||
396 | |||
397 | std::string recovery_img = from_testdata_base("recovery.img"); | ||
398 | size_t recovery_img_size; | ||
399 | std::string recovery_img_sha1; | ||
400 | sha1sum(recovery_img, &recovery_img_sha1, &recovery_img_size); | ||
401 | |||
402 | // Bonus file is not supported in flash mode. | ||
403 | // applypatch -b <bonus-file> <src-file> <tgt-file> <tgt-sha1> <tgt-size> | ||
404 | TemporaryFile tmp4; | ||
405 | std::vector<const char*> args4 = { | ||
406 | "applypatch", | ||
407 | "-b", | ||
408 | bonus_file.c_str(), | ||
409 | boot_img.c_str(), | ||
410 | tmp4.path, | ||
411 | recovery_img_sha1.c_str(), | ||
412 | std::to_string(recovery_img_size).c_str() }; | ||
413 | ASSERT_NE(0, applypatch_modes(args4.size(), args4.data())); | ||
414 | |||
415 | // Failed to parse patch args. | ||
416 | TemporaryFile tmp5; | ||
417 | std::vector<const char*> args5 = { | ||
418 | "applypatch", | ||
419 | boot_img.c_str(), | ||
420 | tmp5.path, | ||
421 | recovery_img_sha1.c_str(), | ||
422 | std::to_string(recovery_img_size).c_str(), | ||
423 | ("invalid-sha1:filename" + from_testdata_base("recovery-from-boot-with-bonus.p")).c_str(), | ||
424 | }; | ||
425 | ASSERT_NE(0, applypatch_modes(args5.size(), args5.data())); | ||
426 | |||
427 | // Target size cannot be zero. | ||
428 | TemporaryFile tmp6; | ||
429 | std::vector<const char*> args6 = { | ||
430 | "applypatch", | ||
431 | boot_img.c_str(), | ||
432 | tmp6.path, | ||
433 | recovery_img_sha1.c_str(), | ||
434 | "0", // target size | ||
435 | (boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot-with-bonus.p")).c_str() | ||
436 | }; | ||
437 | ASSERT_NE(0, applypatch_modes(args6.size(), args6.data())); | ||
438 | } | ||
439 | |||
440 | TEST(ApplyPatchModes, CheckModeInvalidArgs) { | ||
441 | // Insufficient args. | ||
442 | ASSERT_EQ(2, applypatch_modes(2, (const char* []){ "applypatch", "-c" })); | ||
443 | } | ||
444 | |||
445 | TEST(ApplyPatchModes, SpaceModeInvalidArgs) { | ||
446 | // Insufficient args. | ||
447 | ASSERT_EQ(2, applypatch_modes(2, (const char* []){ "applypatch", "-s" })); | ||
448 | |||
449 | // Invalid bytes arg. | ||
450 | ASSERT_EQ(1, applypatch_modes(3, (const char* []){ "applypatch", "-s", "x" })); | ||
451 | |||
452 | // 0 is invalid. | ||
453 | ASSERT_EQ(1, applypatch_modes(3, (const char* []){ "applypatch", "-s", "0" })); | ||
454 | |||
455 | // 0x10 is fine. | ||
456 | ASSERT_EQ(0, applypatch_modes(3, (const char* []){ "applypatch", "-s", "0x10" })); | ||
457 | } | ||
458 | |||
459 | TEST(ApplyPatchModes, ShowLicenses) { | ||
460 | ASSERT_EQ(0, applypatch_modes(2, (const char* []){ "applypatch", "-l" })); | ||
395 | } | 461 | } |
diff --git a/tests/testdata/bonus.file b/tests/testdata/bonus.file new file mode 100644 index 00000000..918ef8ac --- /dev/null +++ b/tests/testdata/bonus.file | |||
Binary files differ | |||
diff --git a/tests/testdata/boot.img b/tests/testdata/boot.img new file mode 100644 index 00000000..dd489751 --- /dev/null +++ b/tests/testdata/boot.img | |||
Binary files differ | |||
diff --git a/tests/testdata/recovery-from-boot-with-bonus.p b/tests/testdata/recovery-from-boot-with-bonus.p new file mode 100644 index 00000000..08b6f55e --- /dev/null +++ b/tests/testdata/recovery-from-boot-with-bonus.p | |||
Binary files differ | |||
diff --git a/tests/testdata/recovery-from-boot.p b/tests/testdata/recovery-from-boot.p new file mode 100644 index 00000000..06f6c299 --- /dev/null +++ b/tests/testdata/recovery-from-boot.p | |||
Binary files differ | |||
diff --git a/tests/testdata/recovery.img b/tests/testdata/recovery.img new file mode 100644 index 00000000..b862e6f0 --- /dev/null +++ b/tests/testdata/recovery.img | |||
Binary files differ | |||