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 <cstring>
17 #ifdef __LINUX__
18 #   include <unistd.h>
19 #   include <fcntl.c>
20 #endif
21 
22 #include "gtest/gtest.h"
23 
24 #include "client_executor/include/i_aie_client.inl"
25 #include "platform/time/include/time.h"
26 #include "protocol/retcode_inner/aie_retcode_inner.h"
27 #include "service_dead_cb.h"
28 #include "utils/aie_macros.h"
29 #include "utils/log/aie_log.h"
30 
31 using namespace OHOS::AI;
32 using namespace testing::ext;
33 
34 namespace {
35     const int REQUEST_ID = 1;
36     const int OPERATE_ID = 2;
37     const long long CLIENT_INFO_VERSION = 1;
38     const int SESSION_ID = -1;
39     const long long ALGORITHM_INFO_CLIENT_VERSION = 1;
40     const int ALGORITHM_ASYNC_TYPE = 1;
41     const long long ALGORITHM_VERSION = 1;
42     const int EXECUTE_TIMES = 100;
43     const int COUNT = 20;
44     const int CHAR_TYPE = 4;
45     const int DESCRIPTION_LENGTH = 129;
46     const int ALPHABET_LENGTH = 26;
47     const int DIGIT = 10;
48     const int UPPER_POSITION = 1;
49     const int LOWER_POSITION = 2;
50     const int SPACE_POSITION = 3;
51     const int SLEEP_TIME = 2;
52     const char MIN_UPPER_CASE_CHAR = 'A';
53     const char MIN_LOWER_CASE_CHAR = 'a';
54     const char MIN_NUMERIC_CHAR = '0';
55     const char TRAILING_CHAR = '\0';
56     const char * const PREPARE_INPUT_ASYNC = "Async prepare inputData";
57     const int EXCEPTED_INIT_TIME = 30;
58     const int EXCEPTED_PREPARE_TIME = 70;
59     const int EXCEPTED_ASYNC_PROCESS_TIME = 40;
60     const int EXCEPTED_RELEASE_TIME = 70;
61     const int EXCEPTED_DESTROY_TIME = 30;
62     const int EXCEPTED_SETOPTION_TIME = 30;
63     const int EXCEPTED_GETOPTION_TIME = 30;
64     std::time_t g_processStartTime;
65     long long g_processTotalTime;
66     long long g_initTotalTime;
67     long long g_prepareTotalTime;
68     long long g_setOptionTotalTime;
69     long long g_getOptionTotalTime;
70     long long g_releaseTotalTime;
71     long long g_destroyTotalTime;
72 }
73 
74 class ClientCallback : public IClientCb {
75 public:
76     ClientCallback() = default;
77     ~ClientCallback() override = default;
OnResult(const DataInfo & result,int resultCode,int requestId)78     void OnResult(const DataInfo &result, int resultCode, int requestId) override
79     {
80         std::time_t processEndTime = GetCurTimeMillSec();
81         g_processTotalTime += processEndTime - g_processStartTime;
82         HILOGI("[Test][AsyncProcess][%lld]", processEndTime - g_processStartTime);
83     }
84 };
85 
Random(void)86 static int Random(void)
87 {
88 #ifndef __LINUX__
89     return -1;
90 #else
91 #ifndef O_RDONLY
92 #define O_RDONLY 0u
93 #endif
94     int r = -1;
95     int fd = open("/dev/random", O_RDONLY);
96     if (fd > 0) {
97         (void)read(fd, &r, sizeof(int));
98     }
99     (void)close(fd);
100 
101     return r;
102 #endif
103 }
104 
RandStr(const int len,char * str)105 static void RandStr(const int len, char *str)
106 {
107     int i;
108     for (i = 0; i < len - 1; ++i) {
109         switch (Random() % CHAR_TYPE) {
110             case UPPER_POSITION:
111                 str[i] = MIN_UPPER_CASE_CHAR + Random() % ALPHABET_LENGTH;
112                 break;
113             case LOWER_POSITION:
114                 str[i] = MIN_LOWER_CASE_CHAR + Random() % ALPHABET_LENGTH;
115                 break;
116             case SPACE_POSITION:
117                 str[i] = ' ';
118                 break;
119             default:
120                 str[i] = MIN_NUMERIC_CHAR + Random() % DIGIT;
121                 break;
122         }
123     }
124 
125     str[i] = TRAILING_CHAR;
126 }
127 
128 class AsyncProcessTimeTest : public testing::Test {
129 public:
130     // SetUpTestCase:The preset action of the test suite is executed before the first TestCase
SetUpTestCase()131     static void SetUpTestCase() {};
132 
133     // TearDownTestCase:The test suite cleanup action is executed after the last TestCase
TearDownTestCase()134     static void TearDownTestCase() {};
135 
136     // SetUp:Execute before each test case
SetUp()137     void SetUp() {};
138 
139     // TearDown:Execute after each test case
TearDown()140     void TearDown() {};
141 };
142 
CheckTimeInit()143 static void CheckTimeInit()
144 {
145     double duration = static_cast<double>(g_initTotalTime)
146                         / static_cast<double>(EXECUTE_TIMES);
147     HILOGI("[Test][CheckTimeInit][%lf]", duration);
148     ASSERT_TRUE((duration > 0) && (duration <= EXCEPTED_INIT_TIME));
149 }
150 
CheckTimePrepare()151 static void CheckTimePrepare()
152 {
153     double duration = static_cast<double>(g_prepareTotalTime)
154                         / static_cast<double>(EXECUTE_TIMES);
155     HILOGI("[Test][CheckTimePrepare][%lf]", duration);
156     ASSERT_TRUE((duration > 0) && (duration <= EXCEPTED_PREPARE_TIME));
157 }
158 
CheckTimeAsyncProcess()159 static void CheckTimeAsyncProcess()
160 {
161     double duration = static_cast<double>(g_processTotalTime)
162                         / static_cast<double>(EXECUTE_TIMES);
163     HILOGI("[Test][CheckTimeAsyncProcess][%lf]", duration);
164     ASSERT_TRUE((duration > 0) && (duration <= EXCEPTED_ASYNC_PROCESS_TIME));
165 }
166 
CheckTimeRelease()167 static void CheckTimeRelease()
168 {
169     double duration = static_cast<double>(g_releaseTotalTime)
170                         / static_cast<double>(EXECUTE_TIMES);
171     HILOGI("[Test][CheckTimeRelease][%lf]", duration);
172     ASSERT_TRUE((duration > 0) && (duration <= EXCEPTED_RELEASE_TIME));
173 }
174 
CheckTimeDestroy()175 static void CheckTimeDestroy()
176 {
177     double duration = static_cast<double>(g_destroyTotalTime)
178                         / static_cast<double>(EXECUTE_TIMES);
179     HILOGI("[Test][CheckTimeDestroy][%lf]", duration);
180     ASSERT_TRUE((duration > 0) && (duration <= EXCEPTED_DESTROY_TIME));
181 }
182 
CheckTimeSetOption()183 static void CheckTimeSetOption()
184 {
185     double duration = static_cast<double>(g_setOptionTotalTime)
186                         / static_cast<double>(EXECUTE_TIMES);
187     HILOGI("[Test][CheckTimeSetOption][%lf]", duration);
188     ASSERT_TRUE((duration > 0) && (duration <= EXCEPTED_SETOPTION_TIME));
189 }
190 
CheckTimeGetOption()191 static void CheckTimeGetOption()
192 {
193     double duration = static_cast<double>(g_getOptionTotalTime)
194                         / static_cast<double>(EXECUTE_TIMES);
195     HILOGI("[Test][CheckTimeGetOption][%lf]", duration);
196     ASSERT_TRUE((duration > 0) && (duration <= EXCEPTED_GETOPTION_TIME));
197 }
198 
199 /**
200  * @tc.name: TestAsyncTime001
201  * @tc.desc: Test Async Time Consumption of ALL Interfaces in AI System.
202  * @tc.type: PERF
203  * @tc.require: AR000F77MI
204  */
205 HWTEST_F(AsyncProcessTimeTest, TestAsyncTime001, TestSize.Level0)
206 {
207     HILOGI("[Test]AsyncProcessTimeTest001.");
208     const char *str = PREPARE_INPUT_ASYNC;
209     char *inputData = const_cast<char*>(str);
210     int len = strlen(str) + 1;
211 
212     for (int i = 0; i < COUNT; ++i) {
213         HILOGI("[Test]Test delay times:[%d]", i);
214         char config[DESCRIPTION_LENGTH];
215         RandStr(DESCRIPTION_LENGTH, config);
216         ConfigInfo configInfo {.description = config};
217         ClientInfo clientInfo = {
218                 .clientVersion = CLIENT_INFO_VERSION,
219                 .clientId = INVALID_CLIENT_ID,
220                 .sessionId = SESSION_ID,
221                 .serverUid = INVALID_UID,
222                 .clientUid = INVALID_UID,
223                 .extendLen = len,
224                 .extendMsg = reinterpret_cast<unsigned char*>(inputData),
225                 };
226 
227         AlgorithmInfo algoInfo = {
228                 .clientVersion = ALGORITHM_INFO_CLIENT_VERSION,
229                 .isAsync = true,
230                 .algorithmType = ALGORITHM_ASYNC_TYPE,
231                 .algorithmVersion = ALGORITHM_VERSION,
232                 .isCloud = true,
233                 .operateId = OPERATE_ID,
234                 .requestId = REQUEST_ID,
235                 .extendLen = len,
236                 .extendMsg = reinterpret_cast<unsigned char*>(inputData),
237                 };
238 
239         std::time_t initStartTime = GetCurTimeMillSec();
240         ServiceDeadCb *cb = nullptr;
241         AIE_NEW(cb, ServiceDeadCb());
242         ASSERT_NE(cb, nullptr);
243         int resultCode = AieClientInit(configInfo, clientInfo, algoInfo, cb);
244         ASSERT_EQ(resultCode, RETCODE_SUCCESS);
245         std::time_t initEndTime = GetCurTimeMillSec();
246         g_initTotalTime += initEndTime - initStartTime;
247 
248         DataInfo inputInfo = {
249                 .data = reinterpret_cast<unsigned char*>(inputData),
250                 .length = len,
251                 };
252         DataInfo outputInfo;
253 
254         ClientCallback *callback = nullptr;
255         AIE_NEW(callback, ClientCallback());
256         ASSERT_NE(cb, nullptr);
257         std::time_t prepareStartTime = GetCurTimeMillSec();
258         resultCode = AieClientPrepare(clientInfo, algoInfo, inputInfo, outputInfo, callback);
259         ASSERT_EQ(resultCode, RETCODE_SUCCESS);
260         std::time_t prepareEndTime = GetCurTimeMillSec();
261         g_prepareTotalTime += prepareEndTime - prepareStartTime;
262 
263         g_processStartTime = GetCurTimeMillSec();
264         resultCode = AieClientAsyncProcess(clientInfo, algoInfo, inputInfo);
265         ASSERT_EQ(resultCode, RETCODE_SUCCESS);
266         sleep(SLEEP_TIME);
267 
268         int optionType = 0;
269         std::time_t setOptionStartTime = GetCurTimeMillSec();
270         resultCode = AieClientSetOption(clientInfo, optionType, inputInfo);
271         ASSERT_EQ(resultCode, RETCODE_SUCCESS);
272         std::time_t setOptionEndTime = GetCurTimeMillSec();
273         g_setOptionTotalTime += setOptionEndTime - setOptionStartTime;
274 
275         outputInfo = {
276                 .data = nullptr,
277                 .length = 0
278         };
279         std::time_t getOptionStartTime = GetCurTimeMillSec();
280         resultCode = AieClientGetOption(clientInfo, optionType, inputInfo, outputInfo);
281         ASSERT_EQ(resultCode, RETCODE_SUCCESS);
282         std::time_t getOptionEndTime = GetCurTimeMillSec();
283         g_getOptionTotalTime += getOptionEndTime - getOptionStartTime;
284 
285         std::time_t releaseStartTime = GetCurTimeMillSec();
286         resultCode = AieClientRelease(clientInfo, algoInfo, inputInfo);
287         ASSERT_EQ(resultCode, RETCODE_SUCCESS);
288         std::time_t releaseEndTime = GetCurTimeMillSec();
289         g_releaseTotalTime += releaseEndTime - releaseStartTime;
290 
291         std::time_t destroyStartTime = GetCurTimeMillSec();
292         resultCode = AieClientDestroy(clientInfo);
293         ASSERT_EQ(resultCode, RETCODE_SUCCESS);
294         std::time_t destroyEndTime = GetCurTimeMillSec();
295         g_destroyTotalTime += destroyEndTime - destroyStartTime;
296 
297         AIE_DELETE(cb);
298         AIE_DELETE(callback);
299     }
300     CheckTimeInit();
301     CheckTimePrepare();
302     CheckTimeAsyncProcess();
303     CheckTimeRelease();
304     CheckTimeDestroy();
305     CheckTimeSetOption();
306     CheckTimeGetOption();
307 }
308