1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci
16fb299fa2Sopenharmony_ci#include <climits>
17fb299fa2Sopenharmony_ci#include <cstring>
18fb299fa2Sopenharmony_ci#include <fcntl.h>
19fb299fa2Sopenharmony_ci#include <gtest/gtest.h>
20fb299fa2Sopenharmony_ci#include <iostream>
21fb299fa2Sopenharmony_ci#include <sys/mman.h>
22fb299fa2Sopenharmony_ci#include <sys/stat.h>
23fb299fa2Sopenharmony_ci#include <unistd.h>
24fb299fa2Sopenharmony_ci#include "hash_data_verifier.h"
25fb299fa2Sopenharmony_ci#include "log.h"
26fb299fa2Sopenharmony_ci#include "pkg_stream.h"
27fb299fa2Sopenharmony_ci#include "pkg_utils.h"
28fb299fa2Sopenharmony_ci#include "scope_guard.h"
29fb299fa2Sopenharmony_ci#include "script_instruction.h"
30fb299fa2Sopenharmony_ci#include "script_manager.h"
31fb299fa2Sopenharmony_ci#include "script/script_unittest.h"
32fb299fa2Sopenharmony_ci#include "script_utils.h"
33fb299fa2Sopenharmony_ci#include "unittest_comm.h"
34fb299fa2Sopenharmony_ci#include "utils.h"
35fb299fa2Sopenharmony_ci
36fb299fa2Sopenharmony_ciusing namespace std;
37fb299fa2Sopenharmony_ciusing namespace Hpackage;
38fb299fa2Sopenharmony_ciusing namespace Uscript;
39fb299fa2Sopenharmony_ciusing namespace Updater;
40fb299fa2Sopenharmony_ciusing namespace testing::ext;
41fb299fa2Sopenharmony_ci
42fb299fa2Sopenharmony_cinamespace {
43fb299fa2Sopenharmony_ciconstexpr int32_t SCRIPT_TEST_PRIORITY_NUM = 3;
44fb299fa2Sopenharmony_ciconstexpr int32_t SCRIPT_TEST_LAST_PRIORITY = 2;
45fb299fa2Sopenharmony_ci
46fb299fa2Sopenharmony_ciclass TestPkgManager : public TestScriptPkgManager {
47fb299fa2Sopenharmony_cipublic:
48fb299fa2Sopenharmony_ci    const FileInfo *GetFileInfo(const std::string &fileId) override
49fb299fa2Sopenharmony_ci    {
50fb299fa2Sopenharmony_ci        static FileInfo fileInfo {};
51fb299fa2Sopenharmony_ci        static std::vector<std::string> testFileNames = {
52fb299fa2Sopenharmony_ci            "loadScript.us",
53fb299fa2Sopenharmony_ci            "registerCmd.us",
54fb299fa2Sopenharmony_ci            "test_function.us",
55fb299fa2Sopenharmony_ci            "test_if.us",
56fb299fa2Sopenharmony_ci            "test_logic.us",
57fb299fa2Sopenharmony_ci            "test_math.us",
58fb299fa2Sopenharmony_ci            "test_native.us",
59fb299fa2Sopenharmony_ci            "testscript.us",
60fb299fa2Sopenharmony_ci            "Verse-script.us",
61fb299fa2Sopenharmony_ci            "test_script.us"
62fb299fa2Sopenharmony_ci        };
63fb299fa2Sopenharmony_ci        if (fileId == "hash_signed_data") {
64fb299fa2Sopenharmony_ci            fileInfo.unpackedSize = GetFileSize(TEST_PATH_FROM + fileId);
65fb299fa2Sopenharmony_ci            return &fileInfo;
66fb299fa2Sopenharmony_ci        }
67fb299fa2Sopenharmony_ci        if (std::find(testFileNames.begin(), testFileNames.end(), fileId) != testFileNames.end()) {
68fb299fa2Sopenharmony_ci            return &fileInfo;
69fb299fa2Sopenharmony_ci        }
70fb299fa2Sopenharmony_ci        return nullptr;
71fb299fa2Sopenharmony_ci    }
72fb299fa2Sopenharmony_ci    int32_t CreatePkgStream(StreamPtr &stream, const std::string &fileName, const PkgBuffer &buffer) override
73fb299fa2Sopenharmony_ci    {
74fb299fa2Sopenharmony_ci        stream = new MemoryMapStream(this, fileName, buffer, PkgStream::PkgStreamType_Buffer);
75fb299fa2Sopenharmony_ci        return PKG_SUCCESS;
76fb299fa2Sopenharmony_ci    }
77fb299fa2Sopenharmony_ci    int32_t ExtractFile(const std::string &fileId, StreamPtr output) override
78fb299fa2Sopenharmony_ci    {
79fb299fa2Sopenharmony_ci        if (fileId != "hash_signed_data") {
80fb299fa2Sopenharmony_ci            return PKG_SUCCESS;
81fb299fa2Sopenharmony_ci        }
82fb299fa2Sopenharmony_ci        if (output == nullptr) {
83fb299fa2Sopenharmony_ci            return PKG_INVALID_STREAM;
84fb299fa2Sopenharmony_ci        }
85fb299fa2Sopenharmony_ci        auto stream = static_cast<MemoryMapStream *>(output);
86fb299fa2Sopenharmony_ci        auto fd = open((TEST_PATH_FROM + fileId).c_str(), O_RDWR);
87fb299fa2Sopenharmony_ci        if (fd == -1) {
88fb299fa2Sopenharmony_ci            PKG_LOGE("file %s not existed", (TEST_PATH_FROM + fileId).c_str());
89fb299fa2Sopenharmony_ci            return PKG_INVALID_FILE;
90fb299fa2Sopenharmony_ci        }
91fb299fa2Sopenharmony_ci        ON_SCOPE_EXIT(close) {
92fb299fa2Sopenharmony_ci            close(fd);
93fb299fa2Sopenharmony_ci        };
94fb299fa2Sopenharmony_ci        std::string content {};
95fb299fa2Sopenharmony_ci        if (!Utils::ReadFileToString(fd, content)) {
96fb299fa2Sopenharmony_ci            PKG_LOGE("read file to string failed");
97fb299fa2Sopenharmony_ci            return PKG_INVALID_FILE;
98fb299fa2Sopenharmony_ci        }
99fb299fa2Sopenharmony_ci        PkgBuffer buffer {};
100fb299fa2Sopenharmony_ci        stream->GetBuffer(buffer);
101fb299fa2Sopenharmony_ci        if (content.size() + 1 != buffer.length) {
102fb299fa2Sopenharmony_ci            PKG_LOGE("content size is not valid, %u != %u", content.size(), buffer.data.size());
103fb299fa2Sopenharmony_ci            return PKG_INVALID_FILE;
104fb299fa2Sopenharmony_ci        }
105fb299fa2Sopenharmony_ci        std::copy(content.begin(), content.end(), buffer.buffer);
106fb299fa2Sopenharmony_ci        return PKG_SUCCESS;
107fb299fa2Sopenharmony_ci    }
108fb299fa2Sopenharmony_ci    int32_t CreatePkgStream(StreamPtr &stream, const std::string &fileName,
109fb299fa2Sopenharmony_ci         size_t size, int32_t type) override
110fb299fa2Sopenharmony_ci    {
111fb299fa2Sopenharmony_ci        FILE *file = nullptr;
112fb299fa2Sopenharmony_ci        std::string fileNameReal = fileName;
113fb299fa2Sopenharmony_ci        auto pos = fileName.rfind('/');
114fb299fa2Sopenharmony_ci        if (pos != std::string::npos) {
115fb299fa2Sopenharmony_ci            fileNameReal = fileName.substr(pos + 1);
116fb299fa2Sopenharmony_ci        }
117fb299fa2Sopenharmony_ci        char realPath[PATH_MAX + 1] = {};
118fb299fa2Sopenharmony_ci        if (realpath((TEST_PATH_FROM + fileNameReal).c_str(), realPath) == nullptr) {
119fb299fa2Sopenharmony_ci            LOG(ERROR) << (TEST_PATH_FROM + fileNameReal) << " realpath failed";
120fb299fa2Sopenharmony_ci            return PKG_INVALID_FILE;
121fb299fa2Sopenharmony_ci        }
122fb299fa2Sopenharmony_ci        file = fopen(realPath, "rb");
123fb299fa2Sopenharmony_ci        if (file == nullptr) {
124fb299fa2Sopenharmony_ci            PKG_LOGE("Fail to open file %s ", fileNameReal.c_str());
125fb299fa2Sopenharmony_ci            return PKG_INVALID_FILE;
126fb299fa2Sopenharmony_ci        }
127fb299fa2Sopenharmony_ci        stream = new FileStream(this, fileNameReal, file, PkgStream::PkgStreamType_Read);
128fb299fa2Sopenharmony_ci        return USCRIPT_SUCCESS;
129fb299fa2Sopenharmony_ci    }
130fb299fa2Sopenharmony_ci    void ClosePkgStream(StreamPtr &stream) override
131fb299fa2Sopenharmony_ci    {
132fb299fa2Sopenharmony_ci        delete stream;
133fb299fa2Sopenharmony_ci    }
134fb299fa2Sopenharmony_ci};
135fb299fa2Sopenharmony_ci
136fb299fa2Sopenharmony_ci
137fb299fa2Sopenharmony_ciclass TestScriptInstructionSparseImageWrite : public Uscript::UScriptInstruction {
138fb299fa2Sopenharmony_cipublic:
139fb299fa2Sopenharmony_ci    TestScriptInstructionSparseImageWrite() {}
140fb299fa2Sopenharmony_ci    virtual ~TestScriptInstructionSparseImageWrite() {}
141fb299fa2Sopenharmony_ci    int32_t Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context) override
142fb299fa2Sopenharmony_ci    {
143fb299fa2Sopenharmony_ci        // 从参数中获取分区信息
144fb299fa2Sopenharmony_ci        std::string partitionName;
145fb299fa2Sopenharmony_ci        int32_t ret = context.GetParam(0, partitionName);
146fb299fa2Sopenharmony_ci        if (ret != USCRIPT_SUCCESS) {
147fb299fa2Sopenharmony_ci            LOG(ERROR) << "Error to get param";
148fb299fa2Sopenharmony_ci            return ret;
149fb299fa2Sopenharmony_ci        }
150fb299fa2Sopenharmony_ci        LOG(INFO) << "UScriptInstructionSparseImageWrite::Execute " << partitionName;
151fb299fa2Sopenharmony_ci        if (env.GetPkgManager() == nullptr) {
152fb299fa2Sopenharmony_ci            LOG(ERROR) << "Error to get pkg manager";
153fb299fa2Sopenharmony_ci            return USCRIPT_ERROR_EXECUTE;
154fb299fa2Sopenharmony_ci        }
155fb299fa2Sopenharmony_ci        return ret;
156fb299fa2Sopenharmony_ci    }
157fb299fa2Sopenharmony_ci};
158fb299fa2Sopenharmony_ci
159fb299fa2Sopenharmony_ciclass TestScriptInstructionFactory : public UScriptInstructionFactory {
160fb299fa2Sopenharmony_cipublic:
161fb299fa2Sopenharmony_ci    virtual int32_t CreateInstructionInstance(UScriptInstructionPtr& instr, const std::string& name)
162fb299fa2Sopenharmony_ci    {
163fb299fa2Sopenharmony_ci        if (name == "sparse_image_write") {
164fb299fa2Sopenharmony_ci            instr = new TestScriptInstructionSparseImageWrite();
165fb299fa2Sopenharmony_ci        }
166fb299fa2Sopenharmony_ci        return USCRIPT_SUCCESS;
167fb299fa2Sopenharmony_ci    }
168fb299fa2Sopenharmony_ci    virtual void DestoryInstructionInstance(UScriptInstructionPtr& instr)
169fb299fa2Sopenharmony_ci    {
170fb299fa2Sopenharmony_ci        delete instr;
171fb299fa2Sopenharmony_ci        instr = nullptr;
172fb299fa2Sopenharmony_ci    }
173fb299fa2Sopenharmony_ci    TestScriptInstructionFactory() {}
174fb299fa2Sopenharmony_ci    virtual ~TestScriptInstructionFactory() {}
175fb299fa2Sopenharmony_ci};
176fb299fa2Sopenharmony_ci
177fb299fa2Sopenharmony_ciclass UTestScriptEnv : public UScriptEnv {
178fb299fa2Sopenharmony_cipublic:
179fb299fa2Sopenharmony_ci    explicit UTestScriptEnv(Hpackage::PkgManager::PkgManagerPtr pkgManager) : UScriptEnv(pkgManager) {}
180fb299fa2Sopenharmony_ci    ~UTestScriptEnv()
181fb299fa2Sopenharmony_ci    {
182fb299fa2Sopenharmony_ci        if (factory_ != nullptr) {
183fb299fa2Sopenharmony_ci            delete factory_;
184fb299fa2Sopenharmony_ci            factory_ = nullptr;
185fb299fa2Sopenharmony_ci        }
186fb299fa2Sopenharmony_ci    }
187fb299fa2Sopenharmony_ci
188fb299fa2Sopenharmony_ci    virtual void PostMessage(const std::string &cmd, std::string content) {}
189fb299fa2Sopenharmony_ci
190fb299fa2Sopenharmony_ci    virtual UScriptInstructionFactoryPtr GetInstructionFactory()
191fb299fa2Sopenharmony_ci    {
192fb299fa2Sopenharmony_ci        if (factory_ == nullptr) {
193fb299fa2Sopenharmony_ci            factory_ = new TestScriptInstructionFactory();
194fb299fa2Sopenharmony_ci        }
195fb299fa2Sopenharmony_ci        return factory_;
196fb299fa2Sopenharmony_ci    }
197fb299fa2Sopenharmony_ci
198fb299fa2Sopenharmony_ci    virtual const std::vector<std::string> GetInstructionNames() const
199fb299fa2Sopenharmony_ci    {
200fb299fa2Sopenharmony_ci        static std::vector<std::string> updaterCmds = {"sparse_image_write"};
201fb299fa2Sopenharmony_ci        return updaterCmds;
202fb299fa2Sopenharmony_ci    }
203fb299fa2Sopenharmony_ci
204fb299fa2Sopenharmony_ci    virtual bool IsRetry() const
205fb299fa2Sopenharmony_ci    {
206fb299fa2Sopenharmony_ci        return isRetry;
207fb299fa2Sopenharmony_ci    }
208fb299fa2Sopenharmony_ci
209fb299fa2Sopenharmony_ci    virtual PostMessageFunction GetPostmsgFunc()
210fb299fa2Sopenharmony_ci    {
211fb299fa2Sopenharmony_ci        return nullptr;
212fb299fa2Sopenharmony_ci    }
213fb299fa2Sopenharmony_ci    UScriptInstructionFactory *factory_ = nullptr;
214fb299fa2Sopenharmony_ciprivate:
215fb299fa2Sopenharmony_ci    bool isRetry = false;
216fb299fa2Sopenharmony_ci};
217fb299fa2Sopenharmony_ci
218fb299fa2Sopenharmony_ciclass UScriptTest : public ::testing::Test {
219fb299fa2Sopenharmony_cipublic:
220fb299fa2Sopenharmony_ci    UScriptTest() {}
221fb299fa2Sopenharmony_ci
222fb299fa2Sopenharmony_ci    ~UScriptTest()
223fb299fa2Sopenharmony_ci    {
224fb299fa2Sopenharmony_ci        ScriptManager::ReleaseScriptManager();
225fb299fa2Sopenharmony_ci    }
226fb299fa2Sopenharmony_ci
227fb299fa2Sopenharmony_ci    int TestUscriptExecute()
228fb299fa2Sopenharmony_ci    {
229fb299fa2Sopenharmony_ci        int32_t ret {};
230fb299fa2Sopenharmony_ci        TestPkgManager packageManager;
231fb299fa2Sopenharmony_ci        UTestScriptEnv *env = new UTestScriptEnv(&packageManager);
232fb299fa2Sopenharmony_ci        HashDataVerifier verifier {&packageManager};
233fb299fa2Sopenharmony_ci        verifier.LoadHashDataAndPkcs7(TEST_PATH_FROM + "updater_fake_pkg.zip");
234fb299fa2Sopenharmony_ci        ScriptManager *manager = ScriptManager::GetScriptManager(env, &verifier);
235fb299fa2Sopenharmony_ci        if (manager == nullptr) {
236fb299fa2Sopenharmony_ci            USCRIPT_LOGI("create manager fail ret:%d", ret);
237fb299fa2Sopenharmony_ci            delete env;
238fb299fa2Sopenharmony_ci            return USCRIPT_INVALID_SCRIPT;
239fb299fa2Sopenharmony_ci        }
240fb299fa2Sopenharmony_ci        int32_t priority = SCRIPT_TEST_PRIORITY_NUM;
241fb299fa2Sopenharmony_ci        ret = manager->ExecuteScript(priority);
242fb299fa2Sopenharmony_ci        EXPECT_EQ(ret, USCRIPT_ABOART);
243fb299fa2Sopenharmony_ci        USCRIPT_LOGI("ExecuteScript ret:%d", ret);
244fb299fa2Sopenharmony_ci        priority = 0;
245fb299fa2Sopenharmony_ci        ret = manager->ExecuteScript(priority);
246fb299fa2Sopenharmony_ci        priority = 1;
247fb299fa2Sopenharmony_ci        ret = manager->ExecuteScript(priority);
248fb299fa2Sopenharmony_ci        priority = SCRIPT_TEST_LAST_PRIORITY;
249fb299fa2Sopenharmony_ci        ret = manager->ExecuteScript(priority);
250fb299fa2Sopenharmony_ci        delete env;
251fb299fa2Sopenharmony_ci        ScriptManager::ReleaseScriptManager();
252fb299fa2Sopenharmony_ci        return ret;
253fb299fa2Sopenharmony_ci    }
254fb299fa2Sopenharmony_ci
255fb299fa2Sopenharmony_ciprotected:
256fb299fa2Sopenharmony_ci    void SetUp() {}
257fb299fa2Sopenharmony_ci    void TearDown() {}
258fb299fa2Sopenharmony_ci    void TestBody() {}
259fb299fa2Sopenharmony_ci
260fb299fa2Sopenharmony_ciprivate:
261fb299fa2Sopenharmony_ci    std::vector<std::string> testFileNames_ = {
262fb299fa2Sopenharmony_ci        "loadScript.us",
263fb299fa2Sopenharmony_ci        "registerCmd.us",
264fb299fa2Sopenharmony_ci        "test_function.us",
265fb299fa2Sopenharmony_ci        "test_if.us",
266fb299fa2Sopenharmony_ci        "test_logic.us",
267fb299fa2Sopenharmony_ci        "test_math.us",
268fb299fa2Sopenharmony_ci        "test_native.us",
269fb299fa2Sopenharmony_ci        "testscript.us",
270fb299fa2Sopenharmony_ci        "Verse-script.us",
271fb299fa2Sopenharmony_ci        "test_script.us"
272fb299fa2Sopenharmony_ci    };
273fb299fa2Sopenharmony_ci};
274fb299fa2Sopenharmony_ci
275fb299fa2Sopenharmony_ciHWTEST_F(UScriptTest, TestUscriptExecute, TestSize.Level1)
276fb299fa2Sopenharmony_ci{
277fb299fa2Sopenharmony_ci    UScriptTest test;
278fb299fa2Sopenharmony_ci    EXPECT_EQ(0, test.TestUscriptExecute());
279fb299fa2Sopenharmony_ci}
280fb299fa2Sopenharmony_ci}
281