1 /*
2  * Copyright (c) 2024 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 <cstdio>
17 #include <fstream>
18 #include <ostream>
19 #include <string>
20 
21 #include "gtest/gtest.h"
22 #include "ecmascript/extractortool/src/zip_file.h"
23 #include "ecmascript/tests/test_helper.h"
24 #include "ecmascript/extractortool/src/zip_file_reader.h"
25 
26 using namespace panda::ecmascript;
27 namespace panda::ecmascript {
28 class ZipFileFriend {
29 public:
ZipFileFriend(const std::string &path)30     explicit ZipFileFriend(const std::string &path) : zipFile_(path)
31     {
32     }
33 
~ZipFileFriend()34     ~ZipFileFriend()
35     {
36         Close();
37     }
38 
SetContentLocation(ZipPos start, size_t length)39     void SetContentLocation(ZipPos start, size_t length)
40     {
41         zipFile_.SetContentLocation(start, length);
42     }
43 
CheckEndDir(EndDir &endDir) const44     bool CheckEndDir(EndDir &endDir) const
45     {
46         return zipFile_.CheckEndDir(endDir);
47     }
48 
ParseEndDirectory()49     bool ParseEndDirectory()
50     {
51         return zipFile_.ParseEndDirectory();
52     }
53 
ParseOneEntry(uint8_t *&entryPtr)54     bool ParseOneEntry(uint8_t *&entryPtr)
55     {
56         return zipFile_.ParseOneEntry(entryPtr);
57     }
58 
AddEntryToTree(const std::string &fileName)59     void AddEntryToTree(const std::string &fileName)
60     {
61         return zipFile_.AddEntryToTree(fileName);
62     }
63 
ParseAllEntries()64     bool ParseAllEntries()
65     {
66         return zipFile_.ParseAllEntries();
67     }
68 
Open()69     bool Open()
70     {
71         return zipFile_.Open();
72     }
73 
Close()74     void Close()
75     {
76         zipFile_.Close();
77     }
78 
IsDirExist(const std::string &dir) const79     bool IsDirExist(const std::string &dir) const
80     {
81         return zipFile_.IsDirExist(dir);
82     }
83 
GetAllFileList(const std::string &srcPath, std::vector<std::string> &assetList)84     void GetAllFileList(const std::string &srcPath, std::vector<std::string> &assetList)
85     {
86         zipFile_.GetAllFileList(srcPath, assetList);
87     }
88 
GetChildNames(const std::string &srcPath, std::set<std::string> &fileSet)89     void GetChildNames(const std::string &srcPath, std::set<std::string> &fileSet)
90     {
91         zipFile_.GetChildNames(srcPath, fileSet);
92     }
93 
GetEntry(const std::string &entryName, ZipEntry &resultEntry) const94     bool GetEntry(const std::string &entryName, ZipEntry &resultEntry) const
95     {
96         return zipFile_.GetEntry(entryName, resultEntry);
97     }
98 
CheckCoherencyLocalHeader(const ZipEntry &zipEntry, uint16_t &extraSize) const99     bool CheckCoherencyLocalHeader(const ZipEntry &zipEntry, uint16_t &extraSize) const
100     {
101         return zipFile_.CheckCoherencyLocalHeader(zipEntry, extraSize);
102     }
103 
CreateFileMapper(const std::string &fileName, FileMapperType type) const104     std::unique_ptr<FileMapper> CreateFileMapper(const std::string &fileName, FileMapperType type) const
105     {
106         return zipFile_.CreateFileMapper(fileName, type);
107     }
108 
ExtractToBufByName(const std::string &fileName, std::unique_ptr<uint8_t[]> &dataPtr, size_t &len) const109     bool ExtractToBufByName(const std::string &fileName, std::unique_ptr<uint8_t[]> &dataPtr, size_t &len) const
110     {
111         return zipFile_.ExtractToBufByName(fileName, dataPtr, len);
112     }
113 
SetIsOpen(bool isOpen)114     void SetIsOpen(bool isOpen)
115     {
116         zipFile_.isOpen_ = isOpen;
117     }
118 
GetFileStartPos() const119     ZipPos GetFileStartPos() const
120     {
121         return zipFile_.fileStartPos_;
122     }
123 
SetFileLength(ZipPos length)124     void SetFileLength(ZipPos length)
125     {
126         zipFile_.fileLength_ = length;
127     }
128 
GetFileLength() const129     ZipPos GetFileLength() const
130     {
131         return zipFile_.fileLength_;
132     }
133 
GetPathName() const134     const std::string &GetPathName() const
135     {
136         return zipFile_.pathName_;
137     }
138 
SetPathName(const std::string &newPathName)139     void SetPathName(const std::string &newPathName)
140     {
141         zipFile_.pathName_ = newPathName;
142     }
143 
GetZipFileReader() const144     std::shared_ptr<ZipFileReader> GetZipFileReader() const
145     {
146         return zipFile_.zipFileReader_;
147     }
148 
SetZipFileReader(const std::shared_ptr<ZipFileReader> &newZipFileReader)149     void SetZipFileReader(const std::shared_ptr<ZipFileReader> &newZipFileReader)
150     {
151         zipFile_.zipFileReader_ = newZipFileReader;
152     }
153 
154 private:
155     ZipFile zipFile_;
156 };
157 }
158 
159 namespace panda::test {
160 class ZipFileTest : public testing::Test {
161 public:
SetUpTestCase()162     static void SetUpTestCase()
163     {
164         GTEST_LOG_(INFO) << "SetUpTestCase";
165     }
166 
TearDownTestCase()167     static void TearDownTestCase()
168     {
169         GTEST_LOG_(INFO) << "TearDownCase";
170     }
171 
172     void SetUp() override
173     {
174         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
175         instance->SetEnableForceGC(false);
176     }
177 
178     void TearDown() override
179     {
180         TestHelper::DestroyEcmaVMWithScope(instance, scope);
181     }
182 
183     EcmaVM *instance{nullptr};
184     EcmaHandleScope *scope{nullptr};
185     JSThread *thread{nullptr};
186 };
187 
CreateTestFile()188 int CreateTestFile()
189 {
190     const std::string fileName = "TestFile.zip";
191     std::ofstream file(fileName);
192     if (!file.is_open()) {
193         return 1;
194     }
195     file << "This is a test file." << std::endl;
196     file.close();
197     if (!file) {
198         return 1;
199     }
200     return 0;
201 }
202 
DeleteTestFile()203 int DeleteTestFile()
204 {
205     const char *fileName = "TestFile.zip";
206     if (std::remove(fileName) != 0) {
207         return 1;
208     }
209     return 0;
210 }
211 
HWTEST_F_L0(ZipFileTest, SetContentLocationTest)212 HWTEST_F_L0(ZipFileTest, SetContentLocationTest)
213 {
214     std::string pathName = "path/to/zip.hap";
215     ZipFileFriend zipFileFriend(pathName);
216     zipFileFriend.SetIsOpen(true);
217     zipFileFriend.SetContentLocation(1, 1);
218     EXPECT_EQ(zipFileFriend.GetFileStartPos(), 0);
219     EXPECT_EQ(zipFileFriend.GetFileLength(), 0);
220 
221     zipFileFriend.SetIsOpen(false);
222     zipFileFriend.SetContentLocation(1, 1);
223     EXPECT_EQ(zipFileFriend.GetFileStartPos(), 1);
224     EXPECT_EQ(zipFileFriend.GetFileLength(), 1);
225 }
226 
HWTEST_F_L0(ZipFileTest, CheckEndDirTest)227 HWTEST_F_L0(ZipFileTest, CheckEndDirTest)
228 {
229     std::string pathName = "path/to/zip.hap";
230     ZipFileFriend zipFileFriend(pathName);
231     EndDir endDir;
232     EXPECT_FALSE(zipFileFriend.CheckEndDir(endDir));
233 
234     zipFileFriend.SetFileLength(100);
235     EndDir endDir2;
236     endDir2.signature = 0x06054b50;
237     endDir2.numDisk = 0;
238     endDir2.startDiskOfCentralDir = 0;
239     endDir2.totalEntriesInThisDisk = 1;
240     endDir2.totalEntries = 1;
241     endDir2.sizeOfCentralDir = 78;
242     endDir2.offset = 0;
243     endDir2.commentLen = 0;
244 
245     EXPECT_TRUE(zipFileFriend.CheckEndDir(endDir2));
246 }
247 
HWTEST_F_L0(ZipFileTest, ParseEndDirectoryTest)248 HWTEST_F_L0(ZipFileTest, ParseEndDirectoryTest)
249 {
250     std::string pathName = "path/to/zip.hap";
251     ZipFileFriend zipFileFriend(pathName);
252     zipFileFriend.SetFileLength(22);
253     EXPECT_FALSE(zipFileFriend.ParseEndDirectory());
254 }
255 
HWTEST_F_L0(ZipFileTest, OpenTest)256 HWTEST_F_L0(ZipFileTest, OpenTest)
257 {
258     std::string pathName = "test_files/long_path_name.txt";
259     ZipFileFriend zipFileFriend(pathName);
260     zipFileFriend.SetIsOpen(true);
261     EXPECT_TRUE(zipFileFriend.Open());
262 
263     zipFileFriend.SetIsOpen(false);
264     std::string longPathName(4097, 'a');
265     zipFileFriend.SetPathName(longPathName);
266     EXPECT_FALSE(zipFileFriend.Open());
267 }
268 
HWTEST_F_L0(ZipFileTest, CloseTest)269 HWTEST_F_L0(ZipFileTest, CloseTest)
270 {
271     std::string pathName = "zipFileTest.zip";
272     ZipFileFriend zipFileFriend(pathName);
273     zipFileFriend.Close();
274     EXPECT_EQ(zipFileFriend.GetPathName(), "zipFileTest.zip");
275 
276     EXPECT_EQ(CreateTestFile(), 0);
277     std::shared_ptr<ZipFileReader> zipFileReader = ZipFileReader::CreateZipFileReader(pathName);
278     zipFileFriend.SetZipFileReader(zipFileReader);
279     EXPECT_EQ(DeleteTestFile(), 0);
280     zipFileFriend.Close();
281 }
282 
HWTEST_F_L0(ZipFileTest, IsDirExistTest)283 HWTEST_F_L0(ZipFileTest, IsDirExistTest)
284 {
285     std::string pathName = "zipFileTest.zip";
286     ZipFileFriend zipFileFriend(pathName);
287     EXPECT_FALSE(zipFileFriend.IsDirExist(""));
288     std::string dir = ".";
289     EXPECT_FALSE(zipFileFriend.IsDirExist(dir));
290     dir = "path/to/nonexistent";
291     EXPECT_FALSE(zipFileFriend.IsDirExist(dir));
292     dir = "/";
293     EXPECT_TRUE(zipFileFriend.IsDirExist(dir));
294 }
295 
HWTEST_F_L0(ZipFileTest, GetAllFileListTest)296 HWTEST_F_L0(ZipFileTest, GetAllFileListTest)
297 {
298     std::string pathName = "zipFileTest.zip";
299     ZipFileFriend zipFileFriend(pathName);
300     std::vector<std::string> assetList;
301     zipFileFriend.GetAllFileList("", assetList);
302     EXPECT_TRUE(assetList.empty());
303 
304     assetList.clear();
305     zipFileFriend.GetAllFileList(".", assetList);
306     EXPECT_TRUE(assetList.empty());
307 
308     assetList.clear();
309     zipFileFriend.GetAllFileList("./", assetList);
310     EXPECT_TRUE(assetList.empty());
311 
312     assetList.clear();
313     zipFileFriend.GetAllFileList("path/to/nonexistent", assetList);
314     EXPECT_TRUE(assetList.empty());
315 }
316 
HWTEST_F_L0(ZipFileTest, GetChildNamesTest)317 HWTEST_F_L0(ZipFileTest, GetChildNamesTest)
318 {
319     std::string pathName = "zipFileTest.zip";
320     ZipFileFriend zipFileFriend(pathName);
321     std::set<std::string> fileSet;
322 
323     zipFileFriend.GetChildNames("", fileSet);
324     EXPECT_TRUE(fileSet.empty());
325 
326     fileSet.clear();
327     zipFileFriend.GetChildNames("/", fileSet);
328     EXPECT_TRUE(fileSet.empty());
329 
330     fileSet.clear();
331     zipFileFriend.GetChildNames(".", fileSet);
332     EXPECT_TRUE(fileSet.empty());
333 
334     fileSet.clear();
335     zipFileFriend.GetChildNames(".", fileSet);
336     EXPECT_TRUE(fileSet.empty());
337 
338     fileSet.clear();
339     zipFileFriend.GetChildNames("path/to/nonexistent", fileSet);
340     EXPECT_TRUE(fileSet.empty());
341 }
342 
HWTEST_F_L0(ZipFileTest, GetEntryTest)343 HWTEST_F_L0(ZipFileTest, GetEntryTest)
344 {
345     std::string pathName = "zipFileTest.zip";
346     ZipFileFriend zipFileFriend(pathName);
347     ZipEntry resultEntry;
348     std::string nonExistingEntryName = "nonExistingEntry";
349     EXPECT_FALSE(zipFileFriend.GetEntry(nonExistingEntryName, resultEntry));
350 }
351 
HWTEST_F_L0(ZipFileTest, CheckCoherencyLocalHeaderTest)352 HWTEST_F_L0(ZipFileTest, CheckCoherencyLocalHeaderTest)
353 {
354     std::string pathName = "zipFileTest.zip";
355     ZipFileFriend zipFileFriend(pathName);
356     ZipEntry zipEntry;
357     uint16_t extraSize;
358     size_t fileStartPos_;
359     fileStartPos_ = 0;
360     zipEntry.compressionMethod = 8;
361     zipEntry.localHeaderOffset = 0;
362     zipEntry.fileName = "testFile.txt";
363     zipEntry.compressionMethod = 9;
364     EXPECT_FALSE(zipFileFriend.CheckCoherencyLocalHeader(zipEntry, extraSize));
365     zipEntry.fileName = std::string(4096, 'a');
366     EXPECT_FALSE(zipFileFriend.CheckCoherencyLocalHeader(zipEntry, extraSize));
367     zipEntry.fileName = "differentName.txt";
368     EXPECT_FALSE(zipFileFriend.CheckCoherencyLocalHeader(zipEntry, extraSize));
369 }
370 }