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 "applypatch_unittest.h"
17#include <cerrno>
18#include <cstdio>
19#include <fcntl.h>
20#include <iostream>
21#include <libgen.h>
22#include <sys/mman.h>
23#include <sys/mount.h>
24#include <sys/stat.h>
25#include <unistd.h>
26#include <vector>
27#include "applypatch/data_writer.h"
28#include "fs_manager/mount.h"
29#include "log/log.h"
30#include "securec.h"
31#include "unittest_comm.h"
32#include "utils.h"
33
34namespace UpdaterUt {
35using namespace testing::ext;
36using namespace Updater;
37using namespace std;
38using namespace testing;
39constexpr unsigned int BUFFER_LEN = 12;
40
41void ApplyPatchUnitTest::SetUp()
42{
43    unsigned long mountFlag = MS_REMOUNT;
44    std::string tmpPath = "/tmp";
45    // mount rootfs to read-write.
46    std::string rootSource = "/dev/root";
47    if (mount(rootSource.c_str(), "/", "ext4", mountFlag, nullptr) != 0) {
48        std::cout << "Cannot re-mount rootfs\n";
49    }
50    auto ret = mkdir(tmpPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
51    if (ret != 0) {
52        std::cout << "Cannot create \"/tmp\" directory: " << errno << "\n";
53    }
54
55    // Load specific fstab for testing.
56    LoadSpecificFstab("/data/updater/applypatch/etc/fstab.ut.updater");
57}
58
59void ApplyPatchUnitTest::TearDown()
60{
61    std::string partitionName = "/rawwriter";
62    auto devPath = GetBlockDeviceByMountPoint(partitionName);
63    unlink(devPath.c_str());
64}
65
66HWTEST_F(ApplyPatchUnitTest, updater_RawWriter, TestSize.Level1)
67{
68    WriteMode mode = WRITE_RAW;
69    uint8_t *addr = nullptr;
70    uint8_t buf[BUFFER_LEN + 1] = {0};
71
72    std::string partitionName = "/rawwriter";
73    std::string filePath = "/data/updater/ut/datawriter/rawwrite";
74    std::unique_ptr<DataWriter> writer = DataWriter::CreateDataWriter(mode, filePath);
75    EXPECT_NE(writer, nullptr);
76    bool ret = writer->Write(addr, 0, nullptr);
77    EXPECT_FALSE(ret);
78
79    addr = buf;
80    ret = writer->Write(addr, 0, nullptr);
81    EXPECT_FALSE(ret);
82
83    ret = writer->Write(buf, BUFFER_LEN, nullptr);
84    EXPECT_FALSE(ret);
85
86    int mRet = memcpy_s(buf, BUFFER_LEN, "hello, world", BUFFER_LEN);
87    EXPECT_EQ(mRet, 0);
88    auto devPath = GetBlockDeviceByMountPoint(partitionName);
89    const std::string devDir = "/data/updater/ut/datawriter";
90    Updater::Utils::MkdirRecursive(devDir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
91    close(open(devPath.c_str(), O_CREAT | O_WRONLY | O_EXCL, 0664));
92    ret = writer->Write(buf, BUFFER_LEN, nullptr);
93    EXPECT_TRUE(ret);
94
95    int fd  = open(devPath.c_str(), O_RDONLY);
96    EXPECT_GE(fd, 0);
97
98    uint8_t buffer[BUFFER_LEN + 1] = {0};
99    size_t n = read(fd, buffer, BUFFER_LEN);
100    EXPECT_EQ(n, BUFFER_LEN);
101
102    auto result = memcmp(buf, buffer, BUFFER_LEN);
103    EXPECT_EQ(result, 0);
104    DataWriter::ReleaseDataWriter(writer);
105}
106
107HWTEST_F(ApplyPatchUnitTest, updater_CreateDataWriter, TestSize.Level1)
108{
109    std::vector<WriteMode> modes = { WRITE_RAW, WRITE_DECRYPT };
110    std::unique_ptr<DataWriter> writer = nullptr;
111    for (auto mode : modes) {
112        if (mode == WRITE_DECRYPT) {
113            EXPECT_EQ(writer, nullptr);
114            continue;
115        }
116        writer = DataWriter::CreateDataWriter(mode, "", DataWriter::GetUpdaterEnv());
117        EXPECT_NE(writer, nullptr);
118        DataWriter::ReleaseDataWriter(writer);
119        writer = nullptr;
120    }
121}
122} // namespace updater_ut
123