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#ifndef PKG_TEST
17#define PKG_TEST
18
19#include <cstring>
20#include <fcntl.h>
21#include <gtest/gtest.h>
22#include <iostream>
23#include <sys/mman.h>
24#include <sys/stat.h>
25#include <unistd.h>
26#include "log.h"
27#include "pkg_algorithm.h"
28#include "pkg_manager.h"
29#include "pkg_manager_impl.h"
30#include "pkg_utils.h"
31#include "unittest_comm.h"
32#include "utils.h"
33
34using Hpackage::PkgManager;
35using Hpackage::PkgManagerImpl;
36using Hpackage::PkgStream;
37using Hpackage::PkgAlgorithmFactory;
38using Hpackage::DigestAlgorithm;
39using Hpackage::ComponentInfo;
40using Hpackage::FileInfo;
41using Hpackage::ZipFileInfo;
42using Hpackage::PkgInfo;
43using Updater::InitUpdaterLogger;
44
45namespace UpdaterUt {
46class PkgTest : public ::testing::Test {
47public:
48    PkgTest()
49    {
50        pkgManager_ = static_cast<PkgManagerImpl*>(PkgManager::CreatePackageInstance());
51    }
52    virtual ~PkgTest()
53    {
54        PkgManager::ReleasePackageInstance(pkgManager_);
55        pkgManager_ = nullptr;
56    }
57
58protected:
59    void SetUp()
60    {
61        // 先创建目标目录
62        if (access(TEST_PATH_TO.c_str(), R_OK | W_OK) == -1) {
63            mkdir(TEST_PATH_TO.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
64        }
65        InitUpdaterLogger("UPDATER ", "updater_log.log", "updater_status.log", "error_code.log");
66    }
67    void TearDown() {}
68    void TestBody() {}
69
70    int32_t BuildFileDigest(uint8_t &digest, size_t size, const std::string &packagePath)
71    {
72        PkgManager::StreamPtr stream = nullptr;
73        int32_t ret = pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read);
74        if (ret != 0) {
75            PKG_LOGE("Create input stream fail %s", packagePath.c_str());
76            return ret;
77        }
78        size_t fileLen = stream->GetFileLength();
79        if (fileLen <= 0 || fileLen > SIZE_MAX) {
80            PKG_LOGE("Invalid file len %zu to load %s", fileLen, stream->GetFileName().c_str());
81            pkgManager_->ClosePkgStream(stream);
82            return -1;
83        }
84
85        size_t buffSize = 4096;
86        Hpackage::PkgBuffer buff(buffSize);
87        // 整包检查
88        DigestAlgorithm::DigestAlgorithmPtr algorithm =
89            PkgAlgorithmFactory::GetDigestAlgorithm(PKG_DIGEST_TYPE_SHA256);
90        if (algorithm == nullptr) {
91            PKG_LOGE("Invalid file %s", stream->GetFileName().c_str());
92            pkgManager_->ClosePkgStream(stream);
93            return -1;
94        }
95        algorithm->Init();
96
97        size_t offset = 0;
98        size_t readLen = 0;
99        while (offset < fileLen) {
100            ret = stream->Read(buff, offset, buffSize, readLen);
101            if (ret != 0) {
102                PKG_LOGE("read buffer fail %s", stream->GetFileName().c_str());
103                pkgManager_->ClosePkgStream(stream);
104                return ret;
105            }
106            algorithm->Update(buff, readLen);
107
108            offset += readLen;
109            readLen = 0;
110        }
111        Hpackage::PkgBuffer buffer(&digest, size);
112        algorithm->Final(buffer);
113        pkgManager_->ClosePkgStream(stream);
114        return 0;
115    }
116
117    void ExtractFile(PkgManager::PkgManagerPtr manager, std::vector<std::string> components, size_t i)
118    {
119        PkgManager::StreamPtr outStream = nullptr;
120        PKG_LOGI("comp [%zu] file name: %s \r\n", i, (TEST_PATH_TO + components[i]).c_str());
121        manager->CreatePkgStream(outStream, TEST_PATH_TO + components[i], 0, PkgStream::PkgStreamType_Write);
122        EXPECT_NE(nullptr, outStream);
123        if (outStream == nullptr) {
124            return;
125        }
126        int ret = manager->ExtractFile(components[i], outStream);
127        EXPECT_EQ(ret, 0);
128        manager->ClosePkgStream(outStream);
129        const FileInfo *info = manager->GetFileInfo(components[i]);
130        ASSERT_NE(info, nullptr);
131        if (info->packMethod == PKG_COMPRESS_METHOD_NONE) {
132            const ComponentInfo* compInfo = (const ComponentInfo*)manager->GetFileInfo(components[i]);
133            if (compInfo != nullptr) {
134                PKG_LOGI("comp [%zu] componentAddr: %s \n", i, (*compInfo).fileInfo.identity.c_str());
135                PKG_LOGI("comp [%zu] version: %s \n", i, (*compInfo).version.c_str());
136                PKG_LOGI("comp [%zu] originalSize: %zu \n", i, (*compInfo).originalSize);
137                PKG_LOGI("comp [%zu] size: %zu \n", i, (*compInfo).fileInfo.unpackedSize);
138                PKG_LOGI("comp [%zu] id: %d \n", i, (*compInfo).id);
139                PKG_LOGI("comp [%zu] resType: %d \n", i, (*compInfo).resType);
140                PKG_LOGI("comp [%zu] flags: %d \n", i, (*compInfo).compFlags);
141                PKG_LOGI("comp [%zu] type: %d \n", i, (*compInfo).type);
142            }
143        } else {
144            PKG_LOGI("FileInfo [%zu] id: %s \n", i, info->identity.c_str());
145            PKG_LOGI("FileInfo [%zu] unpackedSize: %zu \n", i, info->unpackedSize);
146            PKG_LOGI("FileInfo [%zu] packedSize: %zu \n", i, info->packedSize);
147            PKG_LOGI("FileInfo [%zu] packMethod: %d \n", i, info->packMethod);
148            PKG_LOGI("FileInfo [%zu] digestMethod: %d \n", i, info->digestMethod);
149            PKG_LOGI("FileInfo [%zu] flags: %d \n", i, info->flags);
150        }
151    }
152
153    int CreateZipPackage(const std::vector<std::string> &testFileNames,
154        const std::string packageName, const std::string &base, int digestMethod)
155    {
156        PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance();
157        EXPECT_NE(pkgManager, nullptr);
158        std::vector<std::pair<std::string, ZipFileInfo>> files;
159        // 构建要打包的zip文件
160        for (auto name : testFileNames) {
161            ZipFileInfo file;
162            file.fileInfo.identity = name;
163            file.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP;
164            file.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC;
165            std::string fileName = base + name;
166            files.push_back(std::pair<std::string, ZipFileInfo>(fileName, file));
167        }
168
169        PkgInfo pkgInfo;
170        pkgInfo.signMethod = PKG_SIGN_METHOD_RSA;
171        pkgInfo.digestMethod = digestMethod;
172        pkgInfo.pkgType = PKG_PACK_TYPE_ZIP;
173        int32_t ret = pkgManager->CreatePackage(packageName, GetTestPrivateKeyName(digestMethod), &pkgInfo, files);
174        EXPECT_EQ(ret, 0);
175        PkgManager::ReleasePackageInstance(pkgManager);
176        return ret;
177    }
178    std::vector<std::string> testFileNames_ = {
179        "loadScript.us",
180        "registerCmd.us",
181        "test_function.us",
182        "test_if.us",
183        "test_logic.us",
184        "test_math.us",
185        "test_native.us",
186        "testscript.us",
187        "Verse-script.us",
188        "libcrypto.a",
189        "ggg.zip"
190    };
191    PkgManagerImpl* pkgManager_ = nullptr;
192    std::string testPackageName = "test_package.bin";
193    std::string testZipPackageName = "test_package.zip";
194    std::string testLz4PackageName = "test_package.lz4";
195    std::string testGZipPackageName = "test_package.gz";
196    std::string testCombinePkgName = "test_CombinePackage.zip";
197    std::string testPackagePath = "/data/updater/package/";
198};
199}
200#endif // PKG_TEST
201