blob: 2f648501c27166de12376a213fd7d43cbf072fdb [file] [log] [blame]
Tao Bao97555da2016-12-15 10:15:06 -08001/*
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 <string>
18#include <vector>
19
20#include <android-base/file.h>
Tianjie Xu12b90552017-03-07 14:44:14 -080021#include <android-base/memory.h>
Tao Bao97555da2016-12-15 10:15:06 -080022#include <android-base/test_utils.h>
23#include <applypatch/imgdiff.h>
24#include <applypatch/imgpatch.h>
25#include <gtest/gtest.h>
26#include <ziparchive/zip_writer.h>
27
Tianjie Xu12b90552017-03-07 14:44:14 -080028using android::base::get_unaligned;
Tao Bao97555da2016-12-15 10:15:06 -080029
30static ssize_t MemorySink(const unsigned char* data, ssize_t len, void* token) {
31 std::string* s = static_cast<std::string*>(token);
32 s->append(reinterpret_cast<const char*>(data), len);
33 return len;
34}
35
36// Sanity check for the given imgdiff patch header.
37static void verify_patch_header(const std::string& patch, size_t* num_normal, size_t* num_raw,
38 size_t* num_deflate) {
39 const size_t size = patch.size();
40 const char* data = patch.data();
41
42 ASSERT_GE(size, 12U);
43 ASSERT_EQ("IMGDIFF2", std::string(data, 8));
44
Tianjie Xu12b90552017-03-07 14:44:14 -080045 const int num_chunks = get_unaligned<int32_t>(data + 8);
Tao Bao97555da2016-12-15 10:15:06 -080046 ASSERT_GE(num_chunks, 0);
47
48 size_t normal = 0;
49 size_t raw = 0;
50 size_t deflate = 0;
51
52 size_t pos = 12;
53 for (int i = 0; i < num_chunks; ++i) {
54 ASSERT_LE(pos + 4, size);
Tianjie Xu12b90552017-03-07 14:44:14 -080055 int type = get_unaligned<int32_t>(data + pos);
Tao Bao97555da2016-12-15 10:15:06 -080056 pos += 4;
57 if (type == CHUNK_NORMAL) {
58 pos += 24;
59 ASSERT_LE(pos, size);
60 normal++;
61 } else if (type == CHUNK_RAW) {
62 ASSERT_LE(pos + 4, size);
Tianjie Xu12b90552017-03-07 14:44:14 -080063 ssize_t data_len = get_unaligned<int32_t>(data + pos);
Tao Bao97555da2016-12-15 10:15:06 -080064 ASSERT_GT(data_len, 0);
65 pos += 4 + data_len;
66 ASSERT_LE(pos, size);
67 raw++;
68 } else if (type == CHUNK_DEFLATE) {
69 pos += 60;
70 ASSERT_LE(pos, size);
71 deflate++;
72 } else {
73 FAIL() << "Invalid patch type: " << type;
74 }
75 }
76
77 if (num_normal != nullptr) *num_normal = normal;
78 if (num_raw != nullptr) *num_raw = raw;
79 if (num_deflate != nullptr) *num_deflate = deflate;
80}
81
82TEST(ImgdiffTest, invalid_args) {
83 // Insufficient inputs.
84 ASSERT_EQ(2, imgdiff(1, (const char* []){ "imgdiff" }));
85 ASSERT_EQ(2, imgdiff(2, (const char* []){ "imgdiff", "-z" }));
86 ASSERT_EQ(2, imgdiff(2, (const char* []){ "imgdiff", "-b" }));
87 ASSERT_EQ(2, imgdiff(3, (const char* []){ "imgdiff", "-z", "-b" }));
88
89 // Failed to read bonus file.
90 ASSERT_EQ(1, imgdiff(3, (const char* []){ "imgdiff", "-b", "doesntexist" }));
91
92 // Failed to read input files.
93 ASSERT_EQ(1, imgdiff(4, (const char* []){ "imgdiff", "doesntexist", "doesntexist", "output" }));
94 ASSERT_EQ(
95 1, imgdiff(5, (const char* []){ "imgdiff", "-z", "doesntexist", "doesntexist", "output" }));
96}
97
98TEST(ImgdiffTest, image_mode_smoke) {
99 // Random bytes.
100 const std::string src("abcdefg");
101 TemporaryFile src_file;
102 ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
103
104 const std::string tgt("abcdefgxyz");
105 TemporaryFile tgt_file;
106 ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
107
108 TemporaryFile patch_file;
109 std::vector<const char*> args = {
110 "imgdiff", src_file.path, tgt_file.path, patch_file.path,
111 };
112 ASSERT_EQ(0, imgdiff(args.size(), args.data()));
113
114 // Verify.
115 std::string patch;
116 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
117
118 // Expect one CHUNK_RAW entry.
119 size_t num_normal;
120 size_t num_raw;
121 size_t num_deflate;
122 verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
123 ASSERT_EQ(0U, num_normal);
124 ASSERT_EQ(0U, num_deflate);
125 ASSERT_EQ(1U, num_raw);
126
127 std::string patched;
128 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
129 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
130 MemorySink, &patched));
131 ASSERT_EQ(tgt, patched);
132}
133
134TEST(ImgdiffTest, zip_mode_smoke_store) {
135 // Construct src and tgt zip files.
136 TemporaryFile src_file;
137 FILE* src_file_ptr = fdopen(src_file.fd, "wb");
138 ZipWriter src_writer(src_file_ptr);
139 ASSERT_EQ(0, src_writer.StartEntry("file1.txt", 0)); // Store mode.
140 const std::string src_content("abcdefg");
141 ASSERT_EQ(0, src_writer.WriteBytes(src_content.data(), src_content.size()));
142 ASSERT_EQ(0, src_writer.FinishEntry());
143 ASSERT_EQ(0, src_writer.Finish());
144 ASSERT_EQ(0, fclose(src_file_ptr));
145
146 TemporaryFile tgt_file;
147 FILE* tgt_file_ptr = fdopen(tgt_file.fd, "wb");
148 ZipWriter tgt_writer(tgt_file_ptr);
149 ASSERT_EQ(0, tgt_writer.StartEntry("file1.txt", 0)); // Store mode.
150 const std::string tgt_content("abcdefgxyz");
151 ASSERT_EQ(0, tgt_writer.WriteBytes(tgt_content.data(), tgt_content.size()));
152 ASSERT_EQ(0, tgt_writer.FinishEntry());
153 ASSERT_EQ(0, tgt_writer.Finish());
154 ASSERT_EQ(0, fclose(tgt_file_ptr));
155
156 // Compute patch.
157 TemporaryFile patch_file;
158 std::vector<const char*> args = {
159 "imgdiff", "-z", src_file.path, tgt_file.path, patch_file.path,
160 };
161 ASSERT_EQ(0, imgdiff(args.size(), args.data()));
162
163 // Verify.
164 std::string tgt;
165 ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
166 std::string src;
167 ASSERT_TRUE(android::base::ReadFileToString(src_file.path, &src));
168 std::string patch;
169 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
170
171 // Expect one CHUNK_RAW entry.
172 size_t num_normal;
173 size_t num_raw;
174 size_t num_deflate;
175 verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
176 ASSERT_EQ(0U, num_normal);
177 ASSERT_EQ(0U, num_deflate);
178 ASSERT_EQ(1U, num_raw);
179
180 std::string patched;
181 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
182 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
183 MemorySink, &patched));
184 ASSERT_EQ(tgt, patched);
185}
186
187TEST(ImgdiffTest, zip_mode_smoke_compressed) {
188 // Construct src and tgt zip files.
189 TemporaryFile src_file;
190 FILE* src_file_ptr = fdopen(src_file.fd, "wb");
191 ZipWriter src_writer(src_file_ptr);
192 ASSERT_EQ(0, src_writer.StartEntry("file1.txt", ZipWriter::kCompress));
193 const std::string src_content("abcdefg");
194 ASSERT_EQ(0, src_writer.WriteBytes(src_content.data(), src_content.size()));
195 ASSERT_EQ(0, src_writer.FinishEntry());
196 ASSERT_EQ(0, src_writer.Finish());
197 ASSERT_EQ(0, fclose(src_file_ptr));
198
199 TemporaryFile tgt_file;
200 FILE* tgt_file_ptr = fdopen(tgt_file.fd, "wb");
201 ZipWriter tgt_writer(tgt_file_ptr);
202 ASSERT_EQ(0, tgt_writer.StartEntry("file1.txt", ZipWriter::kCompress));
203 const std::string tgt_content("abcdefgxyz");
204 ASSERT_EQ(0, tgt_writer.WriteBytes(tgt_content.data(), tgt_content.size()));
205 ASSERT_EQ(0, tgt_writer.FinishEntry());
206 ASSERT_EQ(0, tgt_writer.Finish());
207 ASSERT_EQ(0, fclose(tgt_file_ptr));
208
209 // Compute patch.
210 TemporaryFile patch_file;
211 std::vector<const char*> args = {
212 "imgdiff", "-z", src_file.path, tgt_file.path, patch_file.path,
213 };
214 ASSERT_EQ(0, imgdiff(args.size(), args.data()));
215
216 // Verify.
217 std::string tgt;
218 ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
219 std::string src;
220 ASSERT_TRUE(android::base::ReadFileToString(src_file.path, &src));
221 std::string patch;
222 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
223
224 // Expect three entries: CHUNK_RAW (header) + CHUNK_DEFLATE (data) + CHUNK_RAW (footer).
225 size_t num_normal;
226 size_t num_raw;
227 size_t num_deflate;
228 verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
229 ASSERT_EQ(0U, num_normal);
230 ASSERT_EQ(1U, num_deflate);
231 ASSERT_EQ(2U, num_raw);
232
233 std::string patched;
234 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
235 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
236 MemorySink, &patched));
237 ASSERT_EQ(tgt, patched);
238}
239
Tianjie Xu1ea84d62017-02-22 18:23:58 -0800240TEST(ImgdiffTest, zip_mode_smoke_trailer_zeros) {
241 // Construct src and tgt zip files.
242 TemporaryFile src_file;
243 FILE* src_file_ptr = fdopen(src_file.fd, "wb");
244 ZipWriter src_writer(src_file_ptr);
245 ASSERT_EQ(0, src_writer.StartEntry("file1.txt", ZipWriter::kCompress));
246 const std::string src_content("abcdefg");
247 ASSERT_EQ(0, src_writer.WriteBytes(src_content.data(), src_content.size()));
248 ASSERT_EQ(0, src_writer.FinishEntry());
249 ASSERT_EQ(0, src_writer.Finish());
250 ASSERT_EQ(0, fclose(src_file_ptr));
251
252 TemporaryFile tgt_file;
253 FILE* tgt_file_ptr = fdopen(tgt_file.fd, "wb");
254 ZipWriter tgt_writer(tgt_file_ptr);
255 ASSERT_EQ(0, tgt_writer.StartEntry("file1.txt", ZipWriter::kCompress));
256 const std::string tgt_content("abcdefgxyz");
257 ASSERT_EQ(0, tgt_writer.WriteBytes(tgt_content.data(), tgt_content.size()));
258 ASSERT_EQ(0, tgt_writer.FinishEntry());
259 ASSERT_EQ(0, tgt_writer.Finish());
260 // Add trailing zeros to the target zip file.
261 std::vector<uint8_t> zeros(10);
262 ASSERT_EQ(zeros.size(), fwrite(zeros.data(), sizeof(uint8_t), zeros.size(), tgt_file_ptr));
263 ASSERT_EQ(0, fclose(tgt_file_ptr));
264
265 // Compute patch.
266 TemporaryFile patch_file;
267 std::vector<const char*> args = {
268 "imgdiff", "-z", src_file.path, tgt_file.path, patch_file.path,
269 };
270 ASSERT_EQ(0, imgdiff(args.size(), args.data()));
271
272 // Verify.
273 std::string tgt;
274 ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
275 std::string src;
276 ASSERT_TRUE(android::base::ReadFileToString(src_file.path, &src));
277 std::string patch;
278 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
279
280 // Expect three entries: CHUNK_RAW (header) + CHUNK_DEFLATE (data) + CHUNK_RAW (footer).
281 size_t num_normal;
282 size_t num_raw;
283 size_t num_deflate;
284 verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
285 ASSERT_EQ(0U, num_normal);
286 ASSERT_EQ(1U, num_deflate);
287 ASSERT_EQ(2U, num_raw);
288
289 std::string patched;
290 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
291 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
292 MemorySink, &patched));
293 ASSERT_EQ(tgt, patched);
294}
295
Tao Bao97555da2016-12-15 10:15:06 -0800296TEST(ImgdiffTest, image_mode_simple) {
297 // src: "abcdefgh" + gzipped "xyz" (echo -n "xyz" | gzip -f | hd).
298 const std::vector<char> src_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
299 'h', '\x1f', '\x8b', '\x08', '\x00', '\xc4', '\x1e',
300 '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xac',
301 '\x02', '\x00', '\x67', '\xba', '\x8e', '\xeb', '\x03',
302 '\x00', '\x00', '\x00' };
303 const std::string src(src_data.cbegin(), src_data.cend());
304 TemporaryFile src_file;
305 ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
306
307 // tgt: "abcdefgxyz" + gzipped "xxyyzz".
308 const std::vector<char> tgt_data = {
309 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z', '\x1f', '\x8b',
310 '\x08', '\x00', '\x62', '\x1f', '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xa8', '\xac',
311 '\xac', '\xaa', '\x02', '\x00', '\x96', '\x30', '\x06', '\xb7', '\x06', '\x00', '\x00', '\x00'
312 };
313 const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
314 TemporaryFile tgt_file;
315 ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
316
317 TemporaryFile patch_file;
318 std::vector<const char*> args = {
319 "imgdiff", src_file.path, tgt_file.path, patch_file.path,
320 };
321 ASSERT_EQ(0, imgdiff(args.size(), args.data()));
322
323 // Verify.
324 std::string patch;
325 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
326
327 // Expect three entries: CHUNK_RAW (header) + CHUNK_DEFLATE (data) + CHUNK_RAW (footer).
328 size_t num_normal;
329 size_t num_raw;
330 size_t num_deflate;
331 verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
332 ASSERT_EQ(0U, num_normal);
333 ASSERT_EQ(1U, num_deflate);
334 ASSERT_EQ(2U, num_raw);
335
336 std::string patched;
337 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
338 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
339 MemorySink, &patched));
340 ASSERT_EQ(tgt, patched);
341}
342
343TEST(ImgdiffTest, image_mode_different_num_chunks) {
344 // src: "abcdefgh" + gzipped "xyz" (echo -n "xyz" | gzip -f | hd) + gzipped "test".
345 const std::vector<char> src_data = {
346 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\x1f', '\x8b', '\x08',
347 '\x00', '\xc4', '\x1e', '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xac', '\x02',
348 '\x00', '\x67', '\xba', '\x8e', '\xeb', '\x03', '\x00', '\x00', '\x00', '\x1f', '\x8b',
349 '\x08', '\x00', '\xb2', '\x3a', '\x53', '\x58', '\x00', '\x03', '\x2b', '\x49', '\x2d',
350 '\x2e', '\x01', '\x00', '\x0c', '\x7e', '\x7f', '\xd8', '\x04', '\x00', '\x00', '\x00'
351 };
352 const std::string src(src_data.cbegin(), src_data.cend());
353 TemporaryFile src_file;
354 ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
355
356 // tgt: "abcdefgxyz" + gzipped "xxyyzz".
357 const std::vector<char> tgt_data = {
358 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z', '\x1f', '\x8b',
359 '\x08', '\x00', '\x62', '\x1f', '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xa8', '\xac',
360 '\xac', '\xaa', '\x02', '\x00', '\x96', '\x30', '\x06', '\xb7', '\x06', '\x00', '\x00', '\x00'
361 };
362 const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
363 TemporaryFile tgt_file;
364 ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
365
366 TemporaryFile patch_file;
367 std::vector<const char*> args = {
368 "imgdiff", src_file.path, tgt_file.path, patch_file.path,
369 };
370 ASSERT_EQ(1, imgdiff(args.size(), args.data()));
371}
372
373TEST(ImgdiffTest, image_mode_merge_chunks) {
374 // src: "abcdefgh" + gzipped "xyz" (echo -n "xyz" | gzip -f | hd).
375 const std::vector<char> src_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
376 'h', '\x1f', '\x8b', '\x08', '\x00', '\xc4', '\x1e',
377 '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xac',
378 '\x02', '\x00', '\x67', '\xba', '\x8e', '\xeb', '\x03',
379 '\x00', '\x00', '\x00' };
380 const std::string src(src_data.cbegin(), src_data.cend());
381 TemporaryFile src_file;
382 ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
383
384 // tgt: gzipped "xyz" + "abcdefgh".
385 const std::vector<char> tgt_data = {
386 '\x1f', '\x8b', '\x08', '\x00', '\x62', '\x1f', '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8',
387 '\xa8', '\xac', '\xac', '\xaa', '\x02', '\x00', '\x96', '\x30', '\x06', '\xb7', '\x06', '\x00',
388 '\x00', '\x00', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z'
389 };
390 const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
391 TemporaryFile tgt_file;
392 ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
393
394 // Since a gzipped entry will become CHUNK_RAW (header) + CHUNK_DEFLATE (data) +
395 // CHUNK_RAW (footer), they both should contain the same chunk types after merging.
396
397 TemporaryFile patch_file;
398 std::vector<const char*> args = {
399 "imgdiff", src_file.path, tgt_file.path, patch_file.path,
400 };
401 ASSERT_EQ(0, imgdiff(args.size(), args.data()));
402
403 // Verify.
404 std::string patch;
405 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
406
407 // Expect three entries: CHUNK_RAW (header) + CHUNK_DEFLATE (data) + CHUNK_RAW (footer).
408 size_t num_normal;
409 size_t num_raw;
410 size_t num_deflate;
411 verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
412 ASSERT_EQ(0U, num_normal);
413 ASSERT_EQ(1U, num_deflate);
414 ASSERT_EQ(2U, num_raw);
415
416 std::string patched;
417 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
418 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
419 MemorySink, &patched));
420 ASSERT_EQ(tgt, patched);
421}
422
423TEST(ImgdiffTest, image_mode_spurious_magic) {
424 // src: "abcdefgh" + '0x1f8b0b00' + some bytes.
425 const std::vector<char> src_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
426 'h', '\x1f', '\x8b', '\x08', '\x00', '\xc4', '\x1e',
427 '\x53', '\x58', 't', 'e', 's', 't' };
428 const std::string src(src_data.cbegin(), src_data.cend());
429 TemporaryFile src_file;
430 ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
431
432 // tgt: "abcdefgxyz".
433 const std::vector<char> tgt_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z' };
434 const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
435 TemporaryFile tgt_file;
436 ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
437
438 TemporaryFile patch_file;
439 std::vector<const char*> args = {
440 "imgdiff", src_file.path, tgt_file.path, patch_file.path,
441 };
442 ASSERT_EQ(0, imgdiff(args.size(), args.data()));
443
444 // Verify.
445 std::string patch;
446 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
447
448 // Expect one CHUNK_RAW (header) entry.
449 size_t num_normal;
450 size_t num_raw;
451 size_t num_deflate;
452 verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
453 ASSERT_EQ(0U, num_normal);
454 ASSERT_EQ(0U, num_deflate);
455 ASSERT_EQ(1U, num_raw);
456
457 std::string patched;
458 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
459 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
460 MemorySink, &patched));
461 ASSERT_EQ(tgt, patched);
462}
463
Tao Baod37ce8f2016-12-17 17:10:04 -0800464TEST(ImgdiffTest, image_mode_short_input1) {
465 // src: "abcdefgh" + '0x1f8b0b'.
466 const std::vector<char> src_data = { 'a', 'b', 'c', 'd', 'e', 'f',
467 'g', 'h', '\x1f', '\x8b', '\x08' };
468 const std::string src(src_data.cbegin(), src_data.cend());
469 TemporaryFile src_file;
470 ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
471
472 // tgt: "abcdefgxyz".
473 const std::vector<char> tgt_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z' };
474 const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
475 TemporaryFile tgt_file;
476 ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
477
478 TemporaryFile patch_file;
479 std::vector<const char*> args = {
480 "imgdiff", src_file.path, tgt_file.path, patch_file.path,
481 };
482 ASSERT_EQ(0, imgdiff(args.size(), args.data()));
483
484 // Verify.
485 std::string patch;
486 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
487
488 // Expect one CHUNK_RAW (header) entry.
489 size_t num_normal;
490 size_t num_raw;
491 size_t num_deflate;
492 verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
493 ASSERT_EQ(0U, num_normal);
494 ASSERT_EQ(0U, num_deflate);
495 ASSERT_EQ(1U, num_raw);
496
497 std::string patched;
498 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
499 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
500 MemorySink, &patched));
501 ASSERT_EQ(tgt, patched);
502}
503
504TEST(ImgdiffTest, image_mode_short_input2) {
505 // src: "abcdefgh" + '0x1f8b0b00'.
506 const std::vector<char> src_data = { 'a', 'b', 'c', 'd', 'e', 'f',
507 'g', 'h', '\x1f', '\x8b', '\x08', '\x00' };
508 const std::string src(src_data.cbegin(), src_data.cend());
509 TemporaryFile src_file;
510 ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
511
512 // tgt: "abcdefgxyz".
513 const std::vector<char> tgt_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z' };
514 const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
515 TemporaryFile tgt_file;
516 ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
517
518 TemporaryFile patch_file;
519 std::vector<const char*> args = {
520 "imgdiff", src_file.path, tgt_file.path, patch_file.path,
521 };
522 ASSERT_EQ(0, imgdiff(args.size(), args.data()));
523
524 // Verify.
525 std::string patch;
526 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
527
528 // Expect one CHUNK_RAW (header) entry.
529 size_t num_normal;
530 size_t num_raw;
531 size_t num_deflate;
532 verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
533 ASSERT_EQ(0U, num_normal);
534 ASSERT_EQ(0U, num_deflate);
535 ASSERT_EQ(1U, num_raw);
536
537 std::string patched;
538 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
539 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
540 MemorySink, &patched));
541 ASSERT_EQ(tgt, patched);
542}
543
Tao Bao97555da2016-12-15 10:15:06 -0800544TEST(ImgdiffTest, image_mode_single_entry_long) {
545 // src: "abcdefgh" + '0x1f8b0b00' + some bytes.
546 const std::vector<char> src_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
547 'h', '\x1f', '\x8b', '\x08', '\x00', '\xc4', '\x1e',
548 '\x53', '\x58', 't', 'e', 's', 't' };
549 const std::string src(src_data.cbegin(), src_data.cend());
550 TemporaryFile src_file;
551 ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
552
553 // tgt: "abcdefgxyz" + 200 bytes.
554 std::vector<char> tgt_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z' };
555 tgt_data.resize(tgt_data.size() + 200);
556
557 const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
558 TemporaryFile tgt_file;
559 ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
560
561 TemporaryFile patch_file;
562 std::vector<const char*> args = {
563 "imgdiff", src_file.path, tgt_file.path, patch_file.path,
564 };
565 ASSERT_EQ(0, imgdiff(args.size(), args.data()));
566
567 // Verify.
568 std::string patch;
569 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
570
571 // Expect one CHUNK_NORMAL entry, since it's exceeding the 160-byte limit for RAW.
572 size_t num_normal;
573 size_t num_raw;
574 size_t num_deflate;
575 verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
576 ASSERT_EQ(1U, num_normal);
577 ASSERT_EQ(0U, num_deflate);
578 ASSERT_EQ(0U, num_raw);
579
580 std::string patched;
581 ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
582 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
583 MemorySink, &patched));
584 ASSERT_EQ(tgt, patched);
585}