1 /*
2 * Copyright (c) 2022 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 * miscservices under the License is miscservices 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 "distributed_stream_test.h"
16
17 #include "gtest/gtest.h"
18 #include <cstring>
19 #include <iostream>
20 #include <semaphore.h>
21 #include <string>
22 #include <unistd.h>
23 #include <unordered_map>
24 #include <unordered_set>
25 #include "securec.h"
26 #include "softbus_bus_center.h"
27 #include "session.h"
28 #include "softbus_common.h"
29 #include "softbus_access_token_test.h"
30 #include "distributed_major.h"
31
32 using namespace std;
33 using namespace testing;
34 using namespace testing::ext;
35
36 #define SLEEP_SEC (1)
37 #define SLEEP_MS (2)
38 #define WAIT_MS (16)
39 #define WAIT_S (2)
40 #define FPS (60)
41 #define I_FRAME_TYPE (1)
42 #define P_FRAME_TYPE (2)
43 #define MAX_SEND_CNT (1000)
44
45 namespace OHOS {
46
SetNumebrInStreamData(char * streamData,int i)47 void SetNumebrInStreamData(char *streamData, int i)
48 {
49 string strI = std::to_string(i);
50 char len = strI.length();
51 streamData[0] = len;
52 (void)memcpy_s(streamData + 1, len, strI.c_str(), len);
53 }
54
GetNumebrInStreamData(const char * streamData)55 int GetNumebrInStreamData(const char *streamData)
56 {
57 char len = streamData[0];
58 string str(streamData + 1, len);
59
60 return std::stoi(str);
61 }
62
63 class DistributeStreamTest : public OHOS::DistributeSystemTest::DistributeTest {
64 public:
65 static void SetUpTestCase(void);
66 static void TearDownTestCase(void);
67 void SetUp();
68 void TearDown();
69
70 static int OnsessionOpened(int sessionId, int result);
71 static int OnCtrlsessionOpened(int sessionId, int result);
72 static void OnSessionClosed(int sessionId);
73 static void OnStreamReceived(int sessionId, const StreamData *data,
74 const StreamData *ext, const StreamFrameInfo *param);
75 static void OnBytesReceived(int sessionId, const void *data, unsigned int dataLen);
76
77 void P2pTransTest(bool isRawStream, bool isP2P, int sendCnt, const string &mySessionName,
78 const string &peerSessionName);
79 void TestSendCommonStream(int sendCnt);
80 void TestSendStream(int sendCnt);
81 void CloseAllSession(void);
82 void OpenAllSession(bool isRawStream, bool isP2P, const string &mySessionName, const string &peerSessionName);
83 void OpenCtrlSession(const string &mySessionName, const string &peerSessionName);
84
85 void SendCreateSessionServerMessage();
86 void SendRemoveSessionServerMessage();
87
88 static unordered_set<string> networkIdSet_;
89 static int contrlSessionId_;
90 static unordered_set<int> sessionSet_;
91 static sem_t localSem_;
92
93 static time_t startTime[MAX_SEND_CNT];
94 static time_t endTime[MAX_SEND_CNT];
95 static char sendBytes[BYTES_SIZE];
96 };
97
98 unordered_set<string> DistributeStreamTest::networkIdSet_;
99 int DistributeStreamTest::contrlSessionId_ = 0;
100 unordered_set<int> DistributeStreamTest::sessionSet_;
101 sem_t DistributeStreamTest::localSem_;
102 time_t DistributeStreamTest::startTime[MAX_SEND_CNT];
103 time_t DistributeStreamTest::endTime[MAX_SEND_CNT];
104 char DistributeStreamTest::sendBytes[BYTES_SIZE];
105
Wsleep(int count,int usl)106 void Wsleep(int count, int usl)
107 {
108 while (count) {
109 if (usl == SLEEP_SEC) {
110 sleep(1);
111 } else {
112 usleep(US_PER_MS);
113 }
114 count--;
115 }
116 }
117
OnsessionOpened(int sessionId,int result)118 int DistributeStreamTest::OnsessionOpened(int sessionId, int result)
119 {
120 EXPECT_EQ(result, 0);
121 if (result == 0) {
122 sessionSet_.insert(sessionId);
123 }
124 int ret = sem_post(&localSem_);
125 EXPECT_EQ(ret, 0);
126 return 0;
127 }
128
OnCtrlsessionOpened(int sessionId,int result)129 int DistributeStreamTest::OnCtrlsessionOpened(int sessionId, int result)
130 {
131 EXPECT_EQ(result, 0);
132 if (result == 0) {
133 contrlSessionId_ = sessionId;
134 }
135 int ret = sem_post(&localSem_);
136 EXPECT_EQ(ret, 0);
137 return 0;
138 }
139
OnSessionClosed(int sessionId)140 void DistributeStreamTest::OnSessionClosed(int sessionId)
141 {
142 sessionSet_.erase(sessionId);
143 }
144
OnStreamReceived(int sessionId,const StreamData * data,const StreamData * ext,const StreamFrameInfo * param)145 void DistributeStreamTest::OnStreamReceived(int sessionId, const StreamData *data,
146 const StreamData *ext, const StreamFrameInfo *param)
147 {
148 }
149
OnBytesReceived(int sessionId,const void * data,unsigned int dataLen)150 void DistributeStreamTest::OnBytesReceived(int sessionId, const void *data, unsigned int dataLen)
151 {
152 int i = GetNumebrInStreamData(static_cast<const char*>(data));
153 if (i < 0) {
154 return;
155 }
156 endTime[i] = GetCurrent();
157 unsigned long long timeDiff = (endTime[i] - startTime[i]);
158 cout << i << " frame time cost " << timeDiff << "ms" << endl;
159 }
160
161 static ISessionListener g_listener = {
162 .OnSessionOpened = DistributeStreamTest::OnsessionOpened,
163 .OnSessionClosed = DistributeStreamTest::OnSessionClosed,
164 .OnBytesReceived = DistributeStreamTest::OnBytesReceived,
165 .OnStreamReceived = DistributeStreamTest::OnStreamReceived
166 };
167
168 static ISessionListener g_ctrllistener = {
169 .OnSessionOpened = DistributeStreamTest::OnCtrlsessionOpened,
170 .OnSessionClosed = DistributeStreamTest::OnSessionClosed,
171 .OnBytesReceived = DistributeStreamTest::OnBytesReceived,
172 .OnStreamReceived = DistributeStreamTest::OnStreamReceived
173 };
174
SetUp()175 void DistributeStreamTest::SetUp()
176 {
177 sessionSet_.clear();
178 }
179
TearDown()180 void DistributeStreamTest::TearDown()
181 {
182 sessionSet_.clear();
183 }
184
SetUpTestCase()185 void DistributeStreamTest::SetUpTestCase()
186 {
187 SetAceessTokenPermission("distributed_stream_test");
188
189 // 获取在线设备
190 NodeBasicInfo *onlineDevices = nullptr;
191 int32_t onlineNum;
192 int ret = GetAllNodeDeviceInfo(TEST_PKG_NAME.c_str(), &onlineDevices, &onlineNum);
193 ASSERT_EQ(ret, 0);
194 ASSERT_GT(onlineNum, 0);
195 cout << "online devices num : " << onlineNum << endl;
196 for (int i = 0; i < onlineNum; i++) {
197 networkIdSet_.insert(string(onlineDevices[i].networkId));
198 cout << "online index " << i << " : " << string(onlineDevices[i].networkId) << endl;
199 }
200 FreeNodeInfo(onlineDevices);
201
202 ret = sem_init(&localSem_, 0, 0);
203 ASSERT_EQ(ret, 0);
204 }
205
TearDownTestCase()206 void DistributeStreamTest::TearDownTestCase()
207 {
208 int ret;
209 sessionSet_.clear();
210
211 ret = sem_destroy(&localSem_);
212 EXPECT_EQ(ret, 0);
213
214 Wsleep(WAIT_S, SLEEP_SEC);
215 }
216
TestSendStream(int sendCnt)217 void DistributeStreamTest::TestSendStream(int sendCnt)
218 {
219 if (sendCnt >= MAX_SEND_CNT) {
220 return;
221 }
222
223 char *sendData = static_cast<char*>(malloc(STREAM_SIZE));
224 if (sendData == nullptr) {
225 return;
226 }
227
228 StreamData extStreamData = {0};
229 StreamData streamData = {
230 .buf = sendData,
231 .bufLen = STREAM_SIZE,
232 };
233 StreamFrameInfo frame = {0};
234
235 for (auto session : sessionSet_) {
236 if (session == contrlSessionId_) {
237 continue;
238 }
239
240 cout << "send stream, session id = " << session << endl;
241 for (int i = 0; i < sendCnt; i++) {
242 startTime[i] = GetCurrent();
243 SetNumebrInStreamData(sendData, i);
244 int ret = SendStream(session, &streamData, &extStreamData, &frame);
245 EXPECT_EQ(ret, 0);
246
247 Wsleep(WAIT_MS, SLEEP_MS);
248 }
249 }
250
251 free(sendData);
252 sendData = nullptr;
253 }
254
TestSendCommonStream(int sendCnt)255 void DistributeStreamTest::TestSendCommonStream(int sendCnt)
256 {
257 char *sendIFrame = static_cast<char*>(malloc(I_FRAME_SIZE));
258 if (sendIFrame == nullptr) {
259 return;
260 }
261 char *sendPFrame = static_cast<char*>(malloc(P_FRAME_SIZE));
262 if (sendPFrame == nullptr) {
263 free(sendIFrame);
264 sendIFrame = nullptr;
265 return;
266 }
267 StreamData extStreamData = {0};
268 StreamData streamIData = {
269 .buf = sendIFrame,
270 .bufLen = I_FRAME_SIZE,
271 };
272 StreamFrameInfo iFrame = {0};
273 iFrame.frameType = I_FRAME_TYPE;
274
275 StreamData streamPData = {
276 .buf = sendPFrame,
277 .bufLen = P_FRAME_SIZE,
278 };
279 StreamFrameInfo pFrame = {0};
280 pFrame.frameType = P_FRAME_TYPE;
281
282 for (auto session : sessionSet_) {
283 if (session == contrlSessionId_) {
284 continue;
285 }
286
287 cout << "send stream, session id = " << session << endl;
288 while (sendCnt > 0) {
289 startTime[0] = GetCurrent();
290 SetNumebrInStreamData(sendIFrame, 0);
291 int ret = SendStream(session, &streamIData, &extStreamData, &iFrame);
292 EXPECT_EQ(ret, 0);
293
294 Wsleep(WAIT_MS, SLEEP_MS);
295 for (int i = 1; i < FPS; i++) {
296 startTime[i] = GetCurrent();
297 SetNumebrInStreamData(sendPFrame, i);
298 ret = SendStream(session, &streamPData, &extStreamData, &pFrame);
299 EXPECT_EQ(ret, 0);
300
301 Wsleep(WAIT_MS, SLEEP_MS);
302 }
303 sendCnt--;
304 }
305 }
306
307 free(sendIFrame);
308 sendIFrame = nullptr;
309
310 free(sendPFrame);
311 sendPFrame = nullptr;
312 }
313
CloseAllSession(void)314 void DistributeStreamTest::CloseAllSession(void)
315 {
316 for (auto session : sessionSet_) {
317 CloseSession(session);
318 }
319 }
320
OpenAllSession(bool isRawStream,bool isP2P,const string & mySessionName,const string & peerSessionName)321 void DistributeStreamTest::OpenAllSession(bool isRawStream, bool isP2P,
322 const string &mySessionName, const string &peerSessionName)
323 {
324 for (auto networkId : networkIdSet_) {
325 SessionAttribute attribute;
326 (void)memset_s(&attribute, sizeof(attribute), 0, sizeof(attribute));
327 // p2p link type session
328 attribute.dataType = TYPE_STREAM;
329 attribute.linkTypeNum = 0;
330 attribute.linkType[0] = isP2P ? LINK_TYPE_WIFI_P2P : LINK_TYPE_WIFI_WLAN_5G;
331 attribute.attr.streamAttr.streamType = isRawStream ? RAW_STREAM : COMMON_VIDEO_STREAM;
332
333 cout << "streamType === " << attribute.attr.streamAttr.streamType << endl;
334
335 int ret = OpenSession(mySessionName.c_str(), peerSessionName.c_str(), networkId.c_str(), "", &attribute);
336 ASSERT_GT(ret, 0);
337
338 struct timespec timeout;
339 clock_gettime(CLOCK_REALTIME, &timeout);
340 timeout.tv_sec += 10; // 10: over time 10 seconds
341 while ((ret = sem_timedwait(&localSem_, &timeout)) == -1 && errno == EINTR) {
342 continue;
343 }
344 if ((ret == -1) && (errno == ETIMEDOUT)) {
345 cout << "wait time out22222222" << endl;
346 }
347 ASSERT_EQ(ret, 0);
348 }
349 }
350
OpenCtrlSession(const string & mySessionName,const string & peerSessionName)351 void DistributeStreamTest::OpenCtrlSession(const string &mySessionName, const string &peerSessionName)
352 {
353 for (auto networkId : networkIdSet_) {
354 SessionAttribute attribute;
355 (void)memset_s(&attribute, sizeof(attribute), 0, sizeof(attribute));
356 // p2p link type session
357 attribute.dataType = TYPE_BYTES;
358 attribute.linkTypeNum = 0;
359 attribute.linkType[0] = LINK_TYPE_WIFI_WLAN_5G;
360
361 int ret = OpenSession(mySessionName.c_str(), peerSessionName.c_str(), networkId.c_str(), "", &attribute);
362 ASSERT_GT(ret, 0);
363
364 struct timespec timeout;
365 clock_gettime(CLOCK_REALTIME, &timeout);
366 timeout.tv_sec += 10; // 10: over time 10 seconds
367 while ((ret = sem_timedwait(&localSem_, &timeout)) == -1 && errno == EINTR) {
368 continue;
369 }
370 if ((ret == -1) && (errno == ETIMEDOUT)) {
371 cout << "wait open session time out" << endl;
372 }
373 ASSERT_EQ(ret, 0);
374 }
375 }
376
SendCreateSessionServerMessage()377 void DistributeStreamTest::SendCreateSessionServerMessage()
378 {
379 string msgbuf = "createSessionServer";
380 int ret = SendMessage(DistributeSystemTest::AGENT_NO::ONE, msgbuf, msgbuf.length(),
381 [&](const string &returnBuf, int rlen)->bool {
382 cout << "receive reply message :" << returnBuf << endl;
383 EXPECT_TRUE("ok" == returnBuf);
384 int ret = sem_post(&localSem_);
385 EXPECT_EQ(ret, 0);
386 return true;
387 });
388 EXPECT_TRUE(ret > 0);
389
390 struct timespec timeout;
391 clock_gettime(CLOCK_REALTIME, &timeout);
392 timeout.tv_sec += 10; // 10: over time 10 seconds
393 while ((ret = sem_timedwait(&localSem_, &timeout)) == -1 && errno == EINTR) {
394 continue;
395 }
396 if ((ret == -1) && (errno == ETIMEDOUT)) {
397 cout << "wait send messgae time out" << endl;
398 }
399 ASSERT_EQ(ret, 0);
400 cout << "SendMessage OK" << endl;
401 }
402
SendRemoveSessionServerMessage()403 void DistributeStreamTest::SendRemoveSessionServerMessage()
404 {
405 string msgbuf = "removeSessionServer";
406 int ret = SendMessage(DistributeSystemTest::AGENT_NO::ONE, msgbuf, msgbuf.length(),
407 [&](const string &returnBuf, int rlen)->bool {
408 cout << "receive reply message :" << returnBuf << endl;
409 EXPECT_TRUE("ok" == returnBuf);
410 int ret = sem_post(&localSem_);
411 EXPECT_EQ(ret, 0);
412 return true;
413 });
414 EXPECT_TRUE(ret > 0);
415
416 struct timespec timeout;
417 clock_gettime(CLOCK_REALTIME, &timeout);
418 timeout.tv_sec += 10; // 10: over time 10 seconds
419 while ((ret = sem_timedwait(&localSem_, &timeout)) == -1 && errno == EINTR) {
420 continue;
421 }
422 if ((ret == -1) && (errno == ETIMEDOUT)) {
423 cout << "wait send messgae time out" << endl;
424 }
425 ASSERT_EQ(ret, 0);
426 cout << "SendMessage OK" << endl;
427 }
428
P2pTransTest(bool isRawStream,bool isP2P,int sendCnt,const string & mySessionName,const string & peerSessionName)429 void DistributeStreamTest::P2pTransTest(bool isRawStream, bool isP2P,
430 int sendCnt, const string &mySessionName, const string &peerSessionName)
431 {
432 OpenAllSession(isRawStream, isP2P, mySessionName, peerSessionName);
433 if (isRawStream) {
434 TestSendStream(sendCnt);
435 } else {
436 TestSendCommonStream(sendCnt);
437 }
438 }
439
440 /*
441 * @tc.name: stream_p2p_trans_test_001
442 * @tc.desc: open stream p2p link type session, send raw stream, close session test.
443 * @tc.type: FUNC
444 * @tc.require: AR000GIIQ3
445 */
446 HWTEST_F(DistributeStreamTest, stream_p2p_trans_test_001, TestSize.Level4)
447 {
448 int ret = CreateSessionServer(TEST_PKG_NAME.c_str(), STREAM_SESSION_NAME.c_str(), &g_listener);
449 ASSERT_EQ(ret, 0);
450 cout << "pkgName : " << TEST_PKG_NAME << ", sessionName : " << STREAM_SESSION_NAME << endl;
451
452 ret = CreateSessionServer(TEST_PKG_NAME.c_str(), CONTRL_SESSION_NAME.c_str(), &g_ctrllistener);
453 ASSERT_EQ(ret, 0);
454 cout << "pkgName : " << TEST_PKG_NAME << ", sessionName : " << CONTRL_SESSION_NAME << endl;
455
456 SendCreateSessionServerMessage();
457 OpenCtrlSession(CONTRL_SESSION_NAME, CONTRL_SESSION_NAME);
458 P2pTransTest(true, true, 60, STREAM_SESSION_NAME, STREAM_SESSION_NAME);
459
460 Wsleep(WAIT_S, SLEEP_SEC);
461
462 CloseAllSession();
463 SendRemoveSessionServerMessage();
464
465 ret = RemoveSessionServer(TEST_PKG_NAME.c_str(), STREAM_SESSION_NAME.c_str());
466 EXPECT_EQ(ret, 0);
467
468 ret = RemoveSessionServer(TEST_PKG_NAME.c_str(), CONTRL_SESSION_NAME.c_str());
469 EXPECT_EQ(ret, 0);
470 }
471
472 /*
473 * @tc.name: stream_p2p_trans_test_002
474 * @tc.desc: open stream wifi link type session, send raw stream, close session test.
475 * @tc.type: FUNC
476 * @tc.require: AR000GIIQ3
477 */
478 HWTEST_F(DistributeStreamTest, stream_p2p_trans_test_002, TestSize.Level4)
479 {
480 int ret = CreateSessionServer(TEST_PKG_NAME.c_str(), STREAM_SESSION_NAME.c_str(), &g_listener);
481 ASSERT_EQ(ret, 0);
482 cout << "pkgName : " << TEST_PKG_NAME << ", sessionName : " << STREAM_SESSION_NAME << endl;
483
484 ret = CreateSessionServer(TEST_PKG_NAME.c_str(), CONTRL_SESSION_NAME.c_str(), &g_ctrllistener);
485 ASSERT_EQ(ret, 0);
486 cout << "pkgName : " << TEST_PKG_NAME << ", sessionName : " << CONTRL_SESSION_NAME << endl;
487
488 SendCreateSessionServerMessage();
489 OpenCtrlSession(CONTRL_SESSION_NAME, CONTRL_SESSION_NAME);
490 P2pTransTest(true, false, 60, STREAM_SESSION_NAME, STREAM_SESSION_NAME);
491
492 Wsleep(WAIT_S, SLEEP_SEC);
493
494 CloseAllSession();
495 SendRemoveSessionServerMessage();
496
497 ret = RemoveSessionServer(TEST_PKG_NAME.c_str(), STREAM_SESSION_NAME.c_str());
498 EXPECT_EQ(ret, 0);
499
500 ret = RemoveSessionServer(TEST_PKG_NAME.c_str(), CONTRL_SESSION_NAME.c_str());
501 EXPECT_EQ(ret, 0);
502 }
503
504 /*
505 * @tc.name: stream_p2p_trans_test_003
506 * @tc.desc: open stream p2p link type session, send common stream, close session test.
507 * @tc.type: FUNC
508 * @tc.require: AR000GIIQ3
509 */
510 HWTEST_F(DistributeStreamTest, stream_p2p_trans_test_003, TestSize.Level4)
511 {
512 int ret = CreateSessionServer(TEST_PKG_NAME.c_str(), STREAM_SESSION_NAME.c_str(), &g_listener);
513 ASSERT_EQ(ret, 0);
514 cout << "pkgName : " << TEST_PKG_NAME << ", sessionName : " << STREAM_SESSION_NAME << endl;
515
516 ret = CreateSessionServer(TEST_PKG_NAME.c_str(), CONTRL_SESSION_NAME.c_str(), &g_ctrllistener);
517 ASSERT_EQ(ret, 0);
518 cout << "pkgName : " << TEST_PKG_NAME << ", sessionName : " << CONTRL_SESSION_NAME << endl;
519
520 SendCreateSessionServerMessage();
521 OpenCtrlSession(CONTRL_SESSION_NAME, CONTRL_SESSION_NAME);
522 P2pTransTest(false, true, 20, STREAM_SESSION_NAME, STREAM_SESSION_NAME);
523
524 Wsleep(WAIT_S, SLEEP_SEC);
525
526 CloseAllSession();
527 SendRemoveSessionServerMessage();
528
529 ret = RemoveSessionServer(TEST_PKG_NAME.c_str(), STREAM_SESSION_NAME.c_str());
530 EXPECT_EQ(ret, 0);
531
532 ret = RemoveSessionServer(TEST_PKG_NAME.c_str(), CONTRL_SESSION_NAME.c_str());
533 EXPECT_EQ(ret, 0);
534 }
535
536 /*
537 * @tc.name: stream_p2p_trans_test_004
538 * @tc.desc: open stream p2p link type session, send raw stream, close session test.
539 * @tc.type: FUNC
540 * @tc.require: AR000GIIQ3
541 */
542 HWTEST_F(DistributeStreamTest, stream_p2p_trans_test_004, TestSize.Level4)
543 {
544 int ret = CreateSessionServer(TEST_PKG_NAME.c_str(), STREAM_SESSION_NAME.c_str(), &g_listener);
545 ASSERT_EQ(ret, 0);
546 cout << "pkgName : " << TEST_PKG_NAME << ", sessionName : " << STREAM_SESSION_NAME << endl;
547
548 ret = CreateSessionServer(TEST_PKG_NAME.c_str(), CONTRL_SESSION_NAME.c_str(), &g_ctrllistener);
549 ASSERT_EQ(ret, 0);
550 cout << "pkgName : " << TEST_PKG_NAME << ", sessionName : " << CONTRL_SESSION_NAME << endl;
551
552 SendCreateSessionServerMessage();
553 OpenCtrlSession(CONTRL_SESSION_NAME, CONTRL_SESSION_NAME);
554 P2pTransTest(false, false, 20, STREAM_SESSION_NAME, STREAM_SESSION_NAME);
555
556 Wsleep(WAIT_S, SLEEP_SEC);
557
558 CloseAllSession();
559 SendRemoveSessionServerMessage();
560
561 ret = RemoveSessionServer(TEST_PKG_NAME.c_str(), STREAM_SESSION_NAME.c_str());
562 EXPECT_EQ(ret, 0);
563
564 ret = RemoveSessionServer(TEST_PKG_NAME.c_str(), CONTRL_SESSION_NAME.c_str());
565 EXPECT_EQ(ret, 0);
566 }
567 }
568
main(int argc,char * argv[])569 int main(int argc, char *argv[])
570 {
571 OHOS::DistributeSystemTest::g_pDistributetestEnv =
572 new OHOS::DistributeSystemTest::DistributeTestEnvironment("major.desc");
573 testing::AddGlobalTestEnvironment(OHOS::DistributeSystemTest::g_pDistributetestEnv);
574 testing::GTEST_FLAG(output) = "xml:./";
575 testing::InitGoogleTest(&argc, argv);
576 return RUN_ALL_TESTS();
577 }
578