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 <thread>
17 #include <unistd.h>
18 
19 #include <gtest/gtest.h>
20 #include "logging.h"
21 #include "profiler_data_repeater.h"
22 
23 using namespace testing::ext;
24 
25 namespace {
26 class ProfilerDataRepeaterTest : public ::testing::Test {
27 protected:
SetUpTestCase()28     static void SetUpTestCase() {}
TearDownTestCase()29     static void TearDownTestCase() {}
30 
31     void SetUp() override {}
32     void TearDown() override {}
33 };
34 
35 /**
36  * @tc.name: server
37  * @tc.desc: put plugin data.
38  * @tc.type: FUNC
39  */
HWTEST_F(ProfilerDataRepeaterTest, PutPluginData, TestSize.Level1)40 HWTEST_F(ProfilerDataRepeaterTest, PutPluginData, TestSize.Level1)
41 {
42     const int bufferSize = 10;
43     auto dataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
44     ASSERT_NE(dataRepeater, nullptr);
45 
46     for (int i = 0; i < bufferSize; i++) {
47         auto data = std::make_shared<ProfilerPluginData>();
48         dataRepeater->PutPluginData(data);
49         EXPECT_EQ(dataRepeater->Size(), i + 1);
50     }
51 }
52 
53 /**
54  * @tc.name: server
55  * @tc.desc: take plugin data.
56  * @tc.type: FUNC
57  */
HWTEST_F(ProfilerDataRepeaterTest, TakePluginData, TestSize.Level1)58 HWTEST_F(ProfilerDataRepeaterTest, TakePluginData, TestSize.Level1)
59 {
60     const int bufferSize = 10;
61     const int itemCounts = 10000;
62     auto inDataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
63     ASSERT_NE(inDataRepeater, nullptr);
64 
65     auto outDataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
66     ASSERT_NE(outDataRepeater, nullptr);
67 
68     auto f = [](int x) { return 2 * x + 1; };
69 
70     std::thread worker([&]() {
71         for (int i = 0; i < itemCounts; i++) {
72             auto itemX = inDataRepeater->TakePluginData();
73 
74             // compute in worker thread
75             int x = itemX ? std::stoi(itemX->data()) : 0;
76             int y = f(x);
77 
78             auto itemY = std::make_shared<ProfilerPluginData>();
79             itemY->set_data(std::to_string(y));
80             outDataRepeater->PutPluginData(itemY);
81         }
82     });
83 
84     for (int i = 0; i < itemCounts; i++) {
85         int x0 = i;
86         auto itemX = std::make_shared<ProfilerPluginData>();
87         itemX->set_data(std::to_string(x0));
88         inDataRepeater->PutPluginData(itemX);
89 
90         auto itemY = outDataRepeater->TakePluginData();
91         int y = itemY ? std::stoi(itemY->data()) : 0;
92 
93         // redo compute in main thread
94         int y0 = f(x0);
95 
96         // check results
97         EXPECT_EQ(y, y0);
98     }
99     worker.join();
100 }
101 
102 /**
103  * @tc.name: server
104  * @tc.desc: take plugin profiler data.
105  * @tc.type: FUNC
106  */
HWTEST_F(ProfilerDataRepeaterTest, TakePluginDataVec, TestSize.Level1)107 HWTEST_F(ProfilerDataRepeaterTest, TakePluginDataVec, TestSize.Level1)
108 {
109     const int itemCounts = 10000;
110     const int bufferSize = itemCounts;
111     auto inDataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
112     ASSERT_NE(inDataRepeater, nullptr);
113 
114     auto outDataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
115     ASSERT_NE(outDataRepeater, nullptr);
116 
117     auto f = [](int x) { return 2 * x + 1; };
118     std::thread worker([&]() {
119         for (int i = 0; i < itemCounts; i++) {
120             auto xData = inDataRepeater->TakePluginData();
121 
122             // compute in worker thread
123             int x = xData ? std::stoi(xData->data()) : 0;
124             int y = f(x);
125 
126             auto yData = std::make_shared<ProfilerPluginData>();
127             yData->set_data(std::to_string(y));
128             outDataRepeater->PutPluginData(yData);
129         }
130     });
131 
132     std::vector<int> yVec;
133     for (int i = 0; i < itemCounts; i++) {
134         int x0 = i;
135         auto xData = std::make_shared<ProfilerPluginData>();
136         xData->set_data(std::to_string(x0));
137         inDataRepeater->PutPluginData(xData);
138 
139         int y0 = f(x0);
140         yVec.push_back(y0);
141     }
142     worker.join();
143 
144     std::vector<ProfilerPluginDataPtr> pluginDataVec;
145     auto count = outDataRepeater->TakePluginData(pluginDataVec);
146     EXPECT_EQ(count, yVec.size());
147 
148     for (size_t i = 0; i < pluginDataVec.size(); i++) {
149         auto yData = pluginDataVec[i];
150         int y = yData ? std::stoi(yData->data()) : 0;
151         EXPECT_EQ(y, yVec[i]);
152     }
153 }
154 
155 /**
156  * @tc.name: server
157  * @tc.desc: close plugin profiler data.
158  * @tc.type: FUNC
159  */
HWTEST_F(ProfilerDataRepeaterTest, Close, TestSize.Level1)160 HWTEST_F(ProfilerDataRepeaterTest, Close, TestSize.Level1)
161 {
162     const int bufferSize = 10;
163     auto dataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
164     ASSERT_NE(dataRepeater, nullptr);
165 
166     dataRepeater->Close();
167 }
168 
169 /**
170  * @tc.name: server
171  * @tc.desc: reset plugin profiler data.
172  * @tc.type: FUNC
173  */
HWTEST_F(ProfilerDataRepeaterTest, Reset, TestSize.Level1)174 HWTEST_F(ProfilerDataRepeaterTest, Reset, TestSize.Level1)
175 {
176     const int bufferSize = 10;
177     auto dataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
178     ASSERT_NE(dataRepeater, nullptr);
179 
180     dataRepeater->Reset();
181 }
182 
183 /**
184  * @tc.name: server
185  * @tc.desc: close plugin profiler data.
186  * @tc.type: FUNC
187  */
HWTEST_F(ProfilerDataRepeaterTest, CloseWithFastProducer, TestSize.Level1)188 HWTEST_F(ProfilerDataRepeaterTest, CloseWithFastProducer, TestSize.Level1)
189 {
190     const int bufferSize = 10;
191     const int numProducts = 20;
192     auto dataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
193     ASSERT_NE(dataRepeater, nullptr);
194 
195     std::thread producer([=]() {
196         for (int i = 0; i < numProducts; i++) {
197             auto data = std::make_shared<ProfilerPluginData>();
198             if (!dataRepeater->PutPluginData(data)) {
199                 PROFILER_LOG_DEBUG(LOG_CORE, "put data %d FAILED!", i);
200                 break;
201             }
202         }
203     });
204 
205     const int consumeDelayUs = 50 * 1000;
206     std::thread consumer([=]() {
207         for (int i = 0; i < numProducts; i++) {
208             auto data = dataRepeater->TakePluginData();
209             if (!data) {
210                 PROFILER_LOG_DEBUG(LOG_CORE, "get data %d FAILED!", i);
211                 break;
212             }
213             usleep(consumeDelayUs);
214         }
215     });
216 
217     usleep(consumeDelayUs * 3);
218     dataRepeater->Close();
219     producer.join();
220     consumer.join();
221 }
222 } // namespace