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 <dlfcn.h>
17 #include <hwext/gtest-ext.h>
18 #include <hwext/gtest-tag.h>
19 #include <sys/mman.h>
20 #include <sys/syscall.h>
21
22 #include "stack_writer.h"
23
24 using namespace testing::ext;
25
26 namespace {
27 constexpr uint32_t BUFFER_SIZE = 1024;
28 constexpr uint32_t SMB_SIZE = 10 * 4096;
29 const std::string SMB_NAME = "stackwritertest";
30 const std::string PLUGIN_NAME = "stackwriter";
31 void* g_smbAddr = nullptr;
32 int g_smbFd = 0;
33
InitShareMemory()34 int InitShareMemory()
35 {
36 int fd = syscall(SYS_memfd_create, SMB_NAME.c_str(), 0);
37 CHECK_TRUE(fd >= 0, false, "CreateBlock FAIL SYS_memfd_create");
38
39 int check = ftruncate(fd, SMB_SIZE);
40 if (check < 0) {
41 close(fd);
42 const int bufSize = 1024;
43 char buf[bufSize] = { 0 };
44 strerror_r(errno, buf, bufSize);
45 HILOG_ERROR(LOG_CORE, "CreateBlock ftruncate ERR : %s", buf);
46 return -1;
47 }
48
49 g_smbAddr = mmap(nullptr, SMB_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
50 if (g_smbAddr == (reinterpret_cast<void *>(-1))) {
51 close(fd);
52 const int bufSize = 1024;
53 char buf[bufSize] = { 0 };
54 strerror_r(errno, buf, bufSize);
55 HILOG_ERROR(LOG_CORE, "CreateBlock g_smbAddr mmap ERR : %s", buf);
56 return -1;
57 }
58
59 ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr);
60
61 // initialize header infos
62 header_->info.readOffset_ = 0;
63 header_->info.writeOffset_ = 0;
64 header_->info.memorySize_ = SMB_SIZE - sizeof(ShareMemoryBlock::BlockHeader);
65 header_->info.bytesCount_ = 0;
66 header_->info.chunkCount_ = 0;
67
68 return fd;
69 }
70
71 class StackWriterTest : public ::testing::Test {
72 public:
SetUpTestCase()73 static void SetUpTestCase() {}
TearDownTestCase()74 static void TearDownTestCase() {}
75
SetUp()76 void SetUp()
77 {
78 g_smbFd = InitShareMemory();
79 }
TearDown()80 void TearDown()
81 {
82 g_smbFd = 0;
83 }
84 };
85
CheckBuffer(uint8_t * buffer,size_t size)86 bool CheckBuffer(uint8_t* buffer, size_t size)
87 {
88 ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr);
89 uint8_t* cmpaddr = (uint8_t*)g_smbAddr + sizeof(ShareMemoryBlock::BlockHeader) + header_->info.readOffset_;
90 uint32_t cmpsize = *(uint32_t*)cmpaddr;
91 cmpaddr = cmpaddr + sizeof(uint32_t);
92
93 header_->info.readOffset_ = header_->info.writeOffset_;
94 if (memcmp(buffer, cmpaddr, size) == 0) {
95 return true;
96 }
97 return false;
98 }
99
RandData(uint8_t * data,int size)100 void RandData(uint8_t* data, int size)
101 {
102 time_t tv = time(nullptr);
103 if (tv == -1) {
104 tv = 1;
105 }
106 unsigned int seed = (unsigned int)tv;
107 while (--size) {
108 data[size] = rand_r(&seed) / (uint8_t)(-1);
109 }
110 }
111
112 /**
113 * @tc.name: StackWriter
114 * @tc.desc: Write data to shared memory through writer.
115 * @tc.type: FUNC
116 */
117 HWTEST_F(StackWriterTest, WriteaNormalTest, TestSize.Level1)
118 {
119 auto write = std::make_shared<StackWriter>(PLUGIN_NAME, SMB_SIZE, g_smbFd, -1);
120 EXPECT_NE(write->shareMemoryBlock_, nullptr);
121 uint8_t buffer1[] = {0x55, 0xAA, 0x55, 0xAA};
122 uint8_t buffer2[] = {0x11, 0x22, 0x33, 0x44};
123 uint8_t buffer3[] = {0xAA, 0xBB, 0xCC, 0xDD};
124
125 EXPECT_TRUE(write->Write((const void*)buffer1, sizeof(buffer1)));
126 EXPECT_TRUE(CheckBuffer(buffer1, sizeof(buffer1)));
127 EXPECT_TRUE(write->Write((const void*)buffer2, sizeof(buffer2)));
128 EXPECT_TRUE(CheckBuffer(buffer2, sizeof(buffer2)));
129 EXPECT_TRUE(write->Write((const void*)buffer3, sizeof(buffer3)));
130 EXPECT_TRUE(CheckBuffer(buffer3, sizeof(buffer3)));
131
132 EXPECT_FALSE(write->Write(nullptr, 0));
133 }
134
135 /**
136 * @tc.name: StackWriter
137 * @tc.desc: Write failure process.
138 * @tc.type: FUNC
139 */
140 HWTEST_F(StackWriterTest, WriteaFalseTest, TestSize.Level1)
141 {
142 auto write = std::make_shared<StackWriter>(PLUGIN_NAME, SMB_SIZE, 0, -1);
143 EXPECT_EQ(write->shareMemoryBlock_, nullptr);
144 uint8_t buffer1[] = {0x55, 0xAA, 0x55, 0xAA};
145 uint8_t buffer2[] = {0x11, 0x22, 0x33, 0x44};
146 uint8_t buffer3[] = {0xAA, 0xBB, 0xCC, 0xDD};
147
148 EXPECT_FALSE(write->Write((const void*)buffer1, sizeof(buffer1)));
149 EXPECT_FALSE(CheckBuffer(buffer1, sizeof(buffer1)));
150 EXPECT_FALSE(write->Write((const void*)buffer2, sizeof(buffer2)));
151 EXPECT_FALSE(CheckBuffer(buffer2, sizeof(buffer2)));
152 EXPECT_FALSE(write->Write((const void*)buffer3, sizeof(buffer3)));
153 EXPECT_FALSE(CheckBuffer(buffer3, sizeof(buffer3)));
154
155 EXPECT_FALSE(write->Write(nullptr, 0));
156 }
157
158 /**
159 * @tc.name: StackWriter
160 * @tc.desc: Write data to shared memory through writer.
161 * @tc.type: FUNC
162 */
163 HWTEST_F(StackWriterTest, WriteProcessTest, TestSize.Level1)
164 {
165 uint8_t data[BUFFER_SIZE];
166 RandData(data, BUFFER_SIZE);
167 auto write = std::make_shared<StackWriter>(PLUGIN_NAME, SMB_SIZE, g_smbFd, -1);
168 EXPECT_NE(write->shareMemoryBlock_, nullptr);
169 long bytes = BUFFER_SIZE;
170
171 EXPECT_GT(write->Write((const void*)data, sizeof(data)), 0);
172 EXPECT_TRUE(CheckBuffer(data, BUFFER_SIZE));
173 EXPECT_TRUE(write->Flush());
174 write->DoStats(bytes);
175 write->Report();
176
177 EXPECT_EQ((int)write->bytesCount_, bytes);
178 EXPECT_EQ((int)write->bytesPending_, bytes);
179 EXPECT_EQ((int)write->writeCount_, 1);
180 EXPECT_EQ((int)write->flushCount_, 1);
181
182 EXPECT_TRUE(write->Flush());
183 write->DoStats(bytes);
184 write->Report();
185
186 EXPECT_EQ((int)write->bytesCount_, bytes + bytes);
187 EXPECT_EQ((int)write->bytesPending_, bytes);
188 EXPECT_EQ((int)write->writeCount_, 2);
189 EXPECT_EQ((int)write->flushCount_, 2);
190 }
191 } // namespace
192