132a6e48fSopenharmony_ci/*
232a6e48fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
332a6e48fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
432a6e48fSopenharmony_ci * you may not use this file except in compliance with the License.
532a6e48fSopenharmony_ci * You may obtain a copy of the License at
632a6e48fSopenharmony_ci *
732a6e48fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
832a6e48fSopenharmony_ci *
932a6e48fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1032a6e48fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1132a6e48fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1232a6e48fSopenharmony_ci * See the License for the specific language governing permissions and
1332a6e48fSopenharmony_ci * limitations under the License.
1432a6e48fSopenharmony_ci */
1532a6e48fSopenharmony_ci#include <gtest/gtest.h>
1632a6e48fSopenharmony_ci
1732a6e48fSopenharmony_ci#include <thread>
1832a6e48fSopenharmony_ci#include <chrono>
1932a6e48fSopenharmony_ci#include <unistd.h>
2032a6e48fSopenharmony_ci#include <fstream>
2132a6e48fSopenharmony_ci
2232a6e48fSopenharmony_ci#include <buffer_utils.h>
2332a6e48fSopenharmony_ci#include "surface_buffer_impl.h"
2432a6e48fSopenharmony_ci#include "sandbox_utils.h"
2532a6e48fSopenharmony_ci
2632a6e48fSopenharmony_ci
2732a6e48fSopenharmony_ciusing namespace testing;
2832a6e48fSopenharmony_ciusing namespace testing::ext;
2932a6e48fSopenharmony_ci
3032a6e48fSopenharmony_cinamespace OHOS::Rosen {
3132a6e48fSopenharmony_ciclass BufferUtilsTest : public testing::Test {
3232a6e48fSopenharmony_cipublic:
3332a6e48fSopenharmony_ci    static void SetUpTestCase();
3432a6e48fSopenharmony_ci    static void TearDownTestCase();
3532a6e48fSopenharmony_ci
3632a6e48fSopenharmony_ci    static inline BufferRequestConfig requestConfig = {
3732a6e48fSopenharmony_ci        .width = 0x100,
3832a6e48fSopenharmony_ci        .height = 0x100,
3932a6e48fSopenharmony_ci        .strideAlignment = 0x8,
4032a6e48fSopenharmony_ci        .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
4132a6e48fSopenharmony_ci        .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
4232a6e48fSopenharmony_ci        .timeout = 0,
4332a6e48fSopenharmony_ci    };
4432a6e48fSopenharmony_ci
4532a6e48fSopenharmony_ci    static inline sptr<SurfaceBuffer> buffer = nullptr;
4632a6e48fSopenharmony_ci    static inline std::string flagPath = "/data/bq_dump";
4732a6e48fSopenharmony_ci    static inline std::string name_ = "test";
4832a6e48fSopenharmony_ci};
4932a6e48fSopenharmony_ci
5032a6e48fSopenharmony_cinamespace fs = std::filesystem;
5132a6e48fSopenharmony_ci
5232a6e48fSopenharmony_civoid BufferUtilsTest::SetUpTestCase()
5332a6e48fSopenharmony_ci{
5432a6e48fSopenharmony_ci    buffer = nullptr;
5532a6e48fSopenharmony_ci
5632a6e48fSopenharmony_ci    // open dump flag
5732a6e48fSopenharmony_ci    std::ofstream outfile(flagPath);
5832a6e48fSopenharmony_ci    outfile << "touch" << std::endl;
5932a6e48fSopenharmony_ci    outfile.close();
6032a6e48fSopenharmony_ci}
6132a6e48fSopenharmony_ci
6232a6e48fSopenharmony_civoid BufferUtilsTest::TearDownTestCase()
6332a6e48fSopenharmony_ci{
6432a6e48fSopenharmony_ci    buffer = nullptr;
6532a6e48fSopenharmony_ci
6632a6e48fSopenharmony_ci    // delete dump flag
6732a6e48fSopenharmony_ci    if (fs::exists(flagPath)) {
6832a6e48fSopenharmony_ci        fs::remove(flagPath);
6932a6e48fSopenharmony_ci    }
7032a6e48fSopenharmony_ci}
7132a6e48fSopenharmony_ci
7232a6e48fSopenharmony_ci/*
7332a6e48fSopenharmony_ci* Function: WriteToFile
7432a6e48fSopenharmony_ci* Type: Function
7532a6e48fSopenharmony_ci* Rank: Important(2)
7632a6e48fSopenharmony_ci* EnvConditions: N/A
7732a6e48fSopenharmony_ci* CaseDescription: 1. call DumpToFileAsync
7832a6e48fSopenharmony_ci*                  2. check ret
7932a6e48fSopenharmony_ci */
8032a6e48fSopenharmony_ciHWTEST_F(BufferUtilsTest, DumpToFileAsyncTest001, Function | MediumTest | Level2)
8132a6e48fSopenharmony_ci{
8232a6e48fSopenharmony_ci    const pid_t pid = GetRealPid();
8332a6e48fSopenharmony_ci
8432a6e48fSopenharmony_ci    // Alloc buffer
8532a6e48fSopenharmony_ci    buffer = new SurfaceBufferImpl();
8632a6e48fSopenharmony_ci    buffer->Alloc(requestConfig);
8732a6e48fSopenharmony_ci
8832a6e48fSopenharmony_ci    // Call DumpToFileAsync
8932a6e48fSopenharmony_ci    GSError ret = DumpToFileAsync(pid, name_, buffer);
9032a6e48fSopenharmony_ci    ASSERT_EQ(ret, OHOS::GSERROR_OK);
9132a6e48fSopenharmony_ci
9232a6e48fSopenharmony_ci    // Expect Buffer Dump to be completed within 20ms.
9332a6e48fSopenharmony_ci    std::chrono::milliseconds dura(20);
9432a6e48fSopenharmony_ci    std::this_thread::sleep_for(dura);
9532a6e48fSopenharmony_ci
9632a6e48fSopenharmony_ci    const std::string directory = "/data";
9732a6e48fSopenharmony_ci    const std::string prefix = "bq_" + std::to_string(pid) + "_" + name_;
9832a6e48fSopenharmony_ci    size_t dumpFileSize = 0;
9932a6e48fSopenharmony_ci    // Traverse the directory and find the dump file.
10032a6e48fSopenharmony_ci    for (const auto& entry : fs::recursive_directory_iterator(directory)) {
10132a6e48fSopenharmony_ci        if (entry.is_regular_file() && entry.path().filename().string().find(prefix) == 0) {
10232a6e48fSopenharmony_ci            // Open the file to create a stream
10332a6e48fSopenharmony_ci            std::ifstream dumpFile(entry.path(), std::ios::binary);
10432a6e48fSopenharmony_ci            std::vector<uint8_t> file_data((std::istreambuf_iterator<char>(dumpFile)),
10532a6e48fSopenharmony_ci                std::istreambuf_iterator<char>());
10632a6e48fSopenharmony_ci            // Get fileSize from the file stream
10732a6e48fSopenharmony_ci            dumpFileSize = file_data.size();
10832a6e48fSopenharmony_ci            dumpFile.close();
10932a6e48fSopenharmony_ci            fs::remove(entry.path());
11032a6e48fSopenharmony_ci            break;
11132a6e48fSopenharmony_ci        }
11232a6e48fSopenharmony_ci    }
11332a6e48fSopenharmony_ci
11432a6e48fSopenharmony_ci    ASSERT_EQ(dumpFileSize, buffer->GetSize());
11532a6e48fSopenharmony_ci}
11632a6e48fSopenharmony_ci
11732a6e48fSopenharmony_ci/*
11832a6e48fSopenharmony_ci* Function: WriteToFile
11932a6e48fSopenharmony_ci* Type: Function
12032a6e48fSopenharmony_ci* Rank: Important(2)
12132a6e48fSopenharmony_ci* EnvConditions: N/A
12232a6e48fSopenharmony_ci* CaseDescription: 1. call DumpToFileAsync
12332a6e48fSopenharmony_ci*                  2. check ret
12432a6e48fSopenharmony_ci */
12532a6e48fSopenharmony_ciHWTEST_F(BufferUtilsTest, DumpToFileAsyncTest002, Function | MediumTest | Level2)
12632a6e48fSopenharmony_ci{
12732a6e48fSopenharmony_ci    const pid_t pid = GetRealPid();
12832a6e48fSopenharmony_ci
12932a6e48fSopenharmony_ci    // Alloc buffer
13032a6e48fSopenharmony_ci    buffer = new SurfaceBufferImpl();
13132a6e48fSopenharmony_ci    buffer->Alloc(requestConfig);
13232a6e48fSopenharmony_ci
13332a6e48fSopenharmony_ci    // Call DumpToFileAsync
13432a6e48fSopenharmony_ci    GSError ret = DumpToFileAsync(pid, name_, buffer);
13532a6e48fSopenharmony_ci    ASSERT_EQ(ret, OHOS::GSERROR_OK);
13632a6e48fSopenharmony_ci
13732a6e48fSopenharmony_ci    // Expect Buffer Dump to be completed within 20ms.
13832a6e48fSopenharmony_ci    std::chrono::milliseconds dura(20);
13932a6e48fSopenharmony_ci    std::this_thread::sleep_for(dura);
14032a6e48fSopenharmony_ci
14132a6e48fSopenharmony_ci    const std::string directory = "/data/storage/el1/base";
14232a6e48fSopenharmony_ci    if (access(directory.c_str(), F_OK) == 0) {
14332a6e48fSopenharmony_ci        const std::string prefix = "bq_" + std::to_string(pid) + "_" + name_;
14432a6e48fSopenharmony_ci        size_t dumpFileSize = 0;
14532a6e48fSopenharmony_ci        // Traverse the directory and find the dump file.
14632a6e48fSopenharmony_ci        for (const auto& entry : fs::recursive_directory_iterator(directory)) {
14732a6e48fSopenharmony_ci            if (entry.is_regular_file() && entry.path().filename().string().find(prefix) == 0) {
14832a6e48fSopenharmony_ci                // Open the file to create a stream
14932a6e48fSopenharmony_ci                std::ifstream dumpFile(entry.path(), std::ios::binary);
15032a6e48fSopenharmony_ci                std::vector<uint8_t> file_data((std::istreambuf_iterator<char>(dumpFile)),
15132a6e48fSopenharmony_ci                    std::istreambuf_iterator<char>());
15232a6e48fSopenharmony_ci                // Get fileSize from the file stream
15332a6e48fSopenharmony_ci                dumpFileSize = file_data.size();
15432a6e48fSopenharmony_ci                dumpFile.close();
15532a6e48fSopenharmony_ci                fs::remove(entry.path());
15632a6e48fSopenharmony_ci                break;
15732a6e48fSopenharmony_ci            }
15832a6e48fSopenharmony_ci        }
15932a6e48fSopenharmony_ci
16032a6e48fSopenharmony_ci        ASSERT_EQ(dumpFileSize, buffer->GetSize());
16132a6e48fSopenharmony_ci    }
16232a6e48fSopenharmony_ci}
16332a6e48fSopenharmony_ci
16432a6e48fSopenharmony_ci/*
16532a6e48fSopenharmony_ci* Function: WriteToFile
16632a6e48fSopenharmony_ci* Type: Function
16732a6e48fSopenharmony_ci* Rank: Important(2)
16832a6e48fSopenharmony_ci* EnvConditions: N/A
16932a6e48fSopenharmony_ci* CaseDescription: 1. call DumpToFileAsync
17032a6e48fSopenharmony_ci*                  2. check ret
17132a6e48fSopenharmony_ci */
17232a6e48fSopenharmony_ciHWTEST_F(BufferUtilsTest, DumpToFileAsyncTest003, Function | MediumTest | Level2)
17332a6e48fSopenharmony_ci{
17432a6e48fSopenharmony_ci    buffer = nullptr;
17532a6e48fSopenharmony_ci    GSError ret = DumpToFileAsync(0, name_, buffer);
17632a6e48fSopenharmony_ci    ASSERT_NE(ret, OHOS::GSERROR_OK);
17732a6e48fSopenharmony_ci}
17832a6e48fSopenharmony_ci
17932a6e48fSopenharmony_ci/*
18032a6e48fSopenharmony_ci* Function: SizeLimitTest
18132a6e48fSopenharmony_ci* Type: Function
18232a6e48fSopenharmony_ci* Rank: Important(2)
18332a6e48fSopenharmony_ci* EnvConditions: N/A
18432a6e48fSopenharmony_ci* CaseDescription: 1. make size bigger than SURFACE_PARCEL_SIZE_LIMIT and check the ret
18532a6e48fSopenharmony_ci */
18632a6e48fSopenharmony_ciHWTEST_F(BufferUtilsTest, SizeLimitTest001, Function | MediumTest | Level2)
18732a6e48fSopenharmony_ci{
18832a6e48fSopenharmony_ci    MessageParcel parcel;
18932a6e48fSopenharmony_ci    uint32_t size = SURFACE_PARCEL_SIZE_LIMIT + 1;
19032a6e48fSopenharmony_ci
19132a6e48fSopenharmony_ci    BufferFlushConfigWithDamages flushConfig = {
19232a6e48fSopenharmony_ci        .damages = std::vector<Rect>(size),
19332a6e48fSopenharmony_ci    };
19432a6e48fSopenharmony_ci    EXPECT_EQ(WriteFlushConfig(parcel, flushConfig), GSERROR_INVALID_ARGUMENTS);
19532a6e48fSopenharmony_ci    EXPECT_TRUE(parcel.WriteUint32(size));
19632a6e48fSopenharmony_ci    EXPECT_EQ(ReadFlushConfig(parcel, flushConfig), GSERROR_BINDER);
19732a6e48fSopenharmony_ci
19832a6e48fSopenharmony_ci    auto infos = std::vector<BufferVerifyAllocInfo>(size);
19932a6e48fSopenharmony_ci    EXPECT_EQ(WriteVerifyAllocInfo(parcel, infos), GSERROR_INVALID_ARGUMENTS);
20032a6e48fSopenharmony_ci    EXPECT_TRUE(parcel.WriteUint32(size));
20132a6e48fSopenharmony_ci    ReadVerifyAllocInfo(parcel, infos);
20232a6e48fSopenharmony_ci
20332a6e48fSopenharmony_ci    auto metaData = std::vector<GraphicHDRMetaData>(size);
20432a6e48fSopenharmony_ci    EXPECT_EQ(WriteHDRMetaData(parcel, metaData), GSERROR_INVALID_ARGUMENTS);
20532a6e48fSopenharmony_ci    EXPECT_TRUE(parcel.WriteUint32(size));
20632a6e48fSopenharmony_ci    EXPECT_EQ(ReadHDRMetaData(parcel, metaData), GSERROR_BINDER);
20732a6e48fSopenharmony_ci
20832a6e48fSopenharmony_ci    auto metaDataSet = std::vector<uint8_t>(size);
20932a6e48fSopenharmony_ci    EXPECT_EQ(WriteHDRMetaDataSet(parcel, metaDataSet), GSERROR_INVALID_ARGUMENTS);
21032a6e48fSopenharmony_ci    EXPECT_TRUE(parcel.WriteUint32(size));
21132a6e48fSopenharmony_ci    EXPECT_EQ(ReadHDRMetaDataSet(parcel, metaDataSet), GSERROR_BINDER);
21232a6e48fSopenharmony_ci
21332a6e48fSopenharmony_ci    GraphicExtDataHandle *handle = static_cast<GraphicExtDataHandle *>(
21432a6e48fSopenharmony_ci        malloc(sizeof(GraphicExtDataHandle) + sizeof(int32_t)));
21532a6e48fSopenharmony_ci    handle->fd = -1;
21632a6e48fSopenharmony_ci    handle->reserveInts = size;
21732a6e48fSopenharmony_ci    handle->reserve[0] = 0;
21832a6e48fSopenharmony_ci    sptr<SurfaceTunnelHandle> tunnelHandle = new SurfaceTunnelHandle();
21932a6e48fSopenharmony_ci    EXPECT_EQ(WriteExtDataHandle(parcel, handle), GSERROR_INVALID_ARGUMENTS);
22032a6e48fSopenharmony_ci    EXPECT_TRUE(parcel.WriteUint32(size));
22132a6e48fSopenharmony_ci    EXPECT_EQ(ReadExtDataHandle(parcel, tunnelHandle), GSERROR_BINDER);
22232a6e48fSopenharmony_ci}
22332a6e48fSopenharmony_ci}