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 #include "logging.h"
24
25 using namespace testing::ext;
26
27 namespace {
28 constexpr uint32_t BUFFER_SIZE = 1024;
29 constexpr uint32_t SMB_SIZE = 10 * 4096;
30 const std::string SMB_NAME = "stackwritertest";
31 const std::string PLUGIN_NAME = "stackwriter";
32 void* g_smbAddr = nullptr;
33 int g_smbFd = 0;
34
InitShareMemory()35 int InitShareMemory()
36 {
37 int fd = syscall(SYS_memfd_create, SMB_NAME.c_str(), 0);
38 CHECK_TRUE(fd >= 0, -1, "CreateBlock FAIL SYS_memfd_create");
39
40 int check = ftruncate(fd, SMB_SIZE);
41 if (check < 0) {
42 close(fd);
43 const int bufSize = 256;
44 char buf[bufSize] = { 0 };
45 strerror_r(errno, buf, bufSize);
46 HILOG_ERROR(LOG_CORE, "CreateBlock ftruncate ERR : %s", buf);
47 return -1;
48 }
49
50 g_smbAddr = mmap(nullptr, SMB_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
51 if (g_smbAddr == (reinterpret_cast<void *>(-1))) {
52 close(fd);
53 const int bufSize = 256;
54 char buf[bufSize] = { 0 };
55 strerror_r(errno, buf, bufSize);
56 HILOG_ERROR(LOG_CORE, "CreateBlock g_smbAddr mmap ERR : %s", buf);
57 return -1;
58 }
59
60 ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr);
61
62 // initialize header infos
63 header_->info.readOffset_ = 0;
64 header_->info.writeOffset_ = 0;
65 header_->info.memorySize_ = SMB_SIZE - sizeof(ShareMemoryBlock::BlockHeader);
66 header_->info.bytesCount_ = 0;
67 header_->info.chunkCount_ = 0;
68
69 return fd;
70 }
71
72 class StackWriterTest : public ::testing::Test {
73 public:
SetUpTestCase()74 static void SetUpTestCase() {}
TearDownTestCase()75 static void TearDownTestCase() {}
76
SetUp()77 void SetUp()
78 {
79 g_smbFd = InitShareMemory();
80 }
TearDown()81 void TearDown()
82 {
83 g_smbFd = 0;
84 }
85 };
86
CheckBuffer(uint8_t * buffer,size_t size)87 bool CheckBuffer(uint8_t* buffer, size_t size)
88 {
89 ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr);
90 uint8_t* cmpaddr = (uint8_t*)g_smbAddr + sizeof(ShareMemoryBlock::BlockHeader) + header_->info.readOffset_;
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
192 /**
193 * @tc.name: StackWriter
194 * @tc.desc: Write data to shared memory with blocked mode.
195 * @tc.type: FUNC
196 */
197 HWTEST_F(StackWriterTest, WriterSyncTest, TestSize.Level1)
198 {
199 auto write = std::make_shared<StackWriter>(PLUGIN_NAME, SMB_SIZE, g_smbFd, -1, true);
200 EXPECT_NE(write->shareMemoryBlock_, nullptr);
201 uint8_t buffer1[] = {0x55, 0xAA, 0x55, 0xAA};
202 uint8_t buffer2[] = {0x11, 0x22, 0x33, 0x44};
203 uint8_t buffer3[] = {0xAA, 0xBB, 0xCC, 0xDD};
204 uint8_t buffer4[] = {0xCC, 0xDD, 0xBB, 0xEE};
205
206 EXPECT_TRUE(write->WriteWithPayloadTimeout((const void*)buffer1, sizeof(buffer1),
207 (const void*)buffer2, sizeof(buffer2)));
208 EXPECT_TRUE(CheckBuffer(buffer1, sizeof(buffer1)));
209 EXPECT_TRUE(write->WriteWithPayloadTimeout((const void*)buffer3, sizeof(buffer3),
210 (const void*)buffer4, sizeof(buffer4)));
211 EXPECT_TRUE(CheckBuffer(buffer3, sizeof(buffer3)));
212 EXPECT_FALSE(write->Write(nullptr, 0));
213 }
214 } // namespace
215