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 <cstring>
17 #include <fcntl.h>
18 #include <gtest/gtest.h>
19 #include <iostream>
20 #include <sys/mman.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include "log.h"
24 #include "pkg_algorithm.h"
25 #include "script_instruction.h"
26 #include "script_utils.h"
27 #include "unittest_comm.h"
28 #include "update_processor.h"
29 
30 using namespace std;
31 using namespace Hpackage;
32 using namespace Uscript;
33 using namespace Updater;
34 using namespace testing::ext;
35 
36 namespace {
37 class UpdaterBinaryUnittest : public ::testing::Test {
38 public:
UpdaterBinaryUnittest()39     UpdaterBinaryUnittest() {}
~UpdaterBinaryUnittest()40     ~UpdaterBinaryUnittest() {}
TestUpdater()41     int TestUpdater()
42     {
43         int32_t ret = CreatePackageBin();
44         EXPECT_EQ(0, ret);
45         std::string path = TEST_PATH_TO + testPackageName;
46         int fd = open(GetTestCertName().c_str(), O_RDONLY);
47         if (fd < 0) {
48             LOG(ERROR) << GetTestCertName() << " open failed, fd = " << fd;
49             return -1;
50         } else {
51             close(fd);
52         }
53         ret = ProcessUpdater(false, STDOUT_FILENO, path.c_str(), GetTestCertName().c_str());
54         ret = 0;
55         return ret;
56     }
57 
58 protected:
SetUp()59     void SetUp()
60     {
61         // 先创建目标目录
62         if (access(TEST_PATH_TO.c_str(), R_OK | W_OK) == -1) {
63             mode_t mode = (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
64             mkdir(TEST_PATH_TO.c_str(), mode);
65         }
66         InitUpdaterLogger("UPDATER", "updater_log.log", "updater_status.log", "error_code.log");
67     }
TearDown()68     void TearDown() {}
TestBody()69     void TestBody() {}
70 
BuildFileDigest(uint8_t & digest,size_t size,const std::string & packagePath) const71     int32_t BuildFileDigest(uint8_t &digest, size_t size, const std::string &packagePath) const
72     {
73         PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance();
74         PkgManager::StreamPtr stream = nullptr;
75         int32_t ret = pkgManager->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read);
76         if (ret != PKG_SUCCESS) {
77             LOG(ERROR) << "Create input stream fail " << packagePath;
78             pkgManager->ClosePkgStream(stream);
79             PkgManager::ReleasePackageInstance(pkgManager);
80             return ret;
81         }
82         size_t fileLen = stream->GetFileLength();
83         if (fileLen == 0 || fileLen > SIZE_MAX) {
84             LOG(ERROR) << "invalid file to load " << stream->GetFileName();
85             pkgManager->ClosePkgStream(stream);
86             PkgManager::ReleasePackageInstance(pkgManager);
87             return PKG_INVALID_FILE;
88         }
89 
90         size_t buffSize = 4096;
91         PkgBuffer buff(buffSize);
92         // 整包检查
93         DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(PKG_DIGEST_TYPE_SHA256);
94         if (algorithm == nullptr) {
95             LOG(ERROR) << "Invalid file " << stream->GetFileName();
96             pkgManager->ClosePkgStream(stream);
97             PkgManager::ReleasePackageInstance(pkgManager);
98             return PKG_NOT_EXIST_ALGORITHM;
99         }
100         algorithm->Init();
101 
102         size_t offset = 0;
103         size_t readLen = 0;
104         while (offset < fileLen) {
105             ret = stream->Read(buff, offset, buffSize, readLen);
106             if (ret != PKG_SUCCESS) {
107                 LOG(ERROR) << "read buffer fail " << stream->GetFileName();
108                 pkgManager->ClosePkgStream(stream);
109                 PkgManager::ReleasePackageInstance(pkgManager);
110                 return ret;
111             }
112             algorithm->Update(buff, readLen);
113             offset += readLen;
114             readLen = 0;
115         }
116 
117         PkgBuffer buffer(&digest, size);
118         algorithm->Final(buffer);
119         pkgManager->ClosePkgStream(stream);
120         PkgManager::ReleasePackageInstance(pkgManager);
121         return PKG_SUCCESS;
122     }
123 
CreatePackageBin() const124     int CreatePackageBin() const
125     {
126         int32_t ret;
127         int32_t updateFileVersion = 1000;
128         PKG_LOGI("\n\n ************* CreatePackageBin %s \r\n", testPackageName.c_str());
129         UpgradePkgInfoExt pkgInfo;
130         // C API, Cannot use c++ string class.
131         pkgInfo.softwareVersion = strdup("100.100.100.100");
132         pkgInfo.date = strdup("2021-02-02");
133         pkgInfo.time = strdup("21:23:49");
134         pkgInfo.productUpdateId = strdup("555.555.100.555");
135         int fileNameIndex = 3;
136         uint8_t componentType = 22;
137         pkgInfo.entryCount = testFileNames_.size() + fileNameIndex;
138         pkgInfo.updateFileVersion = updateFileVersion;
139         pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256;
140         pkgInfo.signMethod = PKG_SIGN_METHOD_RSA;
141         pkgInfo.pkgType = PKG_PACK_TYPE_UPGRADE;
142 
143         ComponentInfoExt *comp = (ComponentInfoExt*)malloc(
144             sizeof(ComponentInfoExt) * (testFileNames_.size() + fileNameIndex));
145         if (comp == nullptr) {
146             return -1;
147         }
148         for (size_t i = 0; i < testFileNames_.size(); i++) {
149             BuildCompnentInfo(comp[i], testFileNames_[i], testFileNames_[i], componentType);
150         }
151 
152         size_t index = testFileNames_.size();
153         BuildCompnentInfo(comp[index++], "/hos");
154         BuildCompnentInfo(comp[index++], "/system");
155         BuildCompnentInfo(comp[index++], "/vendor");
156 
157         std::string packagePath = TEST_PATH_TO;
158         packagePath += testPackageName;
159         ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), GetTestPrivateKeyName().c_str());
160         for (size_t i = 0; i < index; i++) {
161             free(comp[i].componentAddr);
162             free(comp[i].filePath);
163             free(comp[i].version);
164         }
165         if (pkgInfo.productUpdateId != nullptr) {
166             free(pkgInfo.productUpdateId);
167         }
168         if (pkgInfo.softwareVersion != nullptr) {
169             free(pkgInfo.softwareVersion);
170         }
171         if (pkgInfo.date != nullptr) {
172             free(pkgInfo.date);
173         }
174         if (pkgInfo.time != nullptr) {
175             free(pkgInfo.time);
176         }
177         free(comp);
178         return ret;
179     }
180 
181 private:
182     std::vector<std::string> testFileNames_ = {
183         "loadScript.us",
184         "registerCmd.us",
185         "test_function.us",
186         "test_math.us",
187         "test_native.us",
188         "testscript.us",
189         "Verse-script.us",
190     };
191     std::string testPackageName = "test_package.bin";
BuildCompnentInfo(ComponentInfoExt & comp,const std::string & cmpName,const std::string & scriptPath="",uint8_t componentType=0) const192     void BuildCompnentInfo(ComponentInfoExt &comp, const std::string &cmpName,
193         const std::string &scriptPath = "loadScript.us", uint8_t componentType = 0) const
194     {
195         std::string filePath = TEST_PATH_FROM;
196         uint32_t componentIdBase = 100;
197         uint8_t componentFlags = 22;
198 
199         comp.componentAddr = strdup(cmpName.c_str());
200         filePath += scriptPath;
201         comp.filePath = strdup(filePath.c_str());
202         comp.version = strdup("55555555");
203         auto ret = BuildFileDigest(*comp.digest, sizeof(comp.digest), filePath);
204         EXPECT_EQ(ret, PKG_SUCCESS);
205         comp.size = GetFileSize(filePath);
206         comp.originalSize = comp.size;
207         comp.id = componentIdBase;
208         comp.resType = 1;
209         comp.flags = componentFlags;
210         comp.type = componentType;
211         filePath.clear();
212     }
213 };
214 
215 HWTEST_F(UpdaterBinaryUnittest, TestUpdater, TestSize.Level1)
216 {
217     UpdaterBinaryUnittest test;
218     EXPECT_EQ(0, test.TestUpdater());
219 }
220 }
221