1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <gtest/gtest.h>
17 #include "applypatch/data_writer.h"
18 #include "unittest_comm.h"
19 #include "update_diff.h"
20 #include "update_patch.h"
21 
22 using namespace std;
23 using namespace Hpackage;
24 using namespace testing::ext;
25 
26 namespace {
27 class DiffPatchUnitTest : public testing::Test {
28 public:
DiffPatchUnitTest()29     DiffPatchUnitTest() {}
~DiffPatchUnitTest()30     ~DiffPatchUnitTest() {}
31 
SetUpTestCase(void)32     static void SetUpTestCase(void) {}
TearDownTestCase(void)33     static void TearDownTestCase(void) {}
SetUp()34     void SetUp() {}
TearDown()35     void TearDown() {}
TestBody()36     void TestBody() {}
37 public:
GeneraterHash(const std::string & fileName) const38     std::string GeneraterHash(const std::string &fileName) const
39     {
40         UpdatePatch::MemMapInfo data {};
41         int32_t ret = PatchMapFile(fileName, data);
42         EXPECT_EQ(0, ret);
43         return UpdatePatch::GeneraterBufferHash({data.memory, data.length});
44     }
45 
BlockDiffPatchTest(const std::string & oldFile,const std::string & newFile,const std::string & patchFile,const std::string & restoreFile) const46     int BlockDiffPatchTest(const std::string &oldFile,
47         const std::string &newFile, const std::string &patchFile, const std::string &restoreFile) const
48     {
49         int32_t ret = UpdatePatch::UpdateDiff::DiffBlock(TEST_PATH_FROM + oldFile,
50             TEST_PATH_FROM + newFile, TEST_PATH_FROM + patchFile);
51         EXPECT_EQ(0, ret);
52         ret = UpdatePatch::UpdateApplyPatch::ApplyPatch(TEST_PATH_FROM + patchFile,
53             TEST_PATH_FROM + oldFile, TEST_PATH_FROM + restoreFile);
54         EXPECT_EQ(0, ret);
55 
56         std::string expected = GeneraterHash(TEST_PATH_FROM + newFile);
57         std::string restoreHash = GeneraterHash(TEST_PATH_FROM + restoreFile);
58         EXPECT_EQ(0, memcmp(expected.c_str(), restoreHash.c_str(), restoreHash.size()));
59         return 0;
60     }
61 
ImgageDiffPatchFileTest(size_t limit,const std::string & oldFile,const std::string & newFile,const std::string & patchFile,const std::string & restoreFile) const62     int ImgageDiffPatchFileTest(size_t limit, const std::string &oldFile,
63         const std::string &newFile, const std::string &patchFile, const std::string &restoreFile) const
64     {
65         int32_t ret = UpdatePatch::UpdateDiff::DiffImage(limit, TEST_PATH_FROM + oldFile,
66             TEST_PATH_FROM + newFile, TEST_PATH_FROM + patchFile);
67         EXPECT_EQ(0, ret);
68         ret = UpdatePatch::UpdateApplyPatch::ApplyPatch(TEST_PATH_FROM + patchFile,
69             TEST_PATH_FROM + oldFile, TEST_PATH_FROM + restoreFile);
70         EXPECT_EQ(0, ret);
71 
72         // 生成新文件的hash值
73         std::string expected = GeneraterHash(TEST_PATH_FROM + newFile);
74         std::string restoreHash = GeneraterHash(TEST_PATH_FROM + restoreFile);
75         EXPECT_EQ(0, restoreHash.compare(expected));
76         return 0;
77     }
78 
TestApplyPatch(const std::string & patchName,const std::string & oldName,const std::string & expected,UpdatePatch::UpdateApplyPatch::ImageProcessor writer) const79     int32_t TestApplyPatch(const std::string &patchName, const std::string &oldName,
80         const std::string &expected, UpdatePatch::UpdateApplyPatch::ImageProcessor writer) const
81     {
82         PATCH_DEBUG("UpdateApplyPatch::ApplyPatch : %s ", patchName.c_str());
83         std::vector<uint8_t> empty;
84         UpdatePatch::MemMapInfo patchData {};
85         UpdatePatch::MemMapInfo oldData {};
86         int32_t ret = PatchMapFile(patchName, patchData);
87         if (ret != 0) {
88             PATCH_LOGE("Failed to read patch file");
89             return -1;
90         }
91         ret = PatchMapFile(oldName, oldData);
92         if (ret != 0) {
93             PATCH_LOGE("Failed to read old file");
94             return -1;
95         }
96 
97         PATCH_LOGI("UpdateApplyPatch::ApplyPatch patchData %zu oldData %zu ", patchData.length, oldData.length);
98         // check if image patch
99         if (memcmp(patchData.memory, UpdatePatch::PKGDIFF_MAGIC,
100             std::char_traits<char>::length(UpdatePatch::PKGDIFF_MAGIC)) == 0) {
101             UpdatePatch::PatchParam param {};
102             param.patch = patchData.memory;
103             param.patchSize = patchData.length;
104             param.oldBuff = oldData.memory;
105             param.oldSize = oldData.length;
106             ret = UpdatePatch::UpdateApplyPatch::ApplyImagePatch(param, empty, writer, expected);
107             if (ret != 0) {
108                 PATCH_LOGE("Failed to apply image patch file");
109                 return -1;
110             }
111         }
112         return 0;
113     }
114 
ImgageDiffPatchFileTest2(size_t limit,const std::string & oldFile,const std::string & newFile,const std::string & patchFile,const std::string & restoreFile) const115     int ImgageDiffPatchFileTest2(size_t limit, const std::string &oldFile,
116         const std::string &newFile, const std::string &patchFile, const std::string &restoreFile) const
117     {
118         int32_t ret = UpdatePatch::UpdateDiff::DiffImage(limit, TEST_PATH_FROM + oldFile,
119             TEST_PATH_FROM + newFile, TEST_PATH_FROM + patchFile);
120         EXPECT_EQ(0, ret);
121 
122         std::string expected = GeneraterHash(TEST_PATH_FROM + newFile);
123         std::unique_ptr<UpdatePatch::FilePatchWriter> writer =
124             std::make_unique<UpdatePatch::FilePatchWriter>(TEST_PATH_FROM + restoreFile);
125         if (writer == nullptr) {
126             PATCH_LOGE("Failed to create writer");
127             return -1;
128         }
129         writer->Init();
130 
131         ret = TestApplyPatch(TEST_PATH_FROM + patchFile, TEST_PATH_FROM + oldFile, expected,
132             [&](size_t start, const UpdatePatch::BlockBuffer &data, size_t size) -> int {
133                 return writer->Write(start, data, size);
134             });
135         EXPECT_EQ(0, ret);
136         writer->Finish();
137         std::string restoreHash = GeneraterHash(TEST_PATH_FROM + restoreFile);
138         EXPECT_EQ(0, restoreHash.compare(expected));
139         return 0;
140     }
141 
TestApplyBlockPatch(const std::string & patchName,const std::string & oldName,const std::string & newName,bool isBuffer) const142     int32_t TestApplyBlockPatch(const std::string &patchName,
143         const std::string &oldName, const std::string &newName, bool isBuffer) const
144     {
145         PATCH_DEBUG("UpdateApplyPatch::ApplyPatch : %s ", patchName.c_str());
146         std::vector<uint8_t> empty;
147         UpdatePatch::MemMapInfo patchData {};
148         UpdatePatch::MemMapInfo oldData {};
149         int32_t ret = PatchMapFile(patchName, patchData);
150         if (ret != 0) {
151             PATCH_LOGE("Failed to read patch file");
152             return -1;
153         }
154         ret = PatchMapFile(oldName, oldData);
155         if (ret != 0) {
156             PATCH_LOGE("Failed to read old file");
157             return -1;
158         }
159 
160         PATCH_LOGI("TestApplyBlockPatch patchData %zu oldData %zu ", patchData.length, oldData.length);
161         UpdatePatch::PatchBuffer patchInfo = {patchData.memory, 0, patchData.length};
162         UpdatePatch::BlockBuffer oldInfo = {oldData.memory, oldData.length};
163         if (isBuffer) {
164             std::vector<uint8_t> newData;
165             ret = UpdatePatch::UpdateApplyPatch::ApplyBlockPatch(patchInfo, oldInfo, newData);
166             if (ret != 0) {
167                 PATCH_LOGE("Failed to apply block patch file");
168                 return -1;
169             }
170             std::ofstream stream(newName, std::ios::out | std::ios::binary);
171             if (stream.fail()) {
172                 PATCH_LOGE("Failed to open %s", newName.c_str());
173                 return -1;
174             }
175             stream.write(reinterpret_cast<const char*>(newData.data()), newData.size());
176         } else {
177             std::unique_ptr<UpdatePatch::FilePatchWriter> writer =
178                 std::make_unique<UpdatePatch::FilePatchWriter>(newName);
179             if (writer == nullptr) {
180                 PATCH_LOGE("Failed to create writer");
181                 return -1;
182             }
183             writer->Init();
184 
185             ret = UpdatePatch::UpdateApplyPatch::ApplyBlockPatch(patchInfo, oldInfo, writer.get());
186             EXPECT_EQ(0, ret);
187             writer->Finish();
188         }
189         return 0;
190     }
191 
BlockDiffPatchTest2(const std::string & oldFile,const std::string & newFile,const std::string & patchFile,const std::string & restoreFile,bool isBuffer) const192     int BlockDiffPatchTest2(const std::string &oldFile,
193         const std::string &newFile, const std::string &patchFile, const std::string &restoreFile, bool isBuffer) const
194     {
195         int32_t ret = UpdatePatch::UpdateDiff::DiffBlock(TEST_PATH_FROM + oldFile,
196             TEST_PATH_FROM + newFile, TEST_PATH_FROM + patchFile);
197         EXPECT_EQ(0, ret);
198 
199         ret = TestApplyBlockPatch(TEST_PATH_FROM + patchFile,
200             TEST_PATH_FROM + oldFile, TEST_PATH_FROM + restoreFile, isBuffer);
201         EXPECT_EQ(0, ret);
202 
203         std::string expected = GeneraterHash(TEST_PATH_FROM + newFile);
204         std::string restoreHash = GeneraterHash(TEST_PATH_FROM + restoreFile);
205         EXPECT_EQ(0, memcmp(expected.c_str(), restoreHash.c_str(), restoreHash.size()));
206         return 0;
207     }
208 };
209 
210 HWTEST_F(DiffPatchUnitTest, BlockDiffPatchTest, TestSize.Level1)
211 {
212     DiffPatchUnitTest test;
213     EXPECT_EQ(0, test.BlockDiffPatchTest(
214         "../diffpatch/patchtest.old",
215         "../diffpatch/patchtest.new",
216         "../diffpatch/patchtest.patch",
217         "../diffpatch/patchtest.new_1"));
218 }
219 
220 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchFileTest, TestSize.Level1)
221 {
222     DiffPatchUnitTest test;
223     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0,
224         "../diffpatch/patchtest.old",
225         "../diffpatch/patchtest.new",
226         "../diffpatch/patchtest.img_patch",
227         "../diffpatch/patchtest.new_2"));
228 }
229 
230 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchFileWithLimit, TestSize.Level1)
231 {
232     DiffPatchUnitTest test;
233     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(16,
234         "../diffpatch/patchtest.old",
235         "../diffpatch/patchtest.new",
236         "../diffpatch/patchtest.img_patch",
237         "../diffpatch/patchtest.new_3"));
238 }
239 
240 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchGzFile, TestSize.Level1)
241 {
242     DiffPatchUnitTest test;
243     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0,
244         "../diffpatch/PatchGztest_old.gz",
245         "../diffpatch/PatchGztest_new.gz",
246         "../diffpatch/PatchGztest_gz.img_patch",
247         "../diffpatch/PatchGztest_gz_new.zip"));
248 }
249 
250 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File, TestSize.Level1)
251 {
252     DiffPatchUnitTest test;
253     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0,
254         "../diffpatch/PatchLz4test_old.lz4",
255         "../diffpatch/PatchLz4test_new.lz4",
256         "../diffpatch/PatchLz4test_lz4.img_patch",
257         "../diffpatch/PatchLz4test_lz4_new.lz"));
258 }
259 
260 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_1, TestSize.Level1)
261 {
262     DiffPatchUnitTest test;
263     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0,
264         "../diffpatch/ImgageDiffPatchLz4File_1_old.lz",
265         "../diffpatch/ImgageDiffPatchLz4File_1_new.lz",
266         "../diffpatch/ImgageDiffPatchLz4File_1_lz4.img_patch",
267         "../diffpatch/ImgageDiffPatchLz4File_1_lz4_new.lz"));
268 }
269 
270 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_2, TestSize.Level1)
271 {
272     DiffPatchUnitTest test;
273     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(1,
274         "../diffpatch/ImgageDiffPatchLz4File_1_old.lz",
275         "../diffpatch/ImgageDiffPatchLz4File_1_new.lz",
276         "../diffpatch/ImgageDiffPatchLz4File_1_lz4.img_patch",
277         "../diffpatch/ImgageDiffPatchLz4File_1_lz4_new.lz"));
278 }
279 
280 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_3, TestSize.Level1)
281 {
282     DiffPatchUnitTest test;
283     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0,
284         "../diffpatch/ImgageDiffPatchLz4File_3_old.lz4",
285         "../diffpatch/ImgageDiffPatchLz4File_3_new.lz4",
286         "../diffpatch/ImgageDiffPatchLz4File_3_lz4.img_patch",
287         "../diffpatch/ImgageDiffPatchLz4File_3_lz4_new.lz"));
288 }
289 
290 // 测试包含一个文件时,新增一个文件
291 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile, TestSize.Level1)
292 {
293     DiffPatchUnitTest test;
294     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0,
295         "../diffpatch/ImgageDiffPatchZipFile_old.zip",
296         "../diffpatch/ImgageDiffPatchZipFile_new.zip",
297         "../diffpatch/ImgageDiffPatchZipFile_zip.img_patch",
298         "../diffpatch/ImgageDiffPatchZipFile_zip_new.zip"));
299 }
300 
301 // 测试使用winrar的压缩文件
302 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_1, TestSize.Level1)
303 {
304     DiffPatchUnitTest test;
305     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0,
306         "../diffpatch/ImgageDiffPatchZipFile_1_old.zip",
307         "../diffpatch/ImgageDiffPatchZipFile_1_new.zip",
308         "../diffpatch/ImgageDiffPatchZipFile_1_zip.img_patch",
309         "../diffpatch/ImgageDiffPatchZipFile_1_zip_new.zip"));
310 }
311 
312 // 测试包含一个文件时,文件内容不相同
313 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_2, TestSize.Level1)
314 {
315     DiffPatchUnitTest test;
316     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0,
317         "../diffpatch/ImgageDiffPatchZipFile_2_old.zip",
318         "../diffpatch/ImgageDiffPatchZipFile_2_new.zip",
319         "../diffpatch/ImgageDiffPatchZipFile_2_zip.img_patch",
320         "../diffpatch/ImgageDiffPatchZipFile_2_zip_new.zip"));
321 }
322 
323 // linux 上压缩,多文件测试
324 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_3, TestSize.Level1)
325 {
326     DiffPatchUnitTest test;
327     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0,
328         "../diffpatch/ImgageDiffPatchZipFile_3_old.zip",
329         "../diffpatch/ImgageDiffPatchZipFile_3_new.zip",
330         "../diffpatch/ImgageDiffPatchZipFile_3_zip.img_patch",
331         "../diffpatch/ImgageDiffPatchZipFile_3_zip_new.zip"));
332 }
333 
334 // linux 上压缩,超大buffer length测试
335 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_4, TestSize.Level1)
336 {
337     DiffPatchUnitTest test;
338     EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0,
339         "../diffpatch/ImgageDiffPatchZipFile_4_old.zip",
340         "../diffpatch/ImgageDiffPatchZipFile_4_new.zip",
341         "../diffpatch/ImgageDiffPatchZipFile_4_zip.img_patch",
342         "../diffpatch/ImgageDiffPatchZipFile_4_zip_new.zip"));
343 }
344 
345 HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchGzFile2, TestSize.Level1)
346 {
347     DiffPatchUnitTest test;
348     EXPECT_EQ(0, test.ImgageDiffPatchFileTest2(0,
349         "../diffpatch/PatchGztest_old.gz",
350         "../diffpatch/PatchGztest_new.gz",
351         "../diffpatch/PatchGztest_gz.img_patch",
352         "../diffpatch/PatchGztest_gz_new.zip"));
353 }
354 
355 HWTEST_F(DiffPatchUnitTest, BlockDiffPatchGzFile, TestSize.Level1)
356 {
357     DiffPatchUnitTest test;
358     EXPECT_EQ(0, test.BlockDiffPatchTest2(
359         "../diffpatch/PatchGztest_old.gz",
360         "../diffpatch/PatchGztest_new.gz",
361         "../diffpatch/PatchGztest_gz.img_patch",
362         "../diffpatch/PatchGztest_gz_new.zip", true));
363 }
364 
365 HWTEST_F(DiffPatchUnitTest, BlockDiffPatchGzFile_1, TestSize.Level1)
366 {
367     DiffPatchUnitTest test;
368     EXPECT_EQ(0, test.BlockDiffPatchTest2(
369         "../diffpatch/PatchGztest_old.gz",
370         "../diffpatch/PatchGztest_new.gz",
371         "../diffpatch/PatchGztest_gz.img_patch",
372         "../diffpatch/PatchGztest_gz_new.zip", false));
373 }
374 
375 HWTEST_F(DiffPatchUnitTest, BlockDiffPatchLz4File, TestSize.Level1)
376 {
377     DiffPatchUnitTest test;
378     EXPECT_EQ(0, test.BlockDiffPatchTest2(
379         "../diffpatch/PatchLz4test_old.lz4",
380         "../diffpatch/PatchLz4test_new.lz4",
381         "../diffpatch/PatchLz4test_lz4.img_patch",
382         "../diffpatch/PatchLz4test_lz4_new.lz", true));
383 }
384 
385 HWTEST_F(DiffPatchUnitTest, BlockDiffPatchLz4File_1, TestSize.Level1)
386 {
387     DiffPatchUnitTest test;
388     EXPECT_EQ(0, test.BlockDiffPatchTest2(
389         "../diffpatch/PatchLz4test_old.lz4",
390         "../diffpatch/PatchLz4test_new.lz4",
391         "../diffpatch/PatchLz4test_lz4.img_patch",
392         "../diffpatch/PatchLz4test_lz4_new.lz", false));
393 }
394 
395 HWTEST_F(DiffPatchUnitTest, BlockDiffPatchTest_0, TestSize.Level1)
396 {
397     DiffPatchUnitTest test;
398     EXPECT_EQ(0, test.BlockDiffPatchTest2(
399         "../diffpatch/patchtest.old",
400         "../diffpatch/patchtest.new",
401         "../diffpatch/patchtest.img_patch",
402         "../diffpatch/patchtest.new_2", true));
403 }
404 
405 HWTEST_F(DiffPatchUnitTest, BlockDiffPatchTest_1, TestSize.Level1)
406 {
407     DiffPatchUnitTest test;
408     EXPECT_EQ(0, test.BlockDiffPatchTest2(
409         "../diffpatch/patchtest.old",
410         "../diffpatch/patchtest.new",
411         "../diffpatch/patchtest.img_patch",
412         "../diffpatch/patchtest.new_2", false));
413 }
414 
415 HWTEST_F(DiffPatchUnitTest, BlockDiffPatchTest_2, TestSize.Level1)
416 {
417     std::vector<uint8_t> testDate;
418     testDate.push_back('a');
419     EXPECT_EQ(0, UpdatePatch::WriteDataToFile("BlockDiffPatchTest_2.txt", testDate, testDate.size()));
420 }
421 
422 HWTEST_F(DiffPatchUnitTest, PatchMapFileTest, TestSize.Level1)
423 {
424     UpdatePatch::MemMapInfo data{};
425     string filePath = TEST_PATH_FROM + "diffpatch/non_exist.file";
426     EXPECT_EQ(-1, UpdatePatch::PatchMapFile(filePath, data));
427 }
428 }
429