1/*
2 * Copyright (c) 2023 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 "display_buffer_mt.h"
17
18#include <unistd.h>
19#include <vector>
20#include <thread>
21#include <cinttypes>
22#include <securec.h>
23#include <cstring>
24
25#include "gtest/gtest.h"
26#include "v1_0/display_composer_type.h"
27#include "hdf_base.h"
28#include "hdf_log.h"
29
30namespace OHOS {
31namespace HDI {
32namespace Display {
33namespace TEST {
34using namespace OHOS::HDI::Display::Composer::V1_0;
35using namespace OHOS::HDI::Display::Buffer::V1_0;
36using namespace OHOS;
37using namespace testing::ext;
38
39static IDisplayBuffer* g_dispbuf = nullptr;
40static const int SIZE_TIMES = 3;
41static const int HANDLE_NUM_1 = 2;
42static const int HANDLE_NUM_2 = 32;
43static const int LOOP_COUNT = 10;
44static const int INFO_WIDTH = 1024;
45static const int INFO_HEIGHT = 1024;
46
47#define HDF_LOG_TAG display_buffer_module_test
48
49static void WriteBuffer(const BufferHandle& handle)
50{
51    const char VERIFY_MSG[] = "12345678, (*~*)";
52    // write msg to display buffer fully.
53    int strSize = strlen(VERIFY_MSG) + 1;
54    int i = 0;
55    char* ptr = reinterpret_cast<char *>(handle.virAddr);
56    if (ptr == nullptr) {
57        HDF_LOGE("cast ptr failed");
58        return;
59    }
60
61    for (; i < handle.size - strSize;) {
62        errno_t ret = memcpy_s(&ptr[i], sizeof(VERIFY_MSG), VERIFY_MSG, sizeof(VERIFY_MSG));
63        if (ret != EOK) {
64            HDF_LOGE("memcpy_s error : %d", ret);
65            return;
66        }
67        i += strSize;
68        ptr[i - 1] = 0;
69    }
70    for (i = i - 1; i < handle.size; i++) {
71        ptr[i] = 'z';
72    }
73
74    // read all contents from buffer
75    HDF_LOGD("%{public}s(%{public}d), buffer size:%{public}d, len:%{public}d",
76             __func__, __LINE__, handle.size, strSize);
77    // verify buffer contents from strings written.
78    for (i = 0; i < handle.size - SIZE_TIMES * strSize; i = i + strSize) {
79        if (strncmp(VERIFY_MSG, &ptr[i], sizeof(VERIFY_MSG)) != 0) {
80            HDF_LOGD("%{public}s(%{public}d), buffer[%{public}d]:%{public}s",
81                     __func__, __LINE__, i, &ptr[i]);
82        }
83    }
84
85    for (i = handle.size - HANDLE_NUM_1; i < (handle.size - HANDLE_NUM_2); i++) {
86        HDF_LOGD("%{public}s(%{public}d), i:%{public}d, str:%{public}s",
87                 __func__, __LINE__, i, &ptr[i]);
88    }
89}
90
91static void DumpBufferHandle(const BufferHandle& handle)
92{
93    // dump buffer handle infomation
94    HDF_LOGD("-------------------------------------");
95    HDF_LOGD("fd                =%{public}d",   handle.fd);
96    HDF_LOGD("width             =%{public}d",   handle.width);
97    HDF_LOGD("stride            =%{public}d",   handle.stride);
98    HDF_LOGD("height            =%{public}d",   handle.height);
99    HDF_LOGD("size              =0x%{public}x", handle.size);
100    HDF_LOGD("format            =%{public}d",   handle.format);
101    HDF_LOGD("usage             =0x%{public}" PRIx64 "", handle.usage);
102    HDF_LOGD("reserveFds        =%{public}d",   handle.reserveFds);
103    HDF_LOGD("reserveInts       =%{public}d",   handle.reserveInts);
104    HDF_LOGD("-------------------------------------");
105}
106
107int32_t DisplayBufferMt::RunTest(const AllocInfo& info)
108{
109    BufferHandle* bHandle = nullptr;
110    // AllocMem
111    int32_t ec = g_dispbuf->AllocMem(info, bHandle);
112    if (ec != HDF_SUCCESS || bHandle == nullptr) {
113        HDF_LOGE("%{public}s, line=%{public}d, AllocMem failed. ec=0x%{public}x",
114                 __func__, __LINE__, ec);
115        return HDF_FAILURE;
116    }
117
118    // Mmap
119    void* buffer = g_dispbuf->Mmap(*bHandle);
120    if (buffer == nullptr) {
121        HDF_LOGE("Mmap failed.");
122        g_dispbuf->FreeMem(*bHandle);
123        return HDF_FAILURE;
124    }
125    HDF_LOGD("Mmap successful");
126
127    DumpBufferHandle(*bHandle);
128    WriteBuffer(*bHandle);
129
130    // InvalidateCache
131    ec = g_dispbuf->InvalidateCache(*bHandle);
132    if (ec != HDF_SUCCESS) {
133        HDF_LOGE("InvalidateCache failed.");
134        g_dispbuf->Unmap(*bHandle);
135        g_dispbuf->FreeMem(*bHandle);
136        return HDF_FAILURE;
137    }
138    // InvalidateCache
139    ec = g_dispbuf->FlushCache(*bHandle);
140    if (ec != HDF_SUCCESS) {
141        HDF_LOGE("flushCache failed.");
142        g_dispbuf->Unmap(*bHandle);
143        g_dispbuf->FreeMem(*bHandle);
144        return HDF_FAILURE;
145    }
146    HDF_LOGD("flush Cache success.");
147    // free buffer
148    g_dispbuf->Unmap(*bHandle);
149    g_dispbuf->FreeMem(*bHandle);
150    return HDF_SUCCESS;
151}
152
153void DisplayBufferMt::SetUpTestCase()
154{
155    g_dispbuf = IDisplayBuffer::Get();
156    ASSERT_TRUE(g_dispbuf != nullptr);
157}
158
159HWTEST_F(DisplayBufferMt, test_DisplayBuffer, TestSize.Level1)
160{
161    AllocInfo info;
162    info.width  = INFO_WIDTH;
163    info.height = INFO_HEIGHT;
164    info.usage = OHOS::HDI::Display::Composer::V1_0::HBM_USE_MEM_DMA |
165            OHOS::HDI::Display::Composer::V1_0::HBM_USE_CPU_READ |
166            OHOS::HDI::Display::Composer::V1_0::HBM_USE_CPU_WRITE;
167    info.format = PIXEL_FMT_RGBA_8888;
168
169    for (int i = 0; i < LOOP_COUNT; i++) {
170        int32_t ret = RunTest(info);
171        EXPECT_EQ(HDF_SUCCESS, ret);
172    }
173}
174} // OHOS
175} // HDI
176} // DISPLAY
177} // TEST
178