• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <fstream>
17 #include <gtest/gtest.h>
18 
19 #include "db_errno.h"
20 #include "distributeddb_tools_unit_test.h"
21 #include "package_file.h"
22 #include "platform_specific.h"
23 #include "securec.h"
24 #include "value_hash_calc.h"
25 
26 using namespace testing::ext;
27 using namespace DistributedDB;
28 using namespace DistributedDBUnitTest;
29 using namespace std;
30 
31 namespace {
32     string g_testPath;
33     string g_sourcePath = "/source/";
34     string g_packageResultPath = "/package_result/";
35     string g_unpackResultPath = "/unpack_result/";
36     FileInfo g_fileInfo;
37     const string PACKAGE_RESULT_FILE_NAME = "package_result.dat";
38     const string NON_EXIST_PATH = "/nonexist/";
39     const string FILE_NAME_1 = "file1.txt";
40     const string FILE_NAME_2 = "file2.dat";
41     const string FILE_CONTENT_1 = "Hello world.";
42     const string NON_EXIST_FILE = "nonexist.dat";
43     const string EMPTY_FILE = "empty.dat";
44     const string SECURE_FILE = "secure.dat";
45     const int FILE_CONTENT_2_LEN = 4;
46     const char FILE_CONTENT_2[FILE_CONTENT_2_LEN] = {0x5B, 0x3A, 0x29, 0x3E};
47     const int BUFFER_SIZE = 4096;
48     const int DEVICE_ID_LEN = 32;
49     const vector<uint8_t> DIVICE_ID = {'a', 'e', 'i', 'o', 'u'};
50 
RemovePath(const string & path)51     void RemovePath(const string &path)
52     {
53         list<OS::FileAttr> files;
54         int errCode = OS::GetFileAttrFromPath(path, files);
55         ASSERT_EQ(errCode, E_OK);
56         for (auto file : files) {
57             string fileName = path + "/" + file.fileName;
58             switch (file.fileType) {
59                 case OS::FILE:
60                     (void)remove(fileName.c_str());
61                     break;
62                 case OS::PATH:
63                     if (file.fileName != "." && file.fileName != "..") {
64                         RemovePath(fileName);
65                     }
66                     break;
67                 default:
68                     break;
69             }
70         }
71         (void)OS::RemoveDBDirectory(path);
72     }
73 
CompareFileName(const OS::FileAttr & file1,const OS::FileAttr & file2)74     bool CompareFileName(const OS::FileAttr &file1, const OS::FileAttr &file2)
75     {
76         return file1.fileName <= file2.fileName;
77     }
78 
ComparePath(const string & path1,const string & path2)79     void ComparePath(const string &path1, const string &path2)
80     {
81         list<OS::FileAttr> files1;
82         int errCode = OS::GetFileAttrFromPath(path1, files1);
83         ASSERT_EQ(errCode, E_OK);
84         files1.sort(CompareFileName);
85         list<OS::FileAttr> files2;
86         errCode = OS::GetFileAttrFromPath(path2, files2);
87         ASSERT_EQ(errCode, E_OK);
88         files2.sort(CompareFileName);
89         ASSERT_EQ(files1.size(), files2.size());
90         auto fileIter1 = files1.begin();
91         auto fileIter2 = files2.begin();
92         vector<char> buffer1(BUFFER_SIZE, 0);
93         vector<char> buffer2(BUFFER_SIZE, 0);
94         string bufferStr1;
95         string bufferStr2;
96         for (; fileIter1 != files1.end() && fileIter2 != files2.end(); fileIter1++, fileIter2++) {
97             ASSERT_STREQ(fileIter1->fileName.c_str(), fileIter2->fileName.c_str());
98             ASSERT_EQ(fileIter1->fileType, fileIter2->fileType);
99             ASSERT_EQ(fileIter1->fileLen, fileIter2->fileLen);
100             if (fileIter1->fileType != OS::FILE) {
101                 continue;
102             }
103             ifstream file1(path1 + fileIter1->fileName, ios::out | ios::binary);
104             ASSERT_TRUE(file1.is_open());
105             ifstream file2(path2 + fileIter2->fileName, ios::out | ios::binary);
106             ASSERT_TRUE(file2.is_open());
107             buffer1.assign(BUFFER_SIZE, 0);
108             buffer2.assign(BUFFER_SIZE, 0);
109             for (file1.read(buffer1.data(), BUFFER_SIZE), file2.read(buffer2.data(), BUFFER_SIZE);
110                 !(file1.eof() || file2.eof());
111                 file1.read(buffer1.data(), BUFFER_SIZE), file2.read(buffer2.data(), BUFFER_SIZE)) {
112                 bufferStr1.assign(buffer1.begin(), buffer1.end());
113                 bufferStr2.assign(buffer2.begin(), buffer2.end());
114                 ASSERT_STREQ(bufferStr1.c_str(), bufferStr2.c_str());
115             }
116             file1.close();
117             file2.close();
118             bufferStr1.assign(buffer1.begin(), buffer1.end());
119             bufferStr2.assign(buffer2.begin(), buffer2.end());
120             ASSERT_STREQ(bufferStr1.c_str(), bufferStr2.c_str());
121         }
122     }
123 }
124 
125 class DistributedDBFilePackageTest : public testing::Test {
126 public:
127     static void SetUpTestCase(void);
128     static void TearDownTestCase(void);
129     void SetUp();
130     void TearDown();
131 };
132 
SetUpTestCase(void)133 void DistributedDBFilePackageTest::SetUpTestCase(void)
134 {
135     DistributedDBToolsUnitTest::TestDirInit(g_testPath);
136     g_sourcePath = g_testPath + g_sourcePath;
137     g_packageResultPath = g_testPath + g_packageResultPath;
138     g_unpackResultPath = g_testPath + g_unpackResultPath;
139     (void)OS::MakeDBDirectory(g_sourcePath);
140     ofstream file1(g_sourcePath + FILE_NAME_1, ios::out | ios::binary | ios::trunc);
141     ASSERT_TRUE(file1.is_open());
142     file1.write(FILE_CONTENT_1.c_str(), FILE_CONTENT_1.size());
143     file1.close();
144     ofstream file2(g_sourcePath + FILE_NAME_2, ios::out | ios::binary | ios::trunc);
145     ASSERT_TRUE(file2.is_open());
146     file2.write(FILE_CONTENT_2, FILE_CONTENT_2_LEN);
147     file2.close();
148     g_fileInfo.dbType = 1;
149     ValueHashCalc calc;
150     int errCode = calc.Initialize();
151     ASSERT_EQ(errCode, E_OK);
152     errCode = calc.Update(DIVICE_ID);
153     ASSERT_EQ(errCode, E_OK);
154     vector<uint8_t> deviceIDVec;
155     errCode = calc.GetResult(deviceIDVec);
156     ASSERT_EQ(errCode, E_OK);
157     g_fileInfo.deviceID.resize(DEVICE_ID_LEN);
158     g_fileInfo.deviceID.assign(deviceIDVec.begin(), deviceIDVec.end());
159 }
160 
TearDownTestCase(void)161 void DistributedDBFilePackageTest::TearDownTestCase(void)
162 {
163     RemovePath(g_testPath);
164 }
165 
SetUp(void)166 void DistributedDBFilePackageTest::SetUp(void)
167 {
168     DistributedDBToolsUnitTest::PrintTestCaseInfo();
169     (void)OS::MakeDBDirectory(g_packageResultPath);
170     (void)OS::MakeDBDirectory(g_unpackResultPath);
171 }
172 
TearDown(void)173 void DistributedDBFilePackageTest::TearDown(void)
174 {
175     RemovePath(g_packageResultPath);
176     RemovePath(g_unpackResultPath);
177 }
178 
179 /**
180   * @tc.name: PackageFileTest001
181   * @tc.desc: Test file package and unpack functions.
182   * @tc.type: FUNC
183   * @tc.require:
184   * @tc.author: liujialei
185   */
186 HWTEST_F(DistributedDBFilePackageTest, PackageFileTest001, TestSize.Level0)
187 {
188     int errCode = PackageFile::PackageFiles(g_sourcePath, g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_fileInfo);
189     ASSERT_EQ(errCode, E_OK);
190     FileInfo fileInfo;
191     errCode = PackageFile::UnpackFile(g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_unpackResultPath, fileInfo);
192     ASSERT_EQ(errCode, E_OK);
193     ComparePath(g_sourcePath, g_unpackResultPath);
194     ASSERT_EQ(fileInfo.dbType, g_fileInfo.dbType);
195 }
196 
197 /**
198   * @tc.name: PackageFileTest002
199   * @tc.desc: Test file package if source path is not exist.
200   * @tc.type: FUNC
201   * @tc.require:
202   * @tc.author: liujialei
203   */
204 HWTEST_F(DistributedDBFilePackageTest, PackageFileTest002, TestSize.Level0)
205 {
206     int errCode = PackageFile::PackageFiles(g_sourcePath + NON_EXIST_PATH,
207         g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_fileInfo);
208     ASSERT_EQ(errCode, -E_INVALID_PATH);
209 }
210 
211 /**
212   * @tc.name: PackageFileTest003
213   * @tc.desc: Test file package if result path is not exist.
214   * @tc.type: FUNC
215   * @tc.require:
216   * @tc.author: liujialei
217   */
218 HWTEST_F(DistributedDBFilePackageTest, PackageFileTest003, TestSize.Level0)
219 {
220     int errCode = PackageFile::PackageFiles(g_sourcePath,
221         g_packageResultPath + NON_EXIST_PATH + PACKAGE_RESULT_FILE_NAME, g_fileInfo);
222     ASSERT_EQ(errCode, -E_INVALID_PATH);
223 }
224 
225 /**
226   * @tc.name: PackageFileTest004
227   * @tc.desc: Test file package if source path is empty.
228   * @tc.type: FUNC
229   * @tc.require:
230   * @tc.author: liujialei
231   */
232 HWTEST_F(DistributedDBFilePackageTest, PackageFileTest004, TestSize.Level0)
233 {
234     // Clear source files.
235     RemovePath(g_sourcePath);
236     (void)OS::MakeDBDirectory(g_sourcePath);
237     // Test function.
238     int errCode = PackageFile::PackageFiles(g_sourcePath, g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_fileInfo);
239     ASSERT_EQ(errCode, -E_EMPTY_PATH);
240     // Create source files again.
241     ofstream file1(g_sourcePath + FILE_NAME_1, ios::out | ios::binary | ios::trunc);
242     ASSERT_TRUE(file1.is_open());
243     file1.write(FILE_CONTENT_1.c_str(), FILE_CONTENT_1.size());
244     file1.close();
245     ofstream file2(g_sourcePath + FILE_NAME_2, ios::out | ios::binary | ios::trunc);
246     ASSERT_TRUE(file2.is_open());
247     file2.write(FILE_CONTENT_2, 4);
248     file2.close();
249 }
250 
251 /**
252   * @tc.name: PackageFileTest005
253   * @tc.desc: Test file unpack if source file is not exist.
254   * @tc.type: FUNC
255   * @tc.require:
256   * @tc.author: liujialei
257   */
258 HWTEST_F(DistributedDBFilePackageTest, PackageFileTest005, TestSize.Level0)
259 {
260     FileInfo fileInfo;
261     int errCode = PackageFile::UnpackFile(g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_unpackResultPath, fileInfo);
262     ASSERT_EQ(errCode, -E_INVALID_PATH);
263 }
264 
265 /**
266   * @tc.name: PackageFileTest006
267   * @tc.desc: Test file unpack if result path is not exist.
268   * @tc.type: FUNC
269   * @tc.require:
270   * @tc.author: liujialei
271   */
272 HWTEST_F(DistributedDBFilePackageTest, PackageFileTest006, TestSize.Level0)
273 {
274     int errCode = PackageFile::PackageFiles(g_sourcePath, g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_fileInfo);
275     ASSERT_EQ(errCode, E_OK);
276     FileInfo fileInfo;
277     errCode = PackageFile::UnpackFile(g_packageResultPath + PACKAGE_RESULT_FILE_NAME,
278         g_unpackResultPath + NON_EXIST_PATH, fileInfo);
279     ASSERT_EQ(errCode, -E_INVALID_PATH);
280 }
281 
282 /**
283   * @tc.name: PackageFileTest007
284   * @tc.desc: Test file unpack if magic check failed.
285   * @tc.type: FUNC
286   * @tc.require:
287   * @tc.author: liujialei
288   */
289 HWTEST_F(DistributedDBFilePackageTest, PackageFileTest007, TestSize.Level0)
290 {
291     int errCode = PackageFile::PackageFiles(g_sourcePath, g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_fileInfo);
292     ASSERT_EQ(errCode, E_OK);
293     // Change package file header.
294     const string REPLACE_FILE_HEADER = "test";
295     fstream file(g_packageResultPath + PACKAGE_RESULT_FILE_NAME, ios::in | ios::out | ios::binary);
296     ASSERT_TRUE(file.is_open());
297     file.seekp(0, ios_base::beg);
298     file.write(REPLACE_FILE_HEADER.c_str(), REPLACE_FILE_HEADER.size());
299     file.close();
300     // Unpack file.
301     FileInfo fileInfo;
302     errCode = PackageFile::UnpackFile(g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_unpackResultPath, fileInfo);
303     ASSERT_EQ(errCode, -E_INVALID_FILE);
304 }
305 
306 /**
307   * @tc.name: PackageFileTest008
308   * @tc.desc: Test file unpack if checksum check failed.
309   * @tc.type: FUNC
310   * @tc.require:
311   * @tc.author: liujialei
312   */
313 HWTEST_F(DistributedDBFilePackageTest, PackageFileTest008, TestSize.Level0)
314 {
315     int errCode = PackageFile::PackageFiles(g_sourcePath, g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_fileInfo);
316     ASSERT_EQ(errCode, E_OK);
317     // Rewrite package file without file tail.
318     ifstream fileIn(g_packageResultPath + PACKAGE_RESULT_FILE_NAME, ios::in | ios::binary);
319     ASSERT_TRUE(fileIn.is_open());
320     fileIn.seekg(0, ios_base::end);
321     int fileLen = fileIn.tellg();
322     fileIn.seekg(0, ios_base::beg);
323     const int CUT_TAIL = 3;
324     int bufferLen = fileLen > BUFFER_SIZE ? BUFFER_SIZE : fileLen - CUT_TAIL;
325     vector<char> buffer(bufferLen, 0);
326     fileIn.read(buffer.data(), buffer.size());
327     fileIn.close();
328     ofstream fileOut(g_packageResultPath + PACKAGE_RESULT_FILE_NAME, ios::out | ios::binary | ios::trunc);
329     ASSERT_TRUE(fileOut.is_open());
330     fileOut.write(buffer.data(), buffer.size());
331     fileOut.close();
332     // Unpack file.
333     FileInfo fileInfo;
334     errCode = PackageFile::UnpackFile(g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_unpackResultPath, fileInfo);
335     ASSERT_EQ(errCode, -E_INVALID_FILE);
336 }
337 
338 /**
339   * @tc.name: GetPackageVersionTest001
340   * @tc.desc: Test GetPackageVersion func.
341   * @tc.type: FUNC
342   * @tc.require:
343   * @tc.author: tiansimiao
344   */
345 HWTEST_F(DistributedDBFilePackageTest, GetPackageVersionTest001, TestSize.Level0)
346 {
347     uint32_t version;
348     std::ofstream emptyFile(g_packageResultPath + EMPTY_FILE, ios::out | ios::binary | ios::trunc);
349     ASSERT_TRUE(emptyFile.is_open());
350     emptyFile.close();
351     std::ofstream secureFile(g_packageResultPath + SECURE_FILE, ios::out | ios::binary | ios::trunc);
352     ASSERT_TRUE(secureFile.is_open());
353     secureFile.close();
354     EXPECT_EQ(chmod((g_packageResultPath + SECURE_FILE).c_str(), S_IRUSR | S_IRGRP | S_IROTH), E_OK);
355     int errCode = PackageFile::GetPackageVersion(g_packageResultPath + NON_EXIST_FILE, version);
356     EXPECT_EQ(errCode, -E_INVALID_PATH);
357     errCode = PackageFile::GetPackageVersion(g_packageResultPath + EMPTY_FILE, version);
358     EXPECT_EQ(errCode, -E_INVALID_PATH);
359     int oldErr = errno;
360     errno = EKEYREVOKED;
361     errCode = PackageFile::GetPackageVersion(g_packageResultPath + SECURE_FILE, version);
362     EXPECT_EQ(errCode, -E_EKEYREVOKED);
363     errno = oldErr;
364 }