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 <fcntl.h> 17#include <gmock/gmock.h> 18#include <gtest/gtest.h> 19#include <iostream> 20#include <string> 21#include "applypatch/block_set.h" 22#include "applypatch/store.h" 23#include "applypatch/transfer_manager.h" 24#include "log/log.h" 25#include "utils.h" 26 27 28using namespace testing::ext; 29using namespace Updater; 30using namespace std; 31namespace UpdaterUt { 32class AllCmdUnitTest : public testing::Test { 33public: 34 static void SetUpTestCase(void); 35 static void TearDownTestCase(void) {}; 36 void SetUp(); 37 void TearDown(); 38 bool WriteTestBin(int fd, const uint8_t &data, size_t size) const; 39 bool GetTransferContents(const std::string &transferFile, std::string &contents) const; 40 int AllCmdUnitTestMove(int &fd, std::vector<std::string> &allCmd, TransferManager &tm); 41 void FillTransferHeader(std::vector<std::string> &command, const std::string &headerBuffer) const 42 { 43 std::vector<std::string> headInfos = Updater::Utils::SplitString(headerBuffer); 44 for (const auto &headInfo : headInfos) { 45 command.push_back(headInfo); 46 } 47 } 48}; 49 50void AllCmdUnitTest::SetUpTestCase() 51{ 52 cout << "Updater Unit AllCmdUnitTest Setup!" << endl; 53} 54 55void AllCmdUnitTest::SetUp() 56{ 57 cout << "Updater Unit AllCmdUnitTest Begin!" << endl; 58} 59 60void AllCmdUnitTest::TearDown() 61{ 62 cout << "Updater Unit AllCmdUnitTest End!" << endl; 63} 64 65bool AllCmdUnitTest::GetTransferContents(const std::string &transferFile, std::string &contents) const 66{ 67 int fd = open(transferFile.c_str(), O_RDONLY | O_CLOEXEC); 68 if (fd < 0) { 69 return false; 70 } 71 contents.clear(); 72 bool rc = Updater::Utils::ReadFileToString(fd, contents); 73 close(fd); 74 return rc; 75} 76 77bool AllCmdUnitTest::WriteTestBin(int fd, const uint8_t &data, size_t size) const 78{ 79 ssize_t written = 0; 80 size_t rest = size; 81 size_t count = 4096; 82 83 const uint8_t *p = &data; 84 while (rest > 0) { 85 do { 86 written = write(fd, p, count); 87 } while (written < 0 && errno == EINTR); 88 89 if (written < 0) { 90 return false; 91 } 92 rest -= written; 93 } 94 return true; 95} 96 97// Testcase for testing all commands without "new" command. 98// new command is not easy to simulate, it depends on 99// compression and other condition. 100// Leave new command to be covered by update_image_block test. 101HWTEST_F(AllCmdUnitTest, allCmd_test_001, TestSize.Level1) 102{ 103 std::unique_ptr<TransferManager> tm = std::make_unique<TransferManager>(); 104 // Read source 105 106 char filename[] = {"/data/updater/updater/allCmdUnitTest.bin"}; 107 int fd = open(filename, O_RDWR); 108 if (fd == -1) { 109 std::cout << "Failed to open test data allCmdUnitTest.bin : " << errno << std::endl; 110 return; 111 } 112 113 std::string transferContents = ""; 114 // Read transfer list then run all commands. 115 // Cover all correct transfer data, expect all commands return correctly. 116 bool rc = GetTransferContents("/data/updater/applypatch/cmd_001_correct.transfer.list", transferContents); 117 EXPECT_TRUE(rc); 118 std::vector<std::string> transferLines = Updater::Utils::SplitString(transferContents, "\n"); 119 std::cout << "Dump transfer lines: " << std::endl; 120 for (const auto &line : transferLines) { 121 std::cout << line << std::endl; 122 } 123 std::cout << "Dump transfer line done." << std::endl; 124 tm->GetTransferParams()->storeBase = "/data/updater/update_tmp"; 125 std::string storePath = "/data/updater/update_tmp"; 126 Store::CreateNewSpace(storePath, false); 127 rc = tm->CommandsParser(fd, transferLines); 128 EXPECT_TRUE(rc); 129} 130 131int AllCmdUnitTest::AllCmdUnitTestMove(int &fd, std::vector<std::string> &allCmd, TransferManager &tm) 132{ 133 size_t bufferSize = 4096; 134 size_t count = 10; 135 std::vector<uint8_t> buffer1(bufferSize, 1); 136 lseek64(fd, 0, SEEK_SET); 137 auto res = WriteTestBin(fd, *buffer1.data(), bufferSize * count); 138 if (!res) { 139 printf("Write to bin error\n"); 140 } 141 142 std::string baseBlockPair = "2,1,2"; 143 BlockSet baseBlock; 144 baseBlock.ParserAndInsert(baseBlockPair); 145 if (baseBlock.WriteZeroToBlock(fd, false) != 0) { 146 std::cout << "Write 0 to bin error: " << errno << std::endl; 147 } 148 149 allCmd.pop_back(); 150 allCmd.push_back("move ad7facb2586fc6e966c004d7d1d16b024f5805ff7cb47c7a85dabd8b48892ca7 2,0,1 1 2,1,2"); 151 bool result = tm.CommandsParser(fd, allCmd); 152 LOG(INFO) << "CommandsParser result:" << result; 153 154 lseek64(fd, 0, SEEK_SET); 155 res = WriteTestBin(fd, *buffer1.data(), bufferSize * count); 156 if (!res) { 157 std::cout << "Write to bin error" << std::endl; 158 } 159 if (baseBlock.WriteZeroToBlock(fd, false) != 0) { 160 std::cout << "Write 0 to bin error: " << errno << std::endl; 161 } 162 163 close(fd); 164 return 0; 165} 166 167HWTEST_F(AllCmdUnitTest, allCmd_test_002, TestSize.Level1) 168{ 169 std::unique_ptr<TransferManager> tm = std::make_unique<TransferManager>(); 170 std::string filePath = "/tmp/test.bin"; 171 size_t bufferSize = 4096; 172 size_t count = 10; 173 mode_t dirMode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 174 tm->GetTransferParams()->storeBase = "/tmp/cmdtest"; 175 Store::DoFreeSpace(tm->GetTransferParams()->storeBase); 176 Utils::MkdirRecursive(tm->GetTransferParams()->storeBase, dirMode); 177 std::vector<uint8_t> buffer(bufferSize, 0); 178 int fd = open(filePath.c_str(), O_RDWR | O_CREAT, dirMode); 179 if (fd < 0) { 180 printf("Failed to open block %s, errno: %d\n", filePath.c_str(), errno); 181 return; 182 } 183 lseek64(fd, 0, SEEK_SET); 184 auto res = WriteTestBin(fd, *buffer.data(), bufferSize * count); 185 if (!res) { 186 printf("Write to bin error\n"); 187 } 188 189 bool result = false; 190 mode_t mode = (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 191 // 192 // 构造命令 193 std::vector<std::string> allCmd; 194 FillTransferHeader(allCmd, "4 27280 0 3616"); 195 allCmd.push_back("stash ad7facb2586fc6e966c004d7d1d16b024f5805ff7cb47c7a85dabd8b48892ca7 2,0,1"); // 清第一块 196 result = tm->CommandsParser(fd, allCmd); 197 EXPECT_TRUE(result); 198 Store::DoFreeSpace(tm->GetTransferParams()->storeBase); 199 Utils::MkdirRecursive(tm->GetTransferParams()->storeBase, mode); 200 201 EXPECT_EQ(AllCmdUnitTestMove(fd, allCmd, *tm), 0); 202 unlink(filePath.c_str()); 203} 204} // updater_ut 205