xref: /aosp_15_r20/bootable/deprecated-ota/tests/unit/host/imgdiff_test.cpp (revision acea8879c968027b49a027136800575dd9783ddf)
1*acea8879SAndroid Build Coastguard Worker /*
2*acea8879SAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*acea8879SAndroid Build Coastguard Worker  *
4*acea8879SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*acea8879SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*acea8879SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*acea8879SAndroid Build Coastguard Worker  *
8*acea8879SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*acea8879SAndroid Build Coastguard Worker  *
10*acea8879SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*acea8879SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*acea8879SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*acea8879SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*acea8879SAndroid Build Coastguard Worker  * limitations under the License.
15*acea8879SAndroid Build Coastguard Worker  */
16*acea8879SAndroid Build Coastguard Worker 
17*acea8879SAndroid Build Coastguard Worker #include <stdio.h>
18*acea8879SAndroid Build Coastguard Worker 
19*acea8879SAndroid Build Coastguard Worker #include <algorithm>
20*acea8879SAndroid Build Coastguard Worker #include <string>
21*acea8879SAndroid Build Coastguard Worker #include <tuple>
22*acea8879SAndroid Build Coastguard Worker #include <vector>
23*acea8879SAndroid Build Coastguard Worker 
24*acea8879SAndroid Build Coastguard Worker #include <android-base/file.h>
25*acea8879SAndroid Build Coastguard Worker #include <android-base/memory.h>
26*acea8879SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
27*acea8879SAndroid Build Coastguard Worker #include <android-base/strings.h>
28*acea8879SAndroid Build Coastguard Worker #include <applypatch/imgdiff.h>
29*acea8879SAndroid Build Coastguard Worker #include <applypatch/imgdiff_image.h>
30*acea8879SAndroid Build Coastguard Worker #include <applypatch/imgpatch.h>
31*acea8879SAndroid Build Coastguard Worker #include <gtest/gtest.h>
32*acea8879SAndroid Build Coastguard Worker #include <ziparchive/zip_writer.h>
33*acea8879SAndroid Build Coastguard Worker 
34*acea8879SAndroid Build Coastguard Worker #include "common/test_constants.h"
35*acea8879SAndroid Build Coastguard Worker 
36*acea8879SAndroid Build Coastguard Worker using android::base::get_unaligned;
37*acea8879SAndroid Build Coastguard Worker 
verify_patch_header(const std::string & patch,size_t * num_normal,size_t * num_raw,size_t * num_deflate)38*acea8879SAndroid Build Coastguard Worker static void verify_patch_header(const std::string& patch, size_t* num_normal, size_t* num_raw,
39*acea8879SAndroid Build Coastguard Worker                                 size_t* num_deflate) {
40*acea8879SAndroid Build Coastguard Worker   const size_t size = patch.size();
41*acea8879SAndroid Build Coastguard Worker   const char* data = patch.data();
42*acea8879SAndroid Build Coastguard Worker 
43*acea8879SAndroid Build Coastguard Worker   ASSERT_GE(size, 12U);
44*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ("IMGDIFF2", std::string(data, 8));
45*acea8879SAndroid Build Coastguard Worker 
46*acea8879SAndroid Build Coastguard Worker   const int num_chunks = get_unaligned<int32_t>(data + 8);
47*acea8879SAndroid Build Coastguard Worker   ASSERT_GE(num_chunks, 0);
48*acea8879SAndroid Build Coastguard Worker 
49*acea8879SAndroid Build Coastguard Worker   size_t normal = 0;
50*acea8879SAndroid Build Coastguard Worker   size_t raw = 0;
51*acea8879SAndroid Build Coastguard Worker   size_t deflate = 0;
52*acea8879SAndroid Build Coastguard Worker 
53*acea8879SAndroid Build Coastguard Worker   size_t pos = 12;
54*acea8879SAndroid Build Coastguard Worker   for (int i = 0; i < num_chunks; ++i) {
55*acea8879SAndroid Build Coastguard Worker     ASSERT_LE(pos + 4, size);
56*acea8879SAndroid Build Coastguard Worker     int type = get_unaligned<int32_t>(data + pos);
57*acea8879SAndroid Build Coastguard Worker     pos += 4;
58*acea8879SAndroid Build Coastguard Worker     if (type == CHUNK_NORMAL) {
59*acea8879SAndroid Build Coastguard Worker       pos += 24;
60*acea8879SAndroid Build Coastguard Worker       ASSERT_LE(pos, size);
61*acea8879SAndroid Build Coastguard Worker       normal++;
62*acea8879SAndroid Build Coastguard Worker     } else if (type == CHUNK_RAW) {
63*acea8879SAndroid Build Coastguard Worker       ASSERT_LE(pos + 4, size);
64*acea8879SAndroid Build Coastguard Worker       ssize_t data_len = get_unaligned<int32_t>(data + pos);
65*acea8879SAndroid Build Coastguard Worker       ASSERT_GT(data_len, 0);
66*acea8879SAndroid Build Coastguard Worker       pos += 4 + data_len;
67*acea8879SAndroid Build Coastguard Worker       ASSERT_LE(pos, size);
68*acea8879SAndroid Build Coastguard Worker       raw++;
69*acea8879SAndroid Build Coastguard Worker     } else if (type == CHUNK_DEFLATE) {
70*acea8879SAndroid Build Coastguard Worker       pos += 60;
71*acea8879SAndroid Build Coastguard Worker       ASSERT_LE(pos, size);
72*acea8879SAndroid Build Coastguard Worker       deflate++;
73*acea8879SAndroid Build Coastguard Worker     } else {
74*acea8879SAndroid Build Coastguard Worker       FAIL() << "Invalid patch type: " << type;
75*acea8879SAndroid Build Coastguard Worker     }
76*acea8879SAndroid Build Coastguard Worker   }
77*acea8879SAndroid Build Coastguard Worker 
78*acea8879SAndroid Build Coastguard Worker   if (num_normal != nullptr) *num_normal = normal;
79*acea8879SAndroid Build Coastguard Worker   if (num_raw != nullptr) *num_raw = raw;
80*acea8879SAndroid Build Coastguard Worker   if (num_deflate != nullptr) *num_deflate = deflate;
81*acea8879SAndroid Build Coastguard Worker }
82*acea8879SAndroid Build Coastguard Worker 
GenerateTarget(const std::string & src,const std::string & patch,std::string * patched)83*acea8879SAndroid Build Coastguard Worker static void GenerateTarget(const std::string& src, const std::string& patch, std::string* patched) {
84*acea8879SAndroid Build Coastguard Worker   patched->clear();
85*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
86*acea8879SAndroid Build Coastguard Worker                                reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
87*acea8879SAndroid Build Coastguard Worker                                [&](const unsigned char* data, size_t len) {
88*acea8879SAndroid Build Coastguard Worker                                  patched->append(reinterpret_cast<const char*>(data), len);
89*acea8879SAndroid Build Coastguard Worker                                  return len;
90*acea8879SAndroid Build Coastguard Worker                                }));
91*acea8879SAndroid Build Coastguard Worker }
92*acea8879SAndroid Build Coastguard Worker 
verify_patched_image(const std::string & src,const std::string & patch,const std::string & tgt)93*acea8879SAndroid Build Coastguard Worker static void verify_patched_image(const std::string& src, const std::string& patch,
94*acea8879SAndroid Build Coastguard Worker                                  const std::string& tgt) {
95*acea8879SAndroid Build Coastguard Worker   std::string patched;
96*acea8879SAndroid Build Coastguard Worker   GenerateTarget(src, patch, &patched);
97*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(tgt, patched);
98*acea8879SAndroid Build Coastguard Worker }
99*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,invalid_args)100*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, invalid_args) {
101*acea8879SAndroid Build Coastguard Worker   // Insufficient inputs.
102*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(2, imgdiff(1, (const char* []){ "imgdiff" }));
103*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(2, imgdiff(2, (const char* []){ "imgdiff", "-z" }));
104*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(2, imgdiff(2, (const char* []){ "imgdiff", "-b" }));
105*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(2, imgdiff(3, (const char* []){ "imgdiff", "-z", "-b" }));
106*acea8879SAndroid Build Coastguard Worker 
107*acea8879SAndroid Build Coastguard Worker   // Failed to read bonus file.
108*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1, imgdiff(3, (const char* []){ "imgdiff", "-b", "doesntexist" }));
109*acea8879SAndroid Build Coastguard Worker 
110*acea8879SAndroid Build Coastguard Worker   // Failed to read input files.
111*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1, imgdiff(4, (const char* []){ "imgdiff", "doesntexist", "doesntexist", "output" }));
112*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(
113*acea8879SAndroid Build Coastguard Worker       1, imgdiff(5, (const char* []){ "imgdiff", "-z", "doesntexist", "doesntexist", "output" }));
114*acea8879SAndroid Build Coastguard Worker }
115*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,image_mode_smoke)116*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, image_mode_smoke) {
117*acea8879SAndroid Build Coastguard Worker   // Random bytes.
118*acea8879SAndroid Build Coastguard Worker   const std::string src("abcdefg");
119*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
120*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
121*acea8879SAndroid Build Coastguard Worker 
122*acea8879SAndroid Build Coastguard Worker   const std::string tgt("abcdefgxyz");
123*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
124*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
125*acea8879SAndroid Build Coastguard Worker 
126*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
127*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
128*acea8879SAndroid Build Coastguard Worker     "imgdiff", src_file.path, tgt_file.path, patch_file.path,
129*acea8879SAndroid Build Coastguard Worker   };
130*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
131*acea8879SAndroid Build Coastguard Worker 
132*acea8879SAndroid Build Coastguard Worker   // Verify.
133*acea8879SAndroid Build Coastguard Worker   std::string patch;
134*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
135*acea8879SAndroid Build Coastguard Worker 
136*acea8879SAndroid Build Coastguard Worker   // Expect one CHUNK_RAW entry.
137*acea8879SAndroid Build Coastguard Worker   size_t num_normal;
138*acea8879SAndroid Build Coastguard Worker   size_t num_raw;
139*acea8879SAndroid Build Coastguard Worker   size_t num_deflate;
140*acea8879SAndroid Build Coastguard Worker   verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
141*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_normal);
142*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_deflate);
143*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1U, num_raw);
144*acea8879SAndroid Build Coastguard Worker 
145*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
146*acea8879SAndroid Build Coastguard Worker }
147*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,zip_mode_smoke_store)148*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, zip_mode_smoke_store) {
149*acea8879SAndroid Build Coastguard Worker   // Construct src and tgt zip files.
150*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
151*acea8879SAndroid Build Coastguard Worker   FILE* src_file_ptr = fdopen(src_file.release(), "wb");
152*acea8879SAndroid Build Coastguard Worker   ZipWriter src_writer(src_file_ptr);
153*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.StartEntry("file1.txt", 0));  // Store mode.
154*acea8879SAndroid Build Coastguard Worker   const std::string src_content("abcdefg");
155*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.WriteBytes(src_content.data(), src_content.size()));
156*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.FinishEntry());
157*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.Finish());
158*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(src_file_ptr));
159*acea8879SAndroid Build Coastguard Worker 
160*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
161*acea8879SAndroid Build Coastguard Worker   FILE* tgt_file_ptr = fdopen(tgt_file.release(), "wb");
162*acea8879SAndroid Build Coastguard Worker   ZipWriter tgt_writer(tgt_file_ptr);
163*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.StartEntry("file1.txt", 0));  // Store mode.
164*acea8879SAndroid Build Coastguard Worker   const std::string tgt_content("abcdefgxyz");
165*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.WriteBytes(tgt_content.data(), tgt_content.size()));
166*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.FinishEntry());
167*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.Finish());
168*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(tgt_file_ptr));
169*acea8879SAndroid Build Coastguard Worker 
170*acea8879SAndroid Build Coastguard Worker   // Compute patch.
171*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
172*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
173*acea8879SAndroid Build Coastguard Worker     "imgdiff", "-z", src_file.path, tgt_file.path, patch_file.path,
174*acea8879SAndroid Build Coastguard Worker   };
175*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
176*acea8879SAndroid Build Coastguard Worker 
177*acea8879SAndroid Build Coastguard Worker   // Verify.
178*acea8879SAndroid Build Coastguard Worker   std::string tgt;
179*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
180*acea8879SAndroid Build Coastguard Worker   std::string src;
181*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(src_file.path, &src));
182*acea8879SAndroid Build Coastguard Worker   std::string patch;
183*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
184*acea8879SAndroid Build Coastguard Worker 
185*acea8879SAndroid Build Coastguard Worker   // Expect one CHUNK_RAW entry.
186*acea8879SAndroid Build Coastguard Worker   size_t num_normal;
187*acea8879SAndroid Build Coastguard Worker   size_t num_raw;
188*acea8879SAndroid Build Coastguard Worker   size_t num_deflate;
189*acea8879SAndroid Build Coastguard Worker   verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
190*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_normal);
191*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_deflate);
192*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1U, num_raw);
193*acea8879SAndroid Build Coastguard Worker 
194*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
195*acea8879SAndroid Build Coastguard Worker }
196*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,zip_mode_smoke_compressed)197*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, zip_mode_smoke_compressed) {
198*acea8879SAndroid Build Coastguard Worker   // Generate 1 block of random data.
199*acea8879SAndroid Build Coastguard Worker   std::string random_data;
200*acea8879SAndroid Build Coastguard Worker   random_data.reserve(4096);
201*acea8879SAndroid Build Coastguard Worker   generate_n(back_inserter(random_data), 4096, []() { return rand() % 256; });
202*acea8879SAndroid Build Coastguard Worker 
203*acea8879SAndroid Build Coastguard Worker   // Construct src and tgt zip files.
204*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
205*acea8879SAndroid Build Coastguard Worker   FILE* src_file_ptr = fdopen(src_file.release(), "wb");
206*acea8879SAndroid Build Coastguard Worker   ZipWriter src_writer(src_file_ptr);
207*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.StartEntry("file1.txt", ZipWriter::kCompress));
208*acea8879SAndroid Build Coastguard Worker   const std::string src_content = random_data;
209*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.WriteBytes(src_content.data(), src_content.size()));
210*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.FinishEntry());
211*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.Finish());
212*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(src_file_ptr));
213*acea8879SAndroid Build Coastguard Worker 
214*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
215*acea8879SAndroid Build Coastguard Worker   FILE* tgt_file_ptr = fdopen(tgt_file.release(), "wb");
216*acea8879SAndroid Build Coastguard Worker   ZipWriter tgt_writer(tgt_file_ptr);
217*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.StartEntry("file1.txt", ZipWriter::kCompress));
218*acea8879SAndroid Build Coastguard Worker   const std::string tgt_content = random_data + "extra contents";
219*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.WriteBytes(tgt_content.data(), tgt_content.size()));
220*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.FinishEntry());
221*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.Finish());
222*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(tgt_file_ptr));
223*acea8879SAndroid Build Coastguard Worker 
224*acea8879SAndroid Build Coastguard Worker   // Compute patch.
225*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
226*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
227*acea8879SAndroid Build Coastguard Worker     "imgdiff", "-z", src_file.path, tgt_file.path, patch_file.path,
228*acea8879SAndroid Build Coastguard Worker   };
229*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
230*acea8879SAndroid Build Coastguard Worker 
231*acea8879SAndroid Build Coastguard Worker   // Verify.
232*acea8879SAndroid Build Coastguard Worker   std::string tgt;
233*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
234*acea8879SAndroid Build Coastguard Worker   std::string src;
235*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(src_file.path, &src));
236*acea8879SAndroid Build Coastguard Worker   std::string patch;
237*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
238*acea8879SAndroid Build Coastguard Worker 
239*acea8879SAndroid Build Coastguard Worker   // Expect three entries: CHUNK_RAW (header) + CHUNK_DEFLATE (data) + CHUNK_RAW (footer).
240*acea8879SAndroid Build Coastguard Worker   size_t num_normal;
241*acea8879SAndroid Build Coastguard Worker   size_t num_raw;
242*acea8879SAndroid Build Coastguard Worker   size_t num_deflate;
243*acea8879SAndroid Build Coastguard Worker   verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
244*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_normal);
245*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1U, num_deflate);
246*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(2U, num_raw);
247*acea8879SAndroid Build Coastguard Worker 
248*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
249*acea8879SAndroid Build Coastguard Worker }
250*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,zip_mode_empty_target)251*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, zip_mode_empty_target) {
252*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
253*acea8879SAndroid Build Coastguard Worker   FILE* src_file_ptr = fdopen(src_file.release(), "wb");
254*acea8879SAndroid Build Coastguard Worker   ZipWriter src_writer(src_file_ptr);
255*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.StartEntry("file1.txt", ZipWriter::kCompress));
256*acea8879SAndroid Build Coastguard Worker   const std::string src_content = "abcdefg";
257*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.WriteBytes(src_content.data(), src_content.size()));
258*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.FinishEntry());
259*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.Finish());
260*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(src_file_ptr));
261*acea8879SAndroid Build Coastguard Worker 
262*acea8879SAndroid Build Coastguard Worker   // Construct a empty entry in the target zip.
263*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
264*acea8879SAndroid Build Coastguard Worker   FILE* tgt_file_ptr = fdopen(tgt_file.release(), "wb");
265*acea8879SAndroid Build Coastguard Worker   ZipWriter tgt_writer(tgt_file_ptr);
266*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.StartEntry("file1.txt", ZipWriter::kCompress));
267*acea8879SAndroid Build Coastguard Worker   const std::string tgt_content;
268*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.WriteBytes(tgt_content.data(), tgt_content.size()));
269*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.FinishEntry());
270*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.Finish());
271*acea8879SAndroid Build Coastguard Worker 
272*acea8879SAndroid Build Coastguard Worker   // Compute patch.
273*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
274*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
275*acea8879SAndroid Build Coastguard Worker     "imgdiff", "-z", src_file.path, tgt_file.path, patch_file.path,
276*acea8879SAndroid Build Coastguard Worker   };
277*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
278*acea8879SAndroid Build Coastguard Worker 
279*acea8879SAndroid Build Coastguard Worker   // Verify.
280*acea8879SAndroid Build Coastguard Worker   std::string tgt;
281*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
282*acea8879SAndroid Build Coastguard Worker   std::string src;
283*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(src_file.path, &src));
284*acea8879SAndroid Build Coastguard Worker   std::string patch;
285*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
286*acea8879SAndroid Build Coastguard Worker 
287*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
288*acea8879SAndroid Build Coastguard Worker }
289*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,zip_mode_smoke_trailer_zeros)290*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, zip_mode_smoke_trailer_zeros) {
291*acea8879SAndroid Build Coastguard Worker   // Generate 1 block of random data.
292*acea8879SAndroid Build Coastguard Worker   std::string random_data;
293*acea8879SAndroid Build Coastguard Worker   random_data.reserve(4096);
294*acea8879SAndroid Build Coastguard Worker   generate_n(back_inserter(random_data), 4096, []() { return rand() % 256; });
295*acea8879SAndroid Build Coastguard Worker 
296*acea8879SAndroid Build Coastguard Worker   // Construct src and tgt zip files.
297*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
298*acea8879SAndroid Build Coastguard Worker   FILE* src_file_ptr = fdopen(src_file.release(), "wb");
299*acea8879SAndroid Build Coastguard Worker   ZipWriter src_writer(src_file_ptr);
300*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.StartEntry("file1.txt", ZipWriter::kCompress));
301*acea8879SAndroid Build Coastguard Worker   const std::string src_content = random_data;
302*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.WriteBytes(src_content.data(), src_content.size()));
303*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.FinishEntry());
304*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.Finish());
305*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(src_file_ptr));
306*acea8879SAndroid Build Coastguard Worker 
307*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
308*acea8879SAndroid Build Coastguard Worker   FILE* tgt_file_ptr = fdopen(tgt_file.release(), "wb");
309*acea8879SAndroid Build Coastguard Worker   ZipWriter tgt_writer(tgt_file_ptr);
310*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.StartEntry("file1.txt", ZipWriter::kCompress));
311*acea8879SAndroid Build Coastguard Worker   const std::string tgt_content = random_data + "abcdefg";
312*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.WriteBytes(tgt_content.data(), tgt_content.size()));
313*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.FinishEntry());
314*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.Finish());
315*acea8879SAndroid Build Coastguard Worker   // Add trailing zeros to the target zip file.
316*acea8879SAndroid Build Coastguard Worker   std::vector<uint8_t> zeros(10);
317*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(zeros.size(), fwrite(zeros.data(), sizeof(uint8_t), zeros.size(), tgt_file_ptr));
318*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(tgt_file_ptr));
319*acea8879SAndroid Build Coastguard Worker 
320*acea8879SAndroid Build Coastguard Worker   // Compute patch.
321*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
322*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
323*acea8879SAndroid Build Coastguard Worker     "imgdiff", "-z", src_file.path, tgt_file.path, patch_file.path,
324*acea8879SAndroid Build Coastguard Worker   };
325*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
326*acea8879SAndroid Build Coastguard Worker 
327*acea8879SAndroid Build Coastguard Worker   // Verify.
328*acea8879SAndroid Build Coastguard Worker   std::string tgt;
329*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
330*acea8879SAndroid Build Coastguard Worker   std::string src;
331*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(src_file.path, &src));
332*acea8879SAndroid Build Coastguard Worker   std::string patch;
333*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
334*acea8879SAndroid Build Coastguard Worker 
335*acea8879SAndroid Build Coastguard Worker   // Expect three entries: CHUNK_RAW (header) + CHUNK_DEFLATE (data) + CHUNK_RAW (footer).
336*acea8879SAndroid Build Coastguard Worker   size_t num_normal;
337*acea8879SAndroid Build Coastguard Worker   size_t num_raw;
338*acea8879SAndroid Build Coastguard Worker   size_t num_deflate;
339*acea8879SAndroid Build Coastguard Worker   verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
340*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_normal);
341*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1U, num_deflate);
342*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(2U, num_raw);
343*acea8879SAndroid Build Coastguard Worker 
344*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
345*acea8879SAndroid Build Coastguard Worker }
346*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,image_mode_simple)347*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, image_mode_simple) {
348*acea8879SAndroid Build Coastguard Worker   std::string gzipped_source_path = from_testdata_base("gzipped_source");
349*acea8879SAndroid Build Coastguard Worker   std::string gzipped_source;
350*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(gzipped_source_path, &gzipped_source));
351*acea8879SAndroid Build Coastguard Worker 
352*acea8879SAndroid Build Coastguard Worker   const std::string src = "abcdefg" + gzipped_source;
353*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
354*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
355*acea8879SAndroid Build Coastguard Worker 
356*acea8879SAndroid Build Coastguard Worker   std::string gzipped_target_path = from_testdata_base("gzipped_target");
357*acea8879SAndroid Build Coastguard Worker   std::string gzipped_target;
358*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(gzipped_target_path, &gzipped_target));
359*acea8879SAndroid Build Coastguard Worker   const std::string tgt = "abcdefgxyz" + gzipped_target;
360*acea8879SAndroid Build Coastguard Worker 
361*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
362*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
363*acea8879SAndroid Build Coastguard Worker 
364*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
365*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
366*acea8879SAndroid Build Coastguard Worker     "imgdiff", src_file.path, tgt_file.path, patch_file.path,
367*acea8879SAndroid Build Coastguard Worker   };
368*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
369*acea8879SAndroid Build Coastguard Worker 
370*acea8879SAndroid Build Coastguard Worker   // Verify.
371*acea8879SAndroid Build Coastguard Worker   std::string patch;
372*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
373*acea8879SAndroid Build Coastguard Worker 
374*acea8879SAndroid Build Coastguard Worker   // Expect three entries: CHUNK_RAW (header) + CHUNK_DEFLATE (data) + CHUNK_RAW (footer).
375*acea8879SAndroid Build Coastguard Worker   size_t num_normal;
376*acea8879SAndroid Build Coastguard Worker   size_t num_raw;
377*acea8879SAndroid Build Coastguard Worker   size_t num_deflate;
378*acea8879SAndroid Build Coastguard Worker   verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
379*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_normal);
380*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1U, num_deflate);
381*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(2U, num_raw);
382*acea8879SAndroid Build Coastguard Worker 
383*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
384*acea8879SAndroid Build Coastguard Worker }
385*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,image_mode_bad_gzip)386*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, image_mode_bad_gzip) {
387*acea8879SAndroid Build Coastguard Worker   // Modify the uncompressed length in the gzip footer.
388*acea8879SAndroid Build Coastguard Worker   const std::vector<char> src_data = { 'a',    'b',    'c',    'd',    'e',    'f',    'g',
389*acea8879SAndroid Build Coastguard Worker                                        'h',    '\x1f', '\x8b', '\x08', '\x00', '\xc4', '\x1e',
390*acea8879SAndroid Build Coastguard Worker                                        '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xac',
391*acea8879SAndroid Build Coastguard Worker                                        '\x02', '\x00', '\x67', '\xba', '\x8e', '\xeb', '\x03',
392*acea8879SAndroid Build Coastguard Worker                                        '\xff', '\xff', '\xff' };
393*acea8879SAndroid Build Coastguard Worker   const std::string src(src_data.cbegin(), src_data.cend());
394*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
395*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
396*acea8879SAndroid Build Coastguard Worker 
397*acea8879SAndroid Build Coastguard Worker   // Modify the uncompressed length in the gzip footer.
398*acea8879SAndroid Build Coastguard Worker   const std::vector<char> tgt_data = {
399*acea8879SAndroid Build Coastguard Worker     'a',    'b',    'c',    'd',    'e',    'f',    'g',    'x',    'y',    'z',    '\x1f', '\x8b',
400*acea8879SAndroid Build Coastguard Worker     '\x08', '\x00', '\x62', '\x1f', '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xa8', '\xac',
401*acea8879SAndroid Build Coastguard Worker     '\xac', '\xaa', '\x02', '\x00', '\x96', '\x30', '\x06', '\xb7', '\x06', '\xff', '\xff', '\xff'
402*acea8879SAndroid Build Coastguard Worker   };
403*acea8879SAndroid Build Coastguard Worker   const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
404*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
405*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
406*acea8879SAndroid Build Coastguard Worker 
407*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
408*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
409*acea8879SAndroid Build Coastguard Worker     "imgdiff", src_file.path, tgt_file.path, patch_file.path,
410*acea8879SAndroid Build Coastguard Worker   };
411*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
412*acea8879SAndroid Build Coastguard Worker 
413*acea8879SAndroid Build Coastguard Worker   // Verify.
414*acea8879SAndroid Build Coastguard Worker   std::string patch;
415*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
416*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
417*acea8879SAndroid Build Coastguard Worker }
418*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,image_mode_different_num_chunks)419*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, image_mode_different_num_chunks) {
420*acea8879SAndroid Build Coastguard Worker   // src: "abcdefgh" + gzipped "xyz" (echo -n "xyz" | gzip -f | hd) + gzipped "test".
421*acea8879SAndroid Build Coastguard Worker   const std::vector<char> src_data = {
422*acea8879SAndroid Build Coastguard Worker     'a',    'b',    'c',    'd',    'e',    'f',    'g',    'h',    '\x1f', '\x8b', '\x08',
423*acea8879SAndroid Build Coastguard Worker     '\x00', '\xc4', '\x1e', '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xac', '\x02',
424*acea8879SAndroid Build Coastguard Worker     '\x00', '\x67', '\xba', '\x8e', '\xeb', '\x03', '\x00', '\x00', '\x00', '\x1f', '\x8b',
425*acea8879SAndroid Build Coastguard Worker     '\x08', '\x00', '\xb2', '\x3a', '\x53', '\x58', '\x00', '\x03', '\x2b', '\x49', '\x2d',
426*acea8879SAndroid Build Coastguard Worker     '\x2e', '\x01', '\x00', '\x0c', '\x7e', '\x7f', '\xd8', '\x04', '\x00', '\x00', '\x00'
427*acea8879SAndroid Build Coastguard Worker   };
428*acea8879SAndroid Build Coastguard Worker   const std::string src(src_data.cbegin(), src_data.cend());
429*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
430*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
431*acea8879SAndroid Build Coastguard Worker 
432*acea8879SAndroid Build Coastguard Worker   // tgt: "abcdefgxyz" + gzipped "xxyyzz".
433*acea8879SAndroid Build Coastguard Worker   const std::vector<char> tgt_data = {
434*acea8879SAndroid Build Coastguard Worker     'a',    'b',    'c',    'd',    'e',    'f',    'g',    'x',    'y',    'z',    '\x1f', '\x8b',
435*acea8879SAndroid Build Coastguard Worker     '\x08', '\x00', '\x62', '\x1f', '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xa8', '\xac',
436*acea8879SAndroid Build Coastguard Worker     '\xac', '\xaa', '\x02', '\x00', '\x96', '\x30', '\x06', '\xb7', '\x06', '\x00', '\x00', '\x00'
437*acea8879SAndroid Build Coastguard Worker   };
438*acea8879SAndroid Build Coastguard Worker   const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
439*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
440*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
441*acea8879SAndroid Build Coastguard Worker 
442*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
443*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
444*acea8879SAndroid Build Coastguard Worker     "imgdiff", src_file.path, tgt_file.path, patch_file.path,
445*acea8879SAndroid Build Coastguard Worker   };
446*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1, imgdiff(args.size(), args.data()));
447*acea8879SAndroid Build Coastguard Worker }
448*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,image_mode_merge_chunks)449*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, image_mode_merge_chunks) {
450*acea8879SAndroid Build Coastguard Worker   // src: "abcdefg" + gzipped_source.
451*acea8879SAndroid Build Coastguard Worker   std::string gzipped_source_path = from_testdata_base("gzipped_source");
452*acea8879SAndroid Build Coastguard Worker   std::string gzipped_source;
453*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(gzipped_source_path, &gzipped_source));
454*acea8879SAndroid Build Coastguard Worker 
455*acea8879SAndroid Build Coastguard Worker   const std::string src = "abcdefg" + gzipped_source;
456*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
457*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
458*acea8879SAndroid Build Coastguard Worker 
459*acea8879SAndroid Build Coastguard Worker   // tgt: gzipped_target + "abcdefgxyz".
460*acea8879SAndroid Build Coastguard Worker   std::string gzipped_target_path = from_testdata_base("gzipped_target");
461*acea8879SAndroid Build Coastguard Worker   std::string gzipped_target;
462*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(gzipped_target_path, &gzipped_target));
463*acea8879SAndroid Build Coastguard Worker 
464*acea8879SAndroid Build Coastguard Worker   const std::string tgt = gzipped_target + "abcdefgxyz";
465*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
466*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
467*acea8879SAndroid Build Coastguard Worker 
468*acea8879SAndroid Build Coastguard Worker   // Since a gzipped entry will become CHUNK_RAW (header) + CHUNK_DEFLATE (data) +
469*acea8879SAndroid Build Coastguard Worker   // CHUNK_RAW (footer), they both should contain the same chunk types after merging.
470*acea8879SAndroid Build Coastguard Worker 
471*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
472*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
473*acea8879SAndroid Build Coastguard Worker     "imgdiff", src_file.path, tgt_file.path, patch_file.path,
474*acea8879SAndroid Build Coastguard Worker   };
475*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
476*acea8879SAndroid Build Coastguard Worker 
477*acea8879SAndroid Build Coastguard Worker   // Verify.
478*acea8879SAndroid Build Coastguard Worker   std::string patch;
479*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
480*acea8879SAndroid Build Coastguard Worker 
481*acea8879SAndroid Build Coastguard Worker   // Expect three entries: CHUNK_RAW (header) + CHUNK_DEFLATE (data) + CHUNK_RAW (footer).
482*acea8879SAndroid Build Coastguard Worker   size_t num_normal;
483*acea8879SAndroid Build Coastguard Worker   size_t num_raw;
484*acea8879SAndroid Build Coastguard Worker   size_t num_deflate;
485*acea8879SAndroid Build Coastguard Worker   verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
486*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_normal);
487*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1U, num_deflate);
488*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(2U, num_raw);
489*acea8879SAndroid Build Coastguard Worker 
490*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
491*acea8879SAndroid Build Coastguard Worker }
492*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,image_mode_spurious_magic)493*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, image_mode_spurious_magic) {
494*acea8879SAndroid Build Coastguard Worker   // src: "abcdefgh" + '0x1f8b0b00' + some bytes.
495*acea8879SAndroid Build Coastguard Worker   const std::vector<char> src_data = { 'a',    'b',    'c',    'd',    'e',    'f',    'g',
496*acea8879SAndroid Build Coastguard Worker                                        'h',    '\x1f', '\x8b', '\x08', '\x00', '\xc4', '\x1e',
497*acea8879SAndroid Build Coastguard Worker                                        '\x53', '\x58', 't',    'e',    's',    't' };
498*acea8879SAndroid Build Coastguard Worker   const std::string src(src_data.cbegin(), src_data.cend());
499*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
500*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
501*acea8879SAndroid Build Coastguard Worker 
502*acea8879SAndroid Build Coastguard Worker   // tgt: "abcdefgxyz".
503*acea8879SAndroid Build Coastguard Worker   const std::vector<char> tgt_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z' };
504*acea8879SAndroid Build Coastguard Worker   const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
505*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
506*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
507*acea8879SAndroid Build Coastguard Worker 
508*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
509*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
510*acea8879SAndroid Build Coastguard Worker     "imgdiff", src_file.path, tgt_file.path, patch_file.path,
511*acea8879SAndroid Build Coastguard Worker   };
512*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
513*acea8879SAndroid Build Coastguard Worker 
514*acea8879SAndroid Build Coastguard Worker   // Verify.
515*acea8879SAndroid Build Coastguard Worker   std::string patch;
516*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
517*acea8879SAndroid Build Coastguard Worker 
518*acea8879SAndroid Build Coastguard Worker   // Expect one CHUNK_RAW (header) entry.
519*acea8879SAndroid Build Coastguard Worker   size_t num_normal;
520*acea8879SAndroid Build Coastguard Worker   size_t num_raw;
521*acea8879SAndroid Build Coastguard Worker   size_t num_deflate;
522*acea8879SAndroid Build Coastguard Worker   verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
523*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_normal);
524*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_deflate);
525*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1U, num_raw);
526*acea8879SAndroid Build Coastguard Worker 
527*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
528*acea8879SAndroid Build Coastguard Worker }
529*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,image_mode_short_input1)530*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, image_mode_short_input1) {
531*acea8879SAndroid Build Coastguard Worker   // src: "abcdefgh" + '0x1f8b0b'.
532*acea8879SAndroid Build Coastguard Worker   const std::vector<char> src_data = { 'a', 'b', 'c',    'd',    'e',   'f',
533*acea8879SAndroid Build Coastguard Worker                                        'g', 'h', '\x1f', '\x8b', '\x08' };
534*acea8879SAndroid Build Coastguard Worker   const std::string src(src_data.cbegin(), src_data.cend());
535*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
536*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
537*acea8879SAndroid Build Coastguard Worker 
538*acea8879SAndroid Build Coastguard Worker   // tgt: "abcdefgxyz".
539*acea8879SAndroid Build Coastguard Worker   const std::vector<char> tgt_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z' };
540*acea8879SAndroid Build Coastguard Worker   const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
541*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
542*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
543*acea8879SAndroid Build Coastguard Worker 
544*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
545*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
546*acea8879SAndroid Build Coastguard Worker     "imgdiff", src_file.path, tgt_file.path, patch_file.path,
547*acea8879SAndroid Build Coastguard Worker   };
548*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
549*acea8879SAndroid Build Coastguard Worker 
550*acea8879SAndroid Build Coastguard Worker   // Verify.
551*acea8879SAndroid Build Coastguard Worker   std::string patch;
552*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
553*acea8879SAndroid Build Coastguard Worker 
554*acea8879SAndroid Build Coastguard Worker   // Expect one CHUNK_RAW (header) entry.
555*acea8879SAndroid Build Coastguard Worker   size_t num_normal;
556*acea8879SAndroid Build Coastguard Worker   size_t num_raw;
557*acea8879SAndroid Build Coastguard Worker   size_t num_deflate;
558*acea8879SAndroid Build Coastguard Worker   verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
559*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_normal);
560*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_deflate);
561*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1U, num_raw);
562*acea8879SAndroid Build Coastguard Worker 
563*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
564*acea8879SAndroid Build Coastguard Worker }
565*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,image_mode_short_input2)566*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, image_mode_short_input2) {
567*acea8879SAndroid Build Coastguard Worker   // src: "abcdefgh" + '0x1f8b0b00'.
568*acea8879SAndroid Build Coastguard Worker   const std::vector<char> src_data = { 'a', 'b', 'c',    'd',    'e',    'f',
569*acea8879SAndroid Build Coastguard Worker                                        'g', 'h', '\x1f', '\x8b', '\x08', '\x00' };
570*acea8879SAndroid Build Coastguard Worker   const std::string src(src_data.cbegin(), src_data.cend());
571*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
572*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
573*acea8879SAndroid Build Coastguard Worker 
574*acea8879SAndroid Build Coastguard Worker   // tgt: "abcdefgxyz".
575*acea8879SAndroid Build Coastguard Worker   const std::vector<char> tgt_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z' };
576*acea8879SAndroid Build Coastguard Worker   const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
577*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
578*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
579*acea8879SAndroid Build Coastguard Worker 
580*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
581*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
582*acea8879SAndroid Build Coastguard Worker     "imgdiff", src_file.path, tgt_file.path, patch_file.path,
583*acea8879SAndroid Build Coastguard Worker   };
584*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
585*acea8879SAndroid Build Coastguard Worker 
586*acea8879SAndroid Build Coastguard Worker   // Verify.
587*acea8879SAndroid Build Coastguard Worker   std::string patch;
588*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
589*acea8879SAndroid Build Coastguard Worker 
590*acea8879SAndroid Build Coastguard Worker   // Expect one CHUNK_RAW (header) entry.
591*acea8879SAndroid Build Coastguard Worker   size_t num_normal;
592*acea8879SAndroid Build Coastguard Worker   size_t num_raw;
593*acea8879SAndroid Build Coastguard Worker   size_t num_deflate;
594*acea8879SAndroid Build Coastguard Worker   verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
595*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_normal);
596*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_deflate);
597*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1U, num_raw);
598*acea8879SAndroid Build Coastguard Worker 
599*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
600*acea8879SAndroid Build Coastguard Worker }
601*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,image_mode_single_entry_long)602*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, image_mode_single_entry_long) {
603*acea8879SAndroid Build Coastguard Worker   // src: "abcdefgh" + '0x1f8b0b00' + some bytes.
604*acea8879SAndroid Build Coastguard Worker   const std::vector<char> src_data = { 'a',    'b',    'c',    'd',    'e',    'f',    'g',
605*acea8879SAndroid Build Coastguard Worker                                        'h',    '\x1f', '\x8b', '\x08', '\x00', '\xc4', '\x1e',
606*acea8879SAndroid Build Coastguard Worker                                        '\x53', '\x58', 't',    'e',    's',    't' };
607*acea8879SAndroid Build Coastguard Worker   const std::string src(src_data.cbegin(), src_data.cend());
608*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
609*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
610*acea8879SAndroid Build Coastguard Worker 
611*acea8879SAndroid Build Coastguard Worker   // tgt: "abcdefgxyz" + 200 bytes.
612*acea8879SAndroid Build Coastguard Worker   std::vector<char> tgt_data = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z' };
613*acea8879SAndroid Build Coastguard Worker   tgt_data.resize(tgt_data.size() + 200);
614*acea8879SAndroid Build Coastguard Worker 
615*acea8879SAndroid Build Coastguard Worker   const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
616*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
617*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
618*acea8879SAndroid Build Coastguard Worker 
619*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
620*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
621*acea8879SAndroid Build Coastguard Worker     "imgdiff", src_file.path, tgt_file.path, patch_file.path,
622*acea8879SAndroid Build Coastguard Worker   };
623*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
624*acea8879SAndroid Build Coastguard Worker 
625*acea8879SAndroid Build Coastguard Worker   // Verify.
626*acea8879SAndroid Build Coastguard Worker   std::string patch;
627*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
628*acea8879SAndroid Build Coastguard Worker 
629*acea8879SAndroid Build Coastguard Worker   // Expect one CHUNK_NORMAL entry, since it's exceeding the 160-byte limit for RAW.
630*acea8879SAndroid Build Coastguard Worker   size_t num_normal;
631*acea8879SAndroid Build Coastguard Worker   size_t num_raw;
632*acea8879SAndroid Build Coastguard Worker   size_t num_deflate;
633*acea8879SAndroid Build Coastguard Worker   verify_patch_header(patch, &num_normal, &num_raw, &num_deflate);
634*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(1U, num_normal);
635*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_deflate);
636*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0U, num_raw);
637*acea8879SAndroid Build Coastguard Worker 
638*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
639*acea8879SAndroid Build Coastguard Worker }
640*acea8879SAndroid Build Coastguard Worker 
TEST(ImgpatchTest,image_mode_patch_corruption)641*acea8879SAndroid Build Coastguard Worker TEST(ImgpatchTest, image_mode_patch_corruption) {
642*acea8879SAndroid Build Coastguard Worker   // src: "abcdefgh" + gzipped "xyz" (echo -n "xyz" | gzip -f | hd).
643*acea8879SAndroid Build Coastguard Worker   const std::vector<char> src_data = { 'a',    'b',    'c',    'd',    'e',    'f',    'g',
644*acea8879SAndroid Build Coastguard Worker                                        'h',    '\x1f', '\x8b', '\x08', '\x00', '\xc4', '\x1e',
645*acea8879SAndroid Build Coastguard Worker                                        '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xac',
646*acea8879SAndroid Build Coastguard Worker                                        '\x02', '\x00', '\x67', '\xba', '\x8e', '\xeb', '\x03',
647*acea8879SAndroid Build Coastguard Worker                                        '\x00', '\x00', '\x00' };
648*acea8879SAndroid Build Coastguard Worker   const std::string src(src_data.cbegin(), src_data.cend());
649*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
650*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));
651*acea8879SAndroid Build Coastguard Worker 
652*acea8879SAndroid Build Coastguard Worker   // tgt: "abcdefgxyz" + gzipped "xxyyzz".
653*acea8879SAndroid Build Coastguard Worker   const std::vector<char> tgt_data = {
654*acea8879SAndroid Build Coastguard Worker     'a',    'b',    'c',    'd',    'e',    'f',    'g',    'x',    'y',    'z',    '\x1f', '\x8b',
655*acea8879SAndroid Build Coastguard Worker     '\x08', '\x00', '\x62', '\x1f', '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xa8', '\xac',
656*acea8879SAndroid Build Coastguard Worker     '\xac', '\xaa', '\x02', '\x00', '\x96', '\x30', '\x06', '\xb7', '\x06', '\x00', '\x00', '\x00'
657*acea8879SAndroid Build Coastguard Worker   };
658*acea8879SAndroid Build Coastguard Worker   const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
659*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
660*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));
661*acea8879SAndroid Build Coastguard Worker 
662*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
663*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
664*acea8879SAndroid Build Coastguard Worker     "imgdiff", src_file.path, tgt_file.path, patch_file.path,
665*acea8879SAndroid Build Coastguard Worker   };
666*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
667*acea8879SAndroid Build Coastguard Worker 
668*acea8879SAndroid Build Coastguard Worker   // Verify.
669*acea8879SAndroid Build Coastguard Worker   std::string patch;
670*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
671*acea8879SAndroid Build Coastguard Worker   verify_patched_image(src, patch, tgt);
672*acea8879SAndroid Build Coastguard Worker 
673*acea8879SAndroid Build Coastguard Worker   // Corrupt the end of the patch and expect the ApplyImagePatch to fail.
674*acea8879SAndroid Build Coastguard Worker   patch.insert(patch.end() - 10, 10, '0');
675*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(-1, ApplyImagePatch(reinterpret_cast<const unsigned char*>(src.data()), src.size(),
676*acea8879SAndroid Build Coastguard Worker                                 reinterpret_cast<const unsigned char*>(patch.data()), patch.size(),
677*acea8879SAndroid Build Coastguard Worker                                 [](const unsigned char* /*data*/, size_t len) { return len; }));
678*acea8879SAndroid Build Coastguard Worker }
679*acea8879SAndroid Build Coastguard Worker 
construct_store_entry(const std::vector<std::tuple<std::string,size_t,char>> & info,ZipWriter * writer)680*acea8879SAndroid Build Coastguard Worker static void construct_store_entry(const std::vector<std::tuple<std::string, size_t, char>>& info,
681*acea8879SAndroid Build Coastguard Worker                                   ZipWriter* writer) {
682*acea8879SAndroid Build Coastguard Worker   for (auto& t : info) {
683*acea8879SAndroid Build Coastguard Worker     // Create t(1) blocks of t(2), and write the data to t(0)
684*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(0, writer->StartEntry(std::get<0>(t).c_str(), 0));
685*acea8879SAndroid Build Coastguard Worker     const std::string content(std::get<1>(t) * 4096, std::get<2>(t));
686*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(0, writer->WriteBytes(content.data(), content.size()));
687*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(0, writer->FinishEntry());
688*acea8879SAndroid Build Coastguard Worker   }
689*acea8879SAndroid Build Coastguard Worker }
690*acea8879SAndroid Build Coastguard Worker 
construct_deflate_entry(const std::vector<std::tuple<std::string,size_t,size_t>> & info,ZipWriter * writer,const std::string & data)691*acea8879SAndroid Build Coastguard Worker static void construct_deflate_entry(const std::vector<std::tuple<std::string, size_t, size_t>>& info,
692*acea8879SAndroid Build Coastguard Worker                                     ZipWriter* writer, const std::string& data) {
693*acea8879SAndroid Build Coastguard Worker   for (auto& t : info) {
694*acea8879SAndroid Build Coastguard Worker     // t(0): entry_name; t(1): block offset; t(2) length in blocks.
695*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(0, writer->StartEntry(std::get<0>(t).c_str(), ZipWriter::kCompress));
696*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(0, writer->WriteBytes(data.data() + std::get<1>(t) * 4096, std::get<2>(t) * 4096));
697*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(0, writer->FinishEntry());
698*acea8879SAndroid Build Coastguard Worker   }
699*acea8879SAndroid Build Coastguard Worker }
700*acea8879SAndroid Build Coastguard Worker 
701*acea8879SAndroid Build Coastguard Worker // Look for the source and patch pieces in debug_dir. Generate a target piece from each pair.
702*acea8879SAndroid Build Coastguard Worker // Concatenate all the target pieces and match against the original one. Used pieces in debug_dir
703*acea8879SAndroid Build Coastguard Worker // will be cleaned up.
GenerateAndCheckSplitTarget(const std::string & debug_dir,size_t count,const std::string & tgt)704*acea8879SAndroid Build Coastguard Worker static void GenerateAndCheckSplitTarget(const std::string& debug_dir, size_t count,
705*acea8879SAndroid Build Coastguard Worker                                         const std::string& tgt) {
706*acea8879SAndroid Build Coastguard Worker   std::string patched;
707*acea8879SAndroid Build Coastguard Worker   for (size_t i = 0; i < count; i++) {
708*acea8879SAndroid Build Coastguard Worker     std::string split_src_path = android::base::StringPrintf("%s/src-%zu", debug_dir.c_str(), i);
709*acea8879SAndroid Build Coastguard Worker     std::string split_src;
710*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::ReadFileToString(split_src_path, &split_src));
711*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(0, unlink(split_src_path.c_str()));
712*acea8879SAndroid Build Coastguard Worker 
713*acea8879SAndroid Build Coastguard Worker     std::string split_patch_path =
714*acea8879SAndroid Build Coastguard Worker         android::base::StringPrintf("%s/patch-%zu", debug_dir.c_str(), i);
715*acea8879SAndroid Build Coastguard Worker     std::string split_patch;
716*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::ReadFileToString(split_patch_path, &split_patch));
717*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(0, unlink(split_patch_path.c_str()));
718*acea8879SAndroid Build Coastguard Worker 
719*acea8879SAndroid Build Coastguard Worker     std::string split_tgt;
720*acea8879SAndroid Build Coastguard Worker     GenerateTarget(split_src, split_patch, &split_tgt);
721*acea8879SAndroid Build Coastguard Worker     patched += split_tgt;
722*acea8879SAndroid Build Coastguard Worker   }
723*acea8879SAndroid Build Coastguard Worker 
724*acea8879SAndroid Build Coastguard Worker   // Verify we can get back the original target image.
725*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(tgt, patched);
726*acea8879SAndroid Build Coastguard Worker }
727*acea8879SAndroid Build Coastguard Worker 
ConstructImageChunks(const std::vector<uint8_t> & content,const std::vector<std::tuple<std::string,size_t>> & info)728*acea8879SAndroid Build Coastguard Worker std::vector<ImageChunk> ConstructImageChunks(
729*acea8879SAndroid Build Coastguard Worker     const std::vector<uint8_t>& content, const std::vector<std::tuple<std::string, size_t>>& info) {
730*acea8879SAndroid Build Coastguard Worker   std::vector<ImageChunk> chunks;
731*acea8879SAndroid Build Coastguard Worker   size_t start = 0;
732*acea8879SAndroid Build Coastguard Worker   for (const auto& t : info) {
733*acea8879SAndroid Build Coastguard Worker     size_t length = std::get<1>(t);
734*acea8879SAndroid Build Coastguard Worker     chunks.emplace_back(CHUNK_NORMAL, start, &content, length, std::get<0>(t));
735*acea8879SAndroid Build Coastguard Worker     start += length;
736*acea8879SAndroid Build Coastguard Worker   }
737*acea8879SAndroid Build Coastguard Worker 
738*acea8879SAndroid Build Coastguard Worker   return chunks;
739*acea8879SAndroid Build Coastguard Worker }
740*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,zip_mode_split_image_smoke)741*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, zip_mode_split_image_smoke) {
742*acea8879SAndroid Build Coastguard Worker   std::vector<uint8_t> content;
743*acea8879SAndroid Build Coastguard Worker   content.reserve(4096 * 50);
744*acea8879SAndroid Build Coastguard Worker   uint8_t n = 0;
745*acea8879SAndroid Build Coastguard Worker   generate_n(back_inserter(content), 4096 * 50, [&n]() { return n++ / 4096; });
746*acea8879SAndroid Build Coastguard Worker 
747*acea8879SAndroid Build Coastguard Worker   ZipModeImage tgt_image(false, 4096 * 10);
748*acea8879SAndroid Build Coastguard Worker   std::vector<ImageChunk> tgt_chunks = ConstructImageChunks(content, { { "a", 100 },
749*acea8879SAndroid Build Coastguard Worker                                                                        { "b", 4096 * 2 },
750*acea8879SAndroid Build Coastguard Worker                                                                        { "c", 4096 * 3 },
751*acea8879SAndroid Build Coastguard Worker                                                                        { "d", 300 },
752*acea8879SAndroid Build Coastguard Worker                                                                        { "e-0", 4096 * 10 },
753*acea8879SAndroid Build Coastguard Worker                                                                        { "e-1", 4096 * 5 },
754*acea8879SAndroid Build Coastguard Worker                                                                        { "CD", 200 } });
755*acea8879SAndroid Build Coastguard Worker   tgt_image.Initialize(std::move(tgt_chunks),
756*acea8879SAndroid Build Coastguard Worker                        std::vector<uint8_t>(content.begin(), content.begin() + 82520));
757*acea8879SAndroid Build Coastguard Worker 
758*acea8879SAndroid Build Coastguard Worker   tgt_image.DumpChunks();
759*acea8879SAndroid Build Coastguard Worker 
760*acea8879SAndroid Build Coastguard Worker   ZipModeImage src_image(true, 4096 * 10);
761*acea8879SAndroid Build Coastguard Worker   std::vector<ImageChunk> src_chunks = ConstructImageChunks(content, { { "b", 4096 * 3 },
762*acea8879SAndroid Build Coastguard Worker                                                                        { "c-0", 4096 * 10 },
763*acea8879SAndroid Build Coastguard Worker                                                                        { "c-1", 4096 * 2 },
764*acea8879SAndroid Build Coastguard Worker                                                                        { "a", 4096 * 5 },
765*acea8879SAndroid Build Coastguard Worker                                                                        { "e-0", 4096 * 10 },
766*acea8879SAndroid Build Coastguard Worker                                                                        { "e-1", 10000 },
767*acea8879SAndroid Build Coastguard Worker                                                                        { "CD", 5000 } });
768*acea8879SAndroid Build Coastguard Worker   src_image.Initialize(std::move(src_chunks),
769*acea8879SAndroid Build Coastguard Worker                        std::vector<uint8_t>(content.begin(), content.begin() + 137880));
770*acea8879SAndroid Build Coastguard Worker 
771*acea8879SAndroid Build Coastguard Worker   std::vector<ZipModeImage> split_tgt_images;
772*acea8879SAndroid Build Coastguard Worker   std::vector<ZipModeImage> split_src_images;
773*acea8879SAndroid Build Coastguard Worker   std::vector<SortedRangeSet> split_src_ranges;
774*acea8879SAndroid Build Coastguard Worker 
775*acea8879SAndroid Build Coastguard Worker   ZipModeImage::SplitZipModeImageWithLimit(tgt_image, src_image, &split_tgt_images,
776*acea8879SAndroid Build Coastguard Worker                                            &split_src_images, &split_src_ranges);
777*acea8879SAndroid Build Coastguard Worker 
778*acea8879SAndroid Build Coastguard Worker   // src_piece 1: a 5 blocks, b 3 blocks
779*acea8879SAndroid Build Coastguard Worker   // src_piece 2: c-0 10 blocks
780*acea8879SAndroid Build Coastguard Worker   // src_piece 3: d 0 block, e-0 10 blocks
781*acea8879SAndroid Build Coastguard Worker   // src_piece 4: e-1 2 blocks; CD 2 blocks
782*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(split_tgt_images.size(), split_src_images.size());
783*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(4), split_tgt_images.size());
784*acea8879SAndroid Build Coastguard Worker 
785*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(1), split_tgt_images[0].NumOfChunks());
786*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(12288), split_tgt_images[0][0].DataLengthForPatch());
787*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ("4,0,3,15,20", split_src_ranges[0].ToString());
788*acea8879SAndroid Build Coastguard Worker 
789*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(1), split_tgt_images[1].NumOfChunks());
790*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(12288), split_tgt_images[1][0].DataLengthForPatch());
791*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ("2,3,13", split_src_ranges[1].ToString());
792*acea8879SAndroid Build Coastguard Worker 
793*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(1), split_tgt_images[2].NumOfChunks());
794*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(40960), split_tgt_images[2][0].DataLengthForPatch());
795*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ("2,20,30", split_src_ranges[2].ToString());
796*acea8879SAndroid Build Coastguard Worker 
797*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(1), split_tgt_images[3].NumOfChunks());
798*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(16984), split_tgt_images[3][0].DataLengthForPatch());
799*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ("2,30,34", split_src_ranges[3].ToString());
800*acea8879SAndroid Build Coastguard Worker }
801*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,zip_mode_store_large_apk)802*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, zip_mode_store_large_apk) {
803*acea8879SAndroid Build Coastguard Worker   // Construct src and tgt zip files with limit = 10 blocks.
804*acea8879SAndroid Build Coastguard Worker   //     src              tgt
805*acea8879SAndroid Build Coastguard Worker   //  12 blocks 'd'    3 blocks  'a'
806*acea8879SAndroid Build Coastguard Worker   //  8 blocks  'c'    3 blocks  'b'
807*acea8879SAndroid Build Coastguard Worker   //  3 blocks  'b'    8 blocks  'c' (exceeds limit)
808*acea8879SAndroid Build Coastguard Worker   //  3 blocks  'a'    12 blocks 'd' (exceeds limit)
809*acea8879SAndroid Build Coastguard Worker   //                   3 blocks  'e'
810*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
811*acea8879SAndroid Build Coastguard Worker   FILE* tgt_file_ptr = fdopen(tgt_file.release(), "wb");
812*acea8879SAndroid Build Coastguard Worker   ZipWriter tgt_writer(tgt_file_ptr);
813*acea8879SAndroid Build Coastguard Worker   construct_store_entry(
814*acea8879SAndroid Build Coastguard Worker       { { "a", 3, 'a' }, { "b", 3, 'b' }, { "c", 8, 'c' }, { "d", 12, 'd' }, { "e", 3, 'e' } },
815*acea8879SAndroid Build Coastguard Worker       &tgt_writer);
816*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.Finish());
817*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(tgt_file_ptr));
818*acea8879SAndroid Build Coastguard Worker 
819*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
820*acea8879SAndroid Build Coastguard Worker   FILE* src_file_ptr = fdopen(src_file.release(), "wb");
821*acea8879SAndroid Build Coastguard Worker   ZipWriter src_writer(src_file_ptr);
822*acea8879SAndroid Build Coastguard Worker   construct_store_entry({ { "d", 12, 'd' }, { "c", 8, 'c' }, { "b", 3, 'b' }, { "a", 3, 'a' } },
823*acea8879SAndroid Build Coastguard Worker                         &src_writer);
824*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.Finish());
825*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(src_file_ptr));
826*acea8879SAndroid Build Coastguard Worker 
827*acea8879SAndroid Build Coastguard Worker   // Compute patch.
828*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
829*acea8879SAndroid Build Coastguard Worker   TemporaryFile split_info_file;
830*acea8879SAndroid Build Coastguard Worker   TemporaryDir debug_dir;
831*acea8879SAndroid Build Coastguard Worker   std::string split_info_arg = android::base::StringPrintf("--split-info=%s", split_info_file.path);
832*acea8879SAndroid Build Coastguard Worker   std::string debug_dir_arg = android::base::StringPrintf("--debug-dir=%s", debug_dir.path);
833*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
834*acea8879SAndroid Build Coastguard Worker     "imgdiff", "-z", "--block-limit=10", split_info_arg.c_str(), debug_dir_arg.c_str(),
835*acea8879SAndroid Build Coastguard Worker     src_file.path, tgt_file.path, patch_file.path,
836*acea8879SAndroid Build Coastguard Worker   };
837*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
838*acea8879SAndroid Build Coastguard Worker 
839*acea8879SAndroid Build Coastguard Worker   std::string tgt;
840*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
841*acea8879SAndroid Build Coastguard Worker 
842*acea8879SAndroid Build Coastguard Worker   // Expect 4 pieces of patch. (Roughly 3'a',3'b'; 8'c'; 10'd'; 2'd'3'e')
843*acea8879SAndroid Build Coastguard Worker   GenerateAndCheckSplitTarget(debug_dir.path, 4, tgt);
844*acea8879SAndroid Build Coastguard Worker }
845*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,zip_mode_deflate_large_apk)846*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, zip_mode_deflate_large_apk) {
847*acea8879SAndroid Build Coastguard Worker   // Src and tgt zip files are constructed as follows.
848*acea8879SAndroid Build Coastguard Worker   //     src               tgt
849*acea8879SAndroid Build Coastguard Worker   //  22 blocks, "d"    4  blocks,  "a"
850*acea8879SAndroid Build Coastguard Worker   //  5 blocks,  "b"    4  blocks,  "b"
851*acea8879SAndroid Build Coastguard Worker   //  3 blocks,  "a"    8  blocks,  "c" (exceeds limit)
852*acea8879SAndroid Build Coastguard Worker   //  1 block,   "g"    20 blocks,  "d" (exceeds limit)
853*acea8879SAndroid Build Coastguard Worker   //  8 blocks,  "c"    2  blocks,  "e"
854*acea8879SAndroid Build Coastguard Worker   //  1 block,   "f"    1  block ,  "f"
855*acea8879SAndroid Build Coastguard Worker   std::string tgt_path = from_testdata_base("deflate_tgt.zip");
856*acea8879SAndroid Build Coastguard Worker   std::string src_path = from_testdata_base("deflate_src.zip");
857*acea8879SAndroid Build Coastguard Worker 
858*acea8879SAndroid Build Coastguard Worker   ZipModeImage src_image(true, 10 * 4096);
859*acea8879SAndroid Build Coastguard Worker   ZipModeImage tgt_image(false, 10 * 4096);
860*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(src_image.Initialize(src_path));
861*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(tgt_image.Initialize(tgt_path));
862*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(ZipModeImage::CheckAndProcessChunks(&tgt_image, &src_image));
863*acea8879SAndroid Build Coastguard Worker 
864*acea8879SAndroid Build Coastguard Worker   src_image.DumpChunks();
865*acea8879SAndroid Build Coastguard Worker   tgt_image.DumpChunks();
866*acea8879SAndroid Build Coastguard Worker 
867*acea8879SAndroid Build Coastguard Worker   std::vector<ZipModeImage> split_tgt_images;
868*acea8879SAndroid Build Coastguard Worker   std::vector<ZipModeImage> split_src_images;
869*acea8879SAndroid Build Coastguard Worker   std::vector<SortedRangeSet> split_src_ranges;
870*acea8879SAndroid Build Coastguard Worker   ZipModeImage::SplitZipModeImageWithLimit(tgt_image, src_image, &split_tgt_images,
871*acea8879SAndroid Build Coastguard Worker                                            &split_src_images, &split_src_ranges);
872*acea8879SAndroid Build Coastguard Worker 
873*acea8879SAndroid Build Coastguard Worker   // Expected split images with limit = 10 blocks.
874*acea8879SAndroid Build Coastguard Worker   // src_piece 0: a 3 blocks, b 5 blocks
875*acea8879SAndroid Build Coastguard Worker   // src_piece 1: c 8 blocks
876*acea8879SAndroid Build Coastguard Worker   // src_piece 2: d-0 10 block
877*acea8879SAndroid Build Coastguard Worker   // src_piece 3: d-1 10 blocks
878*acea8879SAndroid Build Coastguard Worker   // src_piece 4: e 1 block, CD
879*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(split_tgt_images.size(), split_src_images.size());
880*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(5), split_tgt_images.size());
881*acea8879SAndroid Build Coastguard Worker 
882*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(2), split_src_images[0].NumOfChunks());
883*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ("a", split_src_images[0][0].GetEntryName());
884*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ("b", split_src_images[0][1].GetEntryName());
885*acea8879SAndroid Build Coastguard Worker 
886*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(1), split_src_images[1].NumOfChunks());
887*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ("c", split_src_images[1][0].GetEntryName());
888*acea8879SAndroid Build Coastguard Worker 
889*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(0), split_src_images[2].NumOfChunks());
890*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(0), split_src_images[3].NumOfChunks());
891*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(0), split_src_images[4].NumOfChunks());
892*acea8879SAndroid Build Coastguard Worker 
893*acea8879SAndroid Build Coastguard Worker   // Compute patch.
894*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
895*acea8879SAndroid Build Coastguard Worker   TemporaryFile split_info_file;
896*acea8879SAndroid Build Coastguard Worker   TemporaryDir debug_dir;
897*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(ZipModeImage::GeneratePatches(split_tgt_images, split_src_images, split_src_ranges,
898*acea8879SAndroid Build Coastguard Worker                                             patch_file.path, split_info_file.path, debug_dir.path));
899*acea8879SAndroid Build Coastguard Worker 
900*acea8879SAndroid Build Coastguard Worker   // Verify the content of split info.
901*acea8879SAndroid Build Coastguard Worker   // Expect 5 pieces of patch. ["a","b"; "c"; "d-0"; "d-1"; "e"]
902*acea8879SAndroid Build Coastguard Worker   std::string split_info_string;
903*acea8879SAndroid Build Coastguard Worker   android::base::ReadFileToString(split_info_file.path, &split_info_string);
904*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> info_list =
905*acea8879SAndroid Build Coastguard Worker       android::base::Split(android::base::Trim(split_info_string), "\n");
906*acea8879SAndroid Build Coastguard Worker 
907*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(7), info_list.size());
908*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ("2", android::base::Trim(info_list[0]));
909*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ("5", android::base::Trim(info_list[1]));
910*acea8879SAndroid Build Coastguard Worker 
911*acea8879SAndroid Build Coastguard Worker   std::string tgt;
912*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tgt_path, &tgt));
913*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(160385), tgt.size());
914*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> tgt_file_ranges = {
915*acea8879SAndroid Build Coastguard Worker     "36864 2,22,31", "32768 2,31,40", "40960 2,0,11", "40960 2,11,21", "8833 4,21,22,40,41",
916*acea8879SAndroid Build Coastguard Worker   };
917*acea8879SAndroid Build Coastguard Worker 
918*acea8879SAndroid Build Coastguard Worker   for (size_t i = 0; i < 5; i++) {
919*acea8879SAndroid Build Coastguard Worker     struct stat st;
920*acea8879SAndroid Build Coastguard Worker     std::string path = android::base::StringPrintf("%s/patch-%zu", debug_dir.path, i);
921*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(0, stat(path.c_str(), &st));
922*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(std::to_string(st.st_size) + " " + tgt_file_ranges[i],
923*acea8879SAndroid Build Coastguard Worker               android::base::Trim(info_list[i + 2]));
924*acea8879SAndroid Build Coastguard Worker   }
925*acea8879SAndroid Build Coastguard Worker 
926*acea8879SAndroid Build Coastguard Worker   GenerateAndCheckSplitTarget(debug_dir.path, 5, tgt);
927*acea8879SAndroid Build Coastguard Worker }
928*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,zip_mode_no_match_source)929*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, zip_mode_no_match_source) {
930*acea8879SAndroid Build Coastguard Worker   // Generate 20 blocks of random data.
931*acea8879SAndroid Build Coastguard Worker   std::string random_data;
932*acea8879SAndroid Build Coastguard Worker   random_data.reserve(4096 * 20);
933*acea8879SAndroid Build Coastguard Worker   generate_n(back_inserter(random_data), 4096 * 20, []() { return rand() % 256; });
934*acea8879SAndroid Build Coastguard Worker 
935*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
936*acea8879SAndroid Build Coastguard Worker   FILE* tgt_file_ptr = fdopen(tgt_file.release(), "wb");
937*acea8879SAndroid Build Coastguard Worker   ZipWriter tgt_writer(tgt_file_ptr);
938*acea8879SAndroid Build Coastguard Worker 
939*acea8879SAndroid Build Coastguard Worker   construct_deflate_entry({ { "a", 0, 4 }, { "b", 5, 5 }, { "c", 11, 5 } }, &tgt_writer,
940*acea8879SAndroid Build Coastguard Worker                           random_data);
941*acea8879SAndroid Build Coastguard Worker 
942*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.Finish());
943*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(tgt_file_ptr));
944*acea8879SAndroid Build Coastguard Worker 
945*acea8879SAndroid Build Coastguard Worker   // We don't have a matching source entry.
946*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
947*acea8879SAndroid Build Coastguard Worker   FILE* src_file_ptr = fdopen(src_file.release(), "wb");
948*acea8879SAndroid Build Coastguard Worker   ZipWriter src_writer(src_file_ptr);
949*acea8879SAndroid Build Coastguard Worker   construct_store_entry({ { "d", 1, 'd' } }, &src_writer);
950*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.Finish());
951*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(src_file_ptr));
952*acea8879SAndroid Build Coastguard Worker 
953*acea8879SAndroid Build Coastguard Worker   // Compute patch.
954*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
955*acea8879SAndroid Build Coastguard Worker   TemporaryFile split_info_file;
956*acea8879SAndroid Build Coastguard Worker   TemporaryDir debug_dir;
957*acea8879SAndroid Build Coastguard Worker   std::string split_info_arg = android::base::StringPrintf("--split-info=%s", split_info_file.path);
958*acea8879SAndroid Build Coastguard Worker   std::string debug_dir_arg = android::base::StringPrintf("--debug-dir=%s", debug_dir.path);
959*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
960*acea8879SAndroid Build Coastguard Worker     "imgdiff", "-z", "--block-limit=10", debug_dir_arg.c_str(), split_info_arg.c_str(),
961*acea8879SAndroid Build Coastguard Worker     src_file.path, tgt_file.path, patch_file.path,
962*acea8879SAndroid Build Coastguard Worker   };
963*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
964*acea8879SAndroid Build Coastguard Worker 
965*acea8879SAndroid Build Coastguard Worker   std::string tgt;
966*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
967*acea8879SAndroid Build Coastguard Worker 
968*acea8879SAndroid Build Coastguard Worker   // Expect 1 pieces of patch due to no matching source entry.
969*acea8879SAndroid Build Coastguard Worker   GenerateAndCheckSplitTarget(debug_dir.path, 1, tgt);
970*acea8879SAndroid Build Coastguard Worker }
971*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,zip_mode_large_enough_limit)972*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, zip_mode_large_enough_limit) {
973*acea8879SAndroid Build Coastguard Worker   // Generate 20 blocks of random data.
974*acea8879SAndroid Build Coastguard Worker   std::string random_data;
975*acea8879SAndroid Build Coastguard Worker   random_data.reserve(4096 * 20);
976*acea8879SAndroid Build Coastguard Worker   generate_n(back_inserter(random_data), 4096 * 20, []() { return rand() % 256; });
977*acea8879SAndroid Build Coastguard Worker 
978*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
979*acea8879SAndroid Build Coastguard Worker   FILE* tgt_file_ptr = fdopen(tgt_file.release(), "wb");
980*acea8879SAndroid Build Coastguard Worker   ZipWriter tgt_writer(tgt_file_ptr);
981*acea8879SAndroid Build Coastguard Worker 
982*acea8879SAndroid Build Coastguard Worker   construct_deflate_entry({ { "a", 0, 10 }, { "b", 10, 5 } }, &tgt_writer, random_data);
983*acea8879SAndroid Build Coastguard Worker 
984*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.Finish());
985*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(tgt_file_ptr));
986*acea8879SAndroid Build Coastguard Worker 
987*acea8879SAndroid Build Coastguard Worker   // Construct 10 blocks of source.
988*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
989*acea8879SAndroid Build Coastguard Worker   FILE* src_file_ptr = fdopen(src_file.release(), "wb");
990*acea8879SAndroid Build Coastguard Worker   ZipWriter src_writer(src_file_ptr);
991*acea8879SAndroid Build Coastguard Worker   construct_deflate_entry({ { "a", 1, 10 } }, &src_writer, random_data);
992*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.Finish());
993*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(src_file_ptr));
994*acea8879SAndroid Build Coastguard Worker 
995*acea8879SAndroid Build Coastguard Worker   // Compute patch with a limit of 20 blocks.
996*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
997*acea8879SAndroid Build Coastguard Worker   TemporaryFile split_info_file;
998*acea8879SAndroid Build Coastguard Worker   TemporaryDir debug_dir;
999*acea8879SAndroid Build Coastguard Worker   std::string split_info_arg = android::base::StringPrintf("--split-info=%s", split_info_file.path);
1000*acea8879SAndroid Build Coastguard Worker   std::string debug_dir_arg = android::base::StringPrintf("--debug-dir=%s", debug_dir.path);
1001*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
1002*acea8879SAndroid Build Coastguard Worker     "imgdiff", "-z", "--block-limit=20", split_info_arg.c_str(), debug_dir_arg.c_str(),
1003*acea8879SAndroid Build Coastguard Worker     src_file.path, tgt_file.path, patch_file.path,
1004*acea8879SAndroid Build Coastguard Worker   };
1005*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
1006*acea8879SAndroid Build Coastguard Worker 
1007*acea8879SAndroid Build Coastguard Worker   std::string tgt;
1008*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
1009*acea8879SAndroid Build Coastguard Worker 
1010*acea8879SAndroid Build Coastguard Worker   // Expect 1 piece of patch since limit is larger than the zip file size.
1011*acea8879SAndroid Build Coastguard Worker   GenerateAndCheckSplitTarget(debug_dir.path, 1, tgt);
1012*acea8879SAndroid Build Coastguard Worker }
1013*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,zip_mode_large_apk_small_target_chunk)1014*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, zip_mode_large_apk_small_target_chunk) {
1015*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
1016*acea8879SAndroid Build Coastguard Worker   FILE* tgt_file_ptr = fdopen(tgt_file.release(), "wb");
1017*acea8879SAndroid Build Coastguard Worker   ZipWriter tgt_writer(tgt_file_ptr);
1018*acea8879SAndroid Build Coastguard Worker 
1019*acea8879SAndroid Build Coastguard Worker   // The first entry is less than 4096 bytes, followed immediately by an entry that has a very
1020*acea8879SAndroid Build Coastguard Worker   // large counterpart in the source file. Therefore the first entry will be patched separately.
1021*acea8879SAndroid Build Coastguard Worker   std::string small_chunk("a", 2000);
1022*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.StartEntry("a", 0));
1023*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.WriteBytes(small_chunk.data(), small_chunk.size()));
1024*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.FinishEntry());
1025*acea8879SAndroid Build Coastguard Worker   construct_store_entry(
1026*acea8879SAndroid Build Coastguard Worker       {
1027*acea8879SAndroid Build Coastguard Worker           { "b", 12, 'b' }, { "c", 3, 'c' },
1028*acea8879SAndroid Build Coastguard Worker       },
1029*acea8879SAndroid Build Coastguard Worker       &tgt_writer);
1030*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.Finish());
1031*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(tgt_file_ptr));
1032*acea8879SAndroid Build Coastguard Worker 
1033*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
1034*acea8879SAndroid Build Coastguard Worker   FILE* src_file_ptr = fdopen(src_file.release(), "wb");
1035*acea8879SAndroid Build Coastguard Worker   ZipWriter src_writer(src_file_ptr);
1036*acea8879SAndroid Build Coastguard Worker   construct_store_entry({ { "a", 1, 'a' }, { "b", 13, 'b' }, { "c", 1, 'c' } }, &src_writer);
1037*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.Finish());
1038*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(src_file_ptr));
1039*acea8879SAndroid Build Coastguard Worker 
1040*acea8879SAndroid Build Coastguard Worker   // Compute patch.
1041*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
1042*acea8879SAndroid Build Coastguard Worker   TemporaryFile split_info_file;
1043*acea8879SAndroid Build Coastguard Worker   TemporaryDir debug_dir;
1044*acea8879SAndroid Build Coastguard Worker   std::string split_info_arg = android::base::StringPrintf("--split-info=%s", split_info_file.path);
1045*acea8879SAndroid Build Coastguard Worker   std::string debug_dir_arg = android::base::StringPrintf("--debug-dir=%s", debug_dir.path);
1046*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
1047*acea8879SAndroid Build Coastguard Worker     "imgdiff",     "-z",          "--block-limit=10", split_info_arg.c_str(), debug_dir_arg.c_str(),
1048*acea8879SAndroid Build Coastguard Worker     src_file.path, tgt_file.path, patch_file.path,
1049*acea8879SAndroid Build Coastguard Worker   };
1050*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
1051*acea8879SAndroid Build Coastguard Worker 
1052*acea8879SAndroid Build Coastguard Worker   std::string tgt;
1053*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
1054*acea8879SAndroid Build Coastguard Worker 
1055*acea8879SAndroid Build Coastguard Worker   // Expect three split src images:
1056*acea8879SAndroid Build Coastguard Worker   // src_piece 0: a 1 blocks
1057*acea8879SAndroid Build Coastguard Worker   // src_piece 1: b-0 10 blocks
1058*acea8879SAndroid Build Coastguard Worker   // src_piece 2: b-1 3 blocks, c 1 blocks, CD
1059*acea8879SAndroid Build Coastguard Worker   GenerateAndCheckSplitTarget(debug_dir.path, 3, tgt);
1060*acea8879SAndroid Build Coastguard Worker }
1061*acea8879SAndroid Build Coastguard Worker 
TEST(ImgdiffTest,zip_mode_large_apk_skipped_small_target_chunk)1062*acea8879SAndroid Build Coastguard Worker TEST(ImgdiffTest, zip_mode_large_apk_skipped_small_target_chunk) {
1063*acea8879SAndroid Build Coastguard Worker   TemporaryFile tgt_file;
1064*acea8879SAndroid Build Coastguard Worker   FILE* tgt_file_ptr = fdopen(tgt_file.release(), "wb");
1065*acea8879SAndroid Build Coastguard Worker   ZipWriter tgt_writer(tgt_file_ptr);
1066*acea8879SAndroid Build Coastguard Worker 
1067*acea8879SAndroid Build Coastguard Worker   construct_store_entry(
1068*acea8879SAndroid Build Coastguard Worker       {
1069*acea8879SAndroid Build Coastguard Worker           { "a", 11, 'a' },
1070*acea8879SAndroid Build Coastguard Worker       },
1071*acea8879SAndroid Build Coastguard Worker       &tgt_writer);
1072*acea8879SAndroid Build Coastguard Worker 
1073*acea8879SAndroid Build Coastguard Worker   // Construct a tiny target entry of 1 byte, which will be skipped due to the tail alignment of
1074*acea8879SAndroid Build Coastguard Worker   // the previous entry.
1075*acea8879SAndroid Build Coastguard Worker   std::string small_chunk("b", 1);
1076*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.StartEntry("b", 0));
1077*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.WriteBytes(small_chunk.data(), small_chunk.size()));
1078*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.FinishEntry());
1079*acea8879SAndroid Build Coastguard Worker 
1080*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, tgt_writer.Finish());
1081*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(tgt_file_ptr));
1082*acea8879SAndroid Build Coastguard Worker 
1083*acea8879SAndroid Build Coastguard Worker   TemporaryFile src_file;
1084*acea8879SAndroid Build Coastguard Worker   FILE* src_file_ptr = fdopen(src_file.release(), "wb");
1085*acea8879SAndroid Build Coastguard Worker   ZipWriter src_writer(src_file_ptr);
1086*acea8879SAndroid Build Coastguard Worker   construct_store_entry(
1087*acea8879SAndroid Build Coastguard Worker       {
1088*acea8879SAndroid Build Coastguard Worker           { "a", 11, 'a' }, { "b", 11, 'b' },
1089*acea8879SAndroid Build Coastguard Worker       },
1090*acea8879SAndroid Build Coastguard Worker       &src_writer);
1091*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, src_writer.Finish());
1092*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(src_file_ptr));
1093*acea8879SAndroid Build Coastguard Worker 
1094*acea8879SAndroid Build Coastguard Worker   // Compute patch.
1095*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
1096*acea8879SAndroid Build Coastguard Worker   TemporaryFile split_info_file;
1097*acea8879SAndroid Build Coastguard Worker   TemporaryDir debug_dir;
1098*acea8879SAndroid Build Coastguard Worker   std::string split_info_arg = android::base::StringPrintf("--split-info=%s", split_info_file.path);
1099*acea8879SAndroid Build Coastguard Worker   std::string debug_dir_arg = android::base::StringPrintf("--debug-dir=%s", debug_dir.path);
1100*acea8879SAndroid Build Coastguard Worker   std::vector<const char*> args = {
1101*acea8879SAndroid Build Coastguard Worker     "imgdiff",     "-z",          "--block-limit=10", split_info_arg.c_str(), debug_dir_arg.c_str(),
1102*acea8879SAndroid Build Coastguard Worker     src_file.path, tgt_file.path, patch_file.path,
1103*acea8879SAndroid Build Coastguard Worker   };
1104*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, imgdiff(args.size(), args.data()));
1105*acea8879SAndroid Build Coastguard Worker 
1106*acea8879SAndroid Build Coastguard Worker   std::string tgt;
1107*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tgt_file.path, &tgt));
1108*acea8879SAndroid Build Coastguard Worker 
1109*acea8879SAndroid Build Coastguard Worker   // Expect two split src images:
1110*acea8879SAndroid Build Coastguard Worker   // src_piece 0: a-0 10 blocks
1111*acea8879SAndroid Build Coastguard Worker   // src_piece 1: a-0 1 block, CD
1112*acea8879SAndroid Build Coastguard Worker   GenerateAndCheckSplitTarget(debug_dir.path, 2, tgt);
1113*acea8879SAndroid Build Coastguard Worker }
1114