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 <cstring>
17 #include <dlfcn.h>
18 #include <fcntl.h>
19 #include <gtest/gtest.h>
20 #include <cinttypes>
21 #include <cstdio>
22 #include <ctime>
23 #include <unistd.h>
24
25 #include "hiperf_module.h"
26 #include "hiperf_plugin_config.pb.h"
27 #include "plugin_module_api.h"
28
29 using namespace testing::ext;
30
31 namespace {
32 const std::string DEFAULT_LIB("libhiperfplugin.z.so");
33 const std::string DEFAULT_OUT_PATH("/data/local/tmp/perf.data");
34 const int DEFAULT_WAIT = 2;
35
36 class HiperfPluginUnittest : public ::testing::Test {
37 public:
SetUpTestCase()38 static void SetUpTestCase() {};
TearDownTestCase()39 static void TearDownTestCase() {};
40
SetUp()41 void SetUp() {}
TearDown()42 void TearDown() {}
43 };
44
WriteFunc(WriterStruct* writer, const void* data, size_t size)45 long WriteFunc(WriterStruct* writer, const void* data, size_t size)
46 {
47 if (writer == nullptr || data == nullptr || size <= 0) {
48 return -1;
49 }
50
51 return 0;
52 }
53
FlushFunc(WriterStruct* writer)54 bool FlushFunc(WriterStruct* writer)
55 {
56 if (writer == nullptr) {
57 return false;
58 }
59 return true;
60 }
61
62 /**
63 * @tc.name: hiperf plugin
64 * @tc.desc: Test framework
65 * @tc.type: FUNC
66 */
HWTEST_F(HiperfPluginUnittest, TestFramework, TestSize.Level1)67 HWTEST_F(HiperfPluginUnittest, TestFramework, TestSize.Level1)
68 {
69 void* handle = dlopen(DEFAULT_LIB.c_str(), RTLD_LAZY);
70 EXPECT_NE(handle, nullptr);
71 PluginModuleStruct* plugin = reinterpret_cast<PluginModuleStruct*>(dlsym(handle, "g_pluginModule"));
72 EXPECT_NE(plugin, nullptr);
73 EXPECT_STREQ(plugin->name, "hiperf-plugin");
74
75 // set config
76 HiperfPluginConfig config;
77 config.set_outfile_name(DEFAULT_OUT_PATH);
78 config.set_record_args("-a -c 0 -d 2");
79 int size = config.ByteSizeLong();
80 ASSERT_GT(size, 0);
81 std::vector<uint8_t> configData(size);
82 ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
83
84 // test framework process
85 WriterStruct writer = {WriteFunc, FlushFunc};
86 std::vector<uint8_t> dataBuffer(plugin->resultBufferSizeHint);
87 EXPECT_EQ(plugin->callbacks->onRegisterWriterStruct(&writer), 0);
88 EXPECT_EQ(plugin->callbacks->onPluginSessionStart(configData.data(), configData.size()), 0);
89 EXPECT_EQ(plugin->callbacks->onPluginSessionStop(), 0);
90
91 dlclose(handle);
92 }
93
HWTEST_F(HiperfPluginUnittest, TestNoRecordTarget, TestSize.Level1)94 HWTEST_F(HiperfPluginUnittest, TestNoRecordTarget, TestSize.Level1)
95 {
96 HiperfPluginConfig config;
97 config.set_outfile_name(DEFAULT_OUT_PATH);
98 std::vector<uint8_t> buffer(config.ByteSizeLong());
99 ASSERT_TRUE(config.SerializeToArray(buffer.data(), buffer.size())) << "proto serialize FAILED!";
100
101 ASSERT_NE(HiperfPluginSessionStart(buffer.data(), buffer.size()), 0) << "hiperf should return failed";
102 }
103
HWTEST_F(HiperfPluginUnittest, TestRepeatOutput, TestSize.Level1)104 HWTEST_F(HiperfPluginUnittest, TestRepeatOutput, TestSize.Level1)
105 {
106 HiperfPluginConfig config;
107 config.set_log_level(HiperfPluginConfig_LogLevel_MUCH);
108 config.set_outfile_name(DEFAULT_OUT_PATH); // 1: set output file
109 // 2: set output file by "-o"
110 config.set_record_args("-a -c 0 -d 2 -o /data/local/tmp/perf.data2");
111 std::vector<uint8_t> buffer(config.ByteSizeLong());
112 ASSERT_TRUE(config.SerializeToArray(buffer.data(), buffer.size())) << "proto serialize FAILED!";
113
114 ASSERT_NE(HiperfPluginSessionStart(buffer.data(), buffer.size()), 0) << "hiperf should return failed";
115 }
116
HWTEST_F(HiperfPluginUnittest, TestRepeatStart, TestSize.Level1)117 HWTEST_F(HiperfPluginUnittest, TestRepeatStart, TestSize.Level1)
118 {
119 HiperfPluginConfig config;
120 config.set_log_level(HiperfPluginConfig_LogLevel_VERBOSE);
121 config.set_outfile_name(DEFAULT_OUT_PATH);
122 config.set_record_args("-a -c 0 -d 2");
123 std::vector<uint8_t> buffer(config.ByteSizeLong());
124 ASSERT_TRUE(config.SerializeToArray(buffer.data(), buffer.size())) << "proto serialize FAILED!";
125
126 ASSERT_EQ(HiperfPluginSessionStart(buffer.data(), buffer.size()), 0) << "hiperf should return ok";
127 // repeate to start
128 ASSERT_NE(HiperfPluginSessionStart(buffer.data(), buffer.size()), 0) << "hiperf should return failed";
129 ASSERT_EQ(HiperfPluginSessionStop(), 0) << "hiperf should return ok";
130 }
131
HWTEST_F(HiperfPluginUnittest, TestStopBeforeHiperfExit, TestSize.Level1)132 HWTEST_F(HiperfPluginUnittest, TestStopBeforeHiperfExit, TestSize.Level1)
133 {
134 HiperfPluginConfig config;
135 config.set_log_level(HiperfPluginConfig_LogLevel_DEBUG);
136 config.set_outfile_name(DEFAULT_OUT_PATH);
137 config.set_record_args("-a -c 0 -d 20"); // hiperf will exit after 20s
138 std::vector<uint8_t> buffer(config.ByteSizeLong());
139 ASSERT_TRUE(config.SerializeToArray(buffer.data(), buffer.size())) << "proto serialize FAILED!";
140
141 ASSERT_EQ(HiperfPluginSessionStart(buffer.data(), buffer.size()), 0) << "hiperf should return ok";
142
143 sleep(DEFAULT_WAIT);
144 ASSERT_EQ(HiperfPluginSessionStop(), 0) << "hiperf should return ok";
145 }
146
HWTEST_F(HiperfPluginUnittest, TestStopAfterHiperfExit, TestSize.Level1)147 HWTEST_F(HiperfPluginUnittest, TestStopAfterHiperfExit, TestSize.Level1)
148 {
149 HiperfPluginConfig config;
150 config.set_outfile_name(DEFAULT_OUT_PATH);
151 config.set_record_args("-a -c 0 -d 1"); // hiperf will exit after 1s
152 std::vector<uint8_t> buffer(config.ByteSizeLong());
153 ASSERT_TRUE(config.SerializeToArray(buffer.data(), buffer.size())) << "proto serialize FAILED!";
154
155 ASSERT_EQ(HiperfPluginSessionStart(buffer.data(), buffer.size()), 0) << "hiperf should return ok";
156 sleep(DEFAULT_WAIT);
157 ASSERT_EQ(HiperfPluginSessionStop(), 0) << "hiperf should return ok";
158 }
159
CheckRecordFile(const std::string& fileName)160 void CheckRecordFile(const std::string& fileName)
161 {
162 ASSERT_EQ(access(fileName.c_str(), F_OK), 0) << "perf.data should be exist";
163
164 std::unique_ptr<FILE, int (*)(FILE*)> fp(fopen(fileName.c_str(), "rb"), fclose);
165 ASSERT_NE(fp, nullptr);
166
167 constexpr long perfDataHeaderLen = 13 * 8;
168 fseek(fp.get(), 0, SEEK_END);
169 ASSERT_GE(ftell(fp.get()), perfDataHeaderLen) << "perf.data should have data";
170 fseek(fp.get(), 0, SEEK_SET);
171
172 char buff[perfDataHeaderLen] = {0};
173 long rLen = fread(buff, 1, perfDataHeaderLen, fp.get());
174 ASSERT_EQ(rLen, perfDataHeaderLen);
175 ASSERT_EQ(strncmp(buff, "PERFILE2", strlen("PERFILE2")), 0) << "perf.data magic error";
176 }
177
HWTEST_F(HiperfPluginUnittest, TestCheckOutputFile, TestSize.Level1)178 HWTEST_F(HiperfPluginUnittest, TestCheckOutputFile, TestSize.Level1)
179 {
180 HiperfPluginConfig config;
181 config.set_outfile_name(DEFAULT_OUT_PATH);
182 config.set_record_args("-a -c 0 -d 2");
183 std::vector<uint8_t> buffer(config.ByteSizeLong());
184 ASSERT_TRUE(config.SerializeToArray(buffer.data(), buffer.size())) << "proto serialize FAILED!";
185
186 ASSERT_EQ(HiperfPluginSessionStart(buffer.data(), buffer.size()), 0) << "hiperf should return ok";
187 sleep(DEFAULT_WAIT);
188 ASSERT_EQ(HiperfPluginSessionStop(), 0) << "hiperf should return ok";
189
190 CheckRecordFile(DEFAULT_OUT_PATH);
191 }
192 } // namespace
193