1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 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 <gtest/gtest.h> 17#include <sys/mman.h> 18#include <sys/syscall.h> 19#include "buffer_writer.h" 20#include "plugin_service_types.pb.h" 21 22using namespace testing::ext; 23 24namespace { 25constexpr uint32_t SMB1_SIZE = 10 * 4096; 26constexpr uint32_t SMB2_SIZE = 10 * 4096; 27const std::string SMB1_NAME = "testsmb1"; 28const std::string SMB2_NAME = "testsmb2"; 29const std::string PLUGIN_NAME = "testplugin"; 30const std::string PLUGIN_VERSION = "1.01"; 31void *g_smbAddr1 = nullptr; 32void *g_smbAddr2 = nullptr; 33int g_smbFd1 = 0; 34int g_smbFd2 = 0; 35 36int InitShareMemory1() 37{ 38 int fd = syscall(SYS_memfd_create, SMB1_NAME.c_str(), 0); 39 CHECK_TRUE(fd >= 0, -1, "CreateBlock FAIL SYS_memfd_create"); 40 41 int check = ftruncate(fd, SMB1_SIZE); 42 if (check < 0) { 43 close(fd); 44 const int bufSize = 256; 45 char buf[bufSize] = { 0 }; 46 strerror_r(errno, buf, bufSize); 47 PROFILER_LOG_ERROR(LOG_CORE, "CreateBlock ftruncate ERR : %s", buf); 48 return -1; 49 } 50 51 g_smbAddr1 = mmap(nullptr, SMB1_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 52 if (g_smbAddr1 == static_cast<void*>(MAP_FAILED)) { 53 close(fd); 54 const int bufSize = 256; 55 char buf[bufSize] = { 0 }; 56 strerror_r(errno, buf, bufSize); 57 PROFILER_LOG_ERROR(LOG_CORE, "CreateBlock g_smbAddr1 mmap ERR : %s", buf); 58 return -1; 59 } 60 61 ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr1); 62 63 // initialize header infos 64 header_->info.readOffset_ = 0; 65 header_->info.writeOffset_ = 0; 66 header_->info.memorySize_ = SMB1_SIZE - sizeof(ShareMemoryBlock::BlockHeader); 67 header_->info.bytesCount_ = 0; 68 header_->info.chunkCount_ = 0; 69 70 return fd; 71} 72 73int InitShareMemory2() 74{ 75 int fd = syscall(SYS_memfd_create, SMB2_NAME.c_str(), 0); 76 CHECK_TRUE(fd >= 0, -1, "CreateBlock FAIL SYS_memfd_create"); 77 78 int check = ftruncate(fd, SMB2_SIZE); 79 if (check < 0) { 80 close(fd); 81 const int bufSize = 256; 82 char buf[bufSize] = { 0 }; 83 strerror_r(errno, buf, bufSize); 84 PROFILER_LOG_ERROR(LOG_CORE, "CreateBlock ftruncate ERR : %s", buf); 85 return -1; 86 } 87 88 g_smbAddr2 = mmap(nullptr, SMB2_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 89 if (g_smbAddr2 == static_cast<void*>(MAP_FAILED)) { 90 close(fd); 91 const int bufSize = 256; 92 char buf[bufSize] = { 0 }; 93 strerror_r(errno, buf, bufSize); 94 PROFILER_LOG_ERROR(LOG_CORE, "CreateBlock g_smbAddr2 mmap ERR : %s", buf); 95 return -1; 96 } 97 98 ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr2); 99 100 // initialize header infos 101 header_->info.readOffset_ = 0; 102 header_->info.writeOffset_ = 0; 103 header_->info.memorySize_ = SMB2_SIZE - sizeof(ShareMemoryBlock::BlockHeader); 104 header_->info.bytesCount_ = 0; 105 header_->info.chunkCount_ = 0; 106 107 return fd; 108} 109 110class BufferWriteTest : public ::testing::Test { 111protected: 112 static void SetUpTestCase() 113 { 114 g_smbFd1 = InitShareMemory1(); 115 g_smbFd2 = InitShareMemory2(); 116 } 117 static void TearDownTestCase() {} 118}; 119 120bool CheckBuffer(uint8_t *buffer, size_t size) 121{ 122 ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr1); 123 uint8_t *cmpaddr = (uint8_t *)g_smbAddr1 + sizeof(ShareMemoryBlock::BlockHeader) + header_->info.readOffset_.load(); 124 uint32_t cmpsize = *(uint32_t*)cmpaddr; 125 cmpaddr = cmpaddr + sizeof(uint32_t); 126 ProfilerPluginData pluginData; 127 pluginData.ParseFromArray(cmpaddr, cmpsize); 128 const char* data = pluginData.data().c_str(); 129 130 header_->info.readOffset_ = header_->info.writeOffset_.load(); 131 if (memcmp(buffer, data, size) == 0) { 132 return true; 133 } 134 return false; 135} 136 137 138bool CheckMessage(uint8_t *buffer, size_t size) 139{ 140 ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr2); 141 uint8_t *cmpaddr = (uint8_t *)g_smbAddr2 + sizeof(ShareMemoryBlock::BlockHeader) + header_->info.readOffset_.load(); 142 cmpaddr = cmpaddr + sizeof(uint32_t); 143 header_->info.readOffset_ = header_->info.writeOffset_.load(); 144 145 if (memcmp(buffer, cmpaddr, size) == 0) { 146 return true; 147 } 148 return false; 149} 150 151/** 152 * @tc.name: plugin 153 * @tc.desc: Write data to shared memory through writer. 154 * @tc.type: FUNC 155 */ 156HWTEST_F(BufferWriteTest, WriteTest, TestSize.Level1) 157{ 158 auto write = std::make_shared<BufferWriter>(PLUGIN_NAME, PLUGIN_VERSION, SMB1_SIZE, g_smbFd1, -1, 0); 159 uint8_t buffer1[] = {0x55, 0xAA, 0x55, 0xAA}; 160 uint8_t buffer2[] = {0x11, 0x22, 0x33, 0x44}; 161 uint8_t buffer3[] = {0xAA, 0xBB, 0xCC, 0xDD}; 162 EXPECT_TRUE(write->Write(buffer1, sizeof(buffer1))); 163 EXPECT_TRUE(CheckBuffer(buffer1, sizeof(buffer1))); 164 165 EXPECT_TRUE(write->Write(buffer2, sizeof(buffer2))); 166 EXPECT_TRUE(CheckBuffer(buffer2, sizeof(buffer2))); 167 168 EXPECT_TRUE(write->Write(buffer3, sizeof(buffer3))); 169 EXPECT_TRUE(CheckBuffer(buffer3, sizeof(buffer3))); 170 EXPECT_FALSE(write->Write(nullptr, 0)); 171} 172 173/** 174 * @tc.name: plugin 175 * @tc.desc: Write data to shared memory through writer. 176 * @tc.type: FUNC 177 */ 178HWTEST_F(BufferWriteTest, WriteMessageTest, TestSize.Level1) 179{ 180 uint8_t data[1024]; 181 auto write = std::make_shared<BufferWriter>(PLUGIN_NAME, PLUGIN_VERSION, SMB2_SIZE, g_smbFd2, -1, 0); 182 183 ProfilerPluginConfig configData; 184 configData.set_name("111"); 185 configData.set_plugin_sha256("222"); 186 configData.set_sample_interval(1000); 187 size_t size = configData.ByteSizeLong(); 188 configData.SerializeToArray(data, size); 189 190 EXPECT_TRUE(write->WriteMessage(configData, "111")); 191 EXPECT_TRUE(CheckMessage(data, size)); 192 193 ProfilerPluginState stateData; 194 stateData.set_name("st"); 195 stateData.set_state(ProfilerPluginState::IN_SESSION); 196 size = stateData.ByteSizeLong(); 197 stateData.SerializeToArray(data, size); 198 199 EXPECT_TRUE(write->WriteMessage(stateData, "111")); 200 EXPECT_TRUE(CheckMessage(data, size)); 201 202 203 ProfilerPluginData pluginData; 204 pluginData.set_name("test"); 205 pluginData.set_status(1); 206 struct timespec ts; 207 clock_gettime(CLOCK_REALTIME, &ts); 208 pluginData.set_clock_id(ProfilerPluginData::CLOCKID_REALTIME); 209 pluginData.set_tv_sec(ts.tv_sec); 210 pluginData.set_tv_nsec(ts.tv_nsec); 211 size = pluginData.ByteSizeLong(); 212 pluginData.SerializeToArray(data, size); 213 214 EXPECT_TRUE(write->WriteMessage(pluginData, "111")); 215 EXPECT_TRUE(CheckMessage(data, size)); 216} 217} // namespace