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