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