1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2022. 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 #include <cstring>
16 #include <dlfcn.h>
17 #include <fcntl.h>
18 #include <gtest/gtest.h>
19 #include <cinttypes>
20 #include <cstdio>
21 #include <ctime>
22 #include <unistd.h>
23 
24 #include "hisysevent_plugin.h"
25 #include "plugin_module_api.h"
26 
27 using namespace testing::ext;
28 
29 namespace {
30 const int US_PER_S = 1000000;
31 const int DEFAULT_WAIT = 5;
32 
33 std::atomic<uint64_t> g_testId(1);
34 
35 std::vector<HisyseventInfo> g_proto;
36 
37 class HisyseventPluginTest : public ::testing::Test {
38 public:
SetUpTestCase()39     static void SetUpTestCase() {};
TearDownTestCase()40     static void TearDownTestCase() {};
41 
SetUp()42     void SetUp() {}
TearDown()43     void TearDown() {}
44 };
45 
WriteFunc(WriterStruct* writer, const void* data, size_t size)46 long WriteFunc(WriterStruct* writer, const void* data, size_t size)
47 {
48     if (writer == nullptr || data == nullptr || size <= 0) {
49         return -1;
50     }
51 
52     HisyseventInfo info;
53     if (info.ParseFromArray(data, size) <= 0) {
54         return -1;
55     }
56     g_proto.push_back(info);
57     return 0;
58 }
59 
FlushFunc(WriterStruct* writer)60 bool FlushFunc(WriterStruct* writer)
61 {
62     if (writer == nullptr) {
63         return false;
64     }
65     return true;
66 }
67 
PluginStart(HisyseventPlugin& plugin, HisyseventConfig& config)68 bool PluginStart(HisyseventPlugin& plugin, HisyseventConfig& config)
69 {
70     // serialize
71     int size = config.ByteSizeLong();
72     std::vector<uint8_t> configData(size);
73     int ret = config.SerializeToArray(configData.data(), configData.size());
74     CHECK_TRUE(ret > 0, false, "HisyseventPluginTest: SerializeToArray fail!!!");
75     PROFILER_LOG_INFO(LOG_CORE, "HisyseventPluginTest: SerializeToArray success");
76 
77     // start
78     ret = plugin.Start(configData.data(), configData.size());
79     CHECK_TRUE(ret == 0, false, "HisyseventPluginTest: start plugin fail!!!");
80     PROFILER_LOG_INFO(LOG_CORE, "HisyseventPluginTest: Start success");
81 
82     return true;
83 }
84 
85 /**
86  * @tc.name: hisysevent plugin
87  * @tc.desc: Test default cmd
88  * @tc.type: FUNC
89  * @tc.require: issueI5UGTK
90  */
HWTEST_F(HisyseventPluginTest, TestDefaultCmd, TestSize.Level1)91 HWTEST_F(HisyseventPluginTest, TestDefaultCmd, TestSize.Level1)
92 {
93     HisyseventConfig config;
94     HisyseventPlugin plugin;
95     WriterStruct writer = {WriteFunc, FlushFunc};
96 
97     g_proto.erase(g_proto.begin(), g_proto.end());
98     // set config
99     config.set_msg("Hisysevent Config.");
100 
101     // test plugin process
102     plugin.SetWriter(&writer);
103     EXPECT_TRUE(PluginStart(plugin, config));
104     usleep(US_PER_S * DEFAULT_WAIT); // 5s
105     EXPECT_EQ(plugin.Stop(), 0);
106 
107     // test proto data
108     int protoSize = g_proto.size();
109     EXPECT_TRUE(protoSize >= 0);
110     g_testId = 1;
111     for (int i = 0; i < protoSize; i++) {
112         HisyseventInfo info = g_proto[i];
113         for (int j = 0; j < info.info_size(); j++) {
114             EXPECT_EQ(info.info(j).id(), g_testId);
115             g_testId++;
116         }
117     }
118 }
119 
120 /**
121  * @tc.name: hisysevent plugin
122  * @tc.desc: Framework test
123  * @tc.type: FUNC
124  * @tc.require: issueI5UGTK
125  */
HWTEST_F(HisyseventPluginTest, TestFramework, TestSize.Level1)126 HWTEST_F(HisyseventPluginTest, TestFramework, TestSize.Level1)
127 {
128     std::string path = std::string("libhisyseventplugin.z.so");
129     void* handle = dlopen(path.c_str(), RTLD_LAZY);
130     EXPECT_NE(handle, nullptr);
131     PluginModuleStruct* plugin = reinterpret_cast<PluginModuleStruct*>(dlsym(handle, "g_pluginModule"));
132     EXPECT_NE(plugin, nullptr);
133     EXPECT_STREQ(plugin->name, "hisysevent-plugin");
134 
135     g_testId = 1;
136     g_proto.erase(g_proto.begin(), g_proto.end());
137 
138     // set config
139     HisyseventConfig config;
140     config.set_msg("Hisysevent Config.");
141     int size = config.ByteSizeLong();
142     ASSERT_GT(size, 0);
143     std::vector<uint8_t> configData(size);
144     ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
145 
146     // test framework process
147     WriterStruct writer = {WriteFunc, FlushFunc};
148     std::vector<uint8_t> dataBuffer(plugin->resultBufferSizeHint);
149     EXPECT_EQ(plugin->callbacks->onRegisterWriterStruct(&writer), 0);
150     EXPECT_EQ(plugin->callbacks->onPluginSessionStart(configData.data(), configData.size()), 0);
151     usleep(US_PER_S * DEFAULT_WAIT); // 5s
152     EXPECT_EQ(plugin->callbacks->onPluginSessionStop(), 0);
153 
154     // test proto data
155     int protoSize = g_proto.size();
156     EXPECT_TRUE(protoSize >= 0);
157     g_testId = 1;
158     for (int i = 0; i < protoSize; i++) {
159         HisyseventInfo info = g_proto[i];
160         for (int j = 0; j < info.info_size(); j++) {
161             EXPECT_EQ(info.info(j).id(), g_testId);
162             g_testId++;
163         }
164     }
165 }
166 
167 /**
168  * @tc.name: hisysevent plugin
169  * @tc.desc: start fail test
170  * @tc.type: FUNC
171  * @tc.require: issueI5UGTK
172  */
HWTEST_F(HisyseventPluginTest, TestStartFail, TestSize.Level1)173 HWTEST_F(HisyseventPluginTest, TestStartFail, TestSize.Level1)
174 {
175     HisyseventConfig config;
176     HisyseventPlugin plugin;
177     WriterStruct writer = {WriteFunc, FlushFunc};
178 
179     g_testId = 1;
180     g_proto.erase(g_proto.begin(), g_proto.end());
181     // set config
182     config.set_msg("H");
183 
184     // test plugin process
185     plugin.SetWriter(&writer);
186 
187     // serialize
188     int size = config.ByteSizeLong();
189     ASSERT_GT(size, 0);
190     std::vector<uint8_t> configData(size);
191     ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
192 
193     // start
194     EXPECT_EQ(plugin.Start(configData.data(), 0), 0);
195     usleep(US_PER_S * DEFAULT_WAIT); // 5s
196     plugin.Stop();
197 
198     EXPECT_NE(plugin.Start(nullptr, configData.size()), 0);
199     EXPECT_EQ(plugin.Start(configData.data(), configData.size()), 0);
200     usleep(US_PER_S * DEFAULT_WAIT); // 5s
201     plugin.Stop();
202 }
203 
204 /**
205  * @tc.name: hisysevent plugin
206  * @tc.desc: customer popen test
207  * @tc.type: FUNC
208  */
HWTEST_F(HisyseventPluginTest, TestCustomPopenClose, TestSize.Level1)209 HWTEST_F(HisyseventPluginTest, TestCustomPopenClose, TestSize.Level1)
210 {
211     HisyseventConfig config;
212     HisyseventPlugin plugin;
213     WriterStruct writer = {WriteFunc, FlushFunc};
214     plugin.SetWriter(&writer);
215     // set config
216     config.set_msg("H");
217     int size = config.ByteSizeLong();
218     std::vector<uint8_t> configData(size);
219     config.SerializeToArray(configData.data(), configData.size());
220     EXPECT_EQ(plugin.Start(configData.data(), configData.size()), 0);
221     EXPECT_EQ(plugin.GetFullCmd(), "/system/bin/hisysevent hisysevent -rd");
222     std::vector<std::string> fullCmdTest;
223     fullCmdTest.push_back("/system/bin/hisysevent");
224     fullCmdTest.push_back("hisysevent");
225     fullCmdTest.push_back("-rd");
226     volatile pid_t childPid = -1;
227     int pipeFds[2] = {-1, -1};
228     FILE* fpr = COMMON::CustomPopen(fullCmdTest, nullptr, pipeFds, childPid, true);
229     EXPECT_EQ(fpr, nullptr);
230     EXPECT_EQ(COMMON::CustomPclose(fpr, pipeFds, childPid, true), -1);
231 
232     childPid = -1;
233     pipeFds[0] = -1;
234     pipeFds[1] = -1;
235     FILE* fpw = COMMON::CustomPopen(fullCmdTest, "w", pipeFds, childPid);
236     EXPECT_NE(fpw, nullptr);
237     EXPECT_EQ(COMMON::CustomPclose(fpw, pipeFds, childPid, true), -1);
238     usleep(US_PER_S * DEFAULT_WAIT); // 5s
239     plugin.Stop();
240 }
241 }