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