1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * SPDX-License-Identifier: GPL-2.0
4 *
5 * Unless required by applicable law or agreed to in writing, software
6 * distributed under the License is distributed on an "AS IS" BASIS,
7 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8 * See the License for the specific language governing permissions and
9 * limitations under the License.
10 */
11
12#include "rtg_test.h"
13#include <cstdio>
14#include <cstdlib>
15#include <fcntl.h>
16#include <cerrno>
17#include <unistd.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <sys/mman.h>
21#include <sys/wait.h>
22#include <sys/ioctl.h>
23#include <ctime>
24#include <climits>
25#include <pthread.h>
26#include <sys/syscall.h>
27#include <securec.h>
28#include <string>
29#include <vector>
30
31using namespace testing::ext;
32using namespace std;
33
34constexpr size_t MAX_LENGTH = 100;
35const char RTG_SCHED_IPC_MAGIC = 0xAB;
36const int RTG_ERR = -1;
37const int RTG_SUCC = 0;
38const int MAX_TID_NUM = 5;
39const int MULTI_FRAME_NUM = 5;
40
41#define CMD_ID_SET_ENABLE \
42    _IOWR(RTG_SCHED_IPC_MAGIC, SET_ENABLE, struct RtgEnableData)
43#define CMD_ID_SET_RTG \
44    _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG, struct RtgStrData)
45#define CMD_ID_BEGIN_FRAME_FREQ \
46    _IOWR(RTG_SCHED_IPC_MAGIC, BEGIN_FRAME_FREQ, struct ProcStateData)
47#define CMD_ID_END_FRAME_FREQ \
48    _IOWR(RTG_SCHED_IPC_MAGIC, END_FRAME_FREQ, struct ProcStateData)
49#define CMD_ID_END_SCENE \
50    _IOWR(RTG_SCHED_IPC_MAGIC, END_SCENE, struct ProcStateData)
51#define CMD_ID_SET_MIN_UTIL \
52    _IOWR(RTG_SCHED_IPC_MAGIC, SET_MIN_UTIL, struct ProcStateData)
53#define CMD_ID_SET_MARGIN \
54    _IOWR(RTG_SCHED_IPC_MAGIC, SET_MARGIN, struct ProcStateData)
55#define CMD_ID_SET_RTG_ATTR \
56    _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG_ATTR, struct RtgStrData)
57#define CMD_ID_SET_CONFIG \
58    _IOWR(RTG_SCHED_IPC_MAGIC, SET_CONFIG, struct RtgStrData)
59
60struct RtgEnableData {
61    int enable;
62    int len;
63    char *data;
64};
65
66struct RtgStrData {
67    int type;
68    int len;
69    char *data;
70};
71
72struct ProcStateData {
73    int grpId;
74    int stateParam;
75};
76
77enum GrpCtrlCmd {
78    CMD_CREATE_RTG_GRP,
79    CMD_ADD_RTG_THREAD,
80    CMD_REMOVE_RTG_THREAD,
81    CMD_CLEAR_RTG_GRP,
82    CMD_DESTROY_RTG_GRP
83};
84
85struct RtgGrpData {
86    int rtgCmd;
87    int grpId;
88    int prioType;
89    int rtCnt;
90    int tidNum;
91    int tids[MAX_TID_NUM];
92};
93
94struct RtgInfo {
95    int rtgNum;
96    int rtgs[MULTI_FRAME_NUM];
97};
98
99enum RtgSchedCmdid {
100    SET_ENABLE = 1,
101    SET_RTG,
102    SET_CONFIG,
103    SET_RTG_ATTR,
104    BEGIN_FRAME_FREQ = 5,
105    END_FRAME_FREQ,
106    END_SCENE,
107    SET_MIN_UTIL,
108    SET_MARGIN,
109    LIST_RTG = 10,
110    LIST_RTG_THREAD,
111    SEARCH_RTG,
112    GET_ENABLE,
113    RTG_CTRL_MAX_NR,
114};
115
116enum RtgType : int {
117    VIP = 0,
118    TOP_TASK_KEY,
119    NORMAL_TASK,
120    RTG_TYPE_MAX,
121};
122
123static int BasicOpenRtgNode()
124{
125    char fileName[] = "/proc/self/sched_rtg_ctrl";
126
127    int fd = open(fileName, O_RDWR);
128    if (fd < 0) {
129        cout << "open node err." << endl;
130    }
131
132    return fd;
133}
134
135static int EnableRtg(bool flag)
136{
137    struct RtgEnableData enableData;
138    char configStr[] = "load_freq_switch:1;sched_cycle:1";
139
140    enableData.enable = flag;
141    enableData.len = sizeof(configStr);
142    enableData.data = configStr;
143    int fd = BasicOpenRtgNode();
144    if (fd < 0) {
145        return RTG_ERR;
146    }
147    if (ioctl(fd, CMD_ID_SET_ENABLE, &enableData)) {
148        close(fd);
149        return RTG_ERR;
150    }
151
152    close(fd);
153    return 0;
154}
155
156static int CreateNewRtgGrp(int prioType, int rtNum)
157{
158    struct RtgGrpData grpData;
159    int ret;
160    int fd = BasicOpenRtgNode();
161    if (fd < 0) {
162        return RTG_ERR;
163    }
164    (void)memset_s(&grpData, sizeof(struct RtgGrpData), 0, sizeof(struct RtgGrpData));
165    if ((prioType > 0) && (prioType < RTG_TYPE_MAX)) {
166        grpData.prioType = prioType;
167    }
168    if (rtNum > 0) {
169        grpData.rtCnt = rtNum;
170    }
171    grpData.rtgCmd = CMD_CREATE_RTG_GRP;
172    ret = ioctl(fd, CMD_ID_SET_RTG, &grpData);
173
174    close(fd);
175    return ret;
176}
177
178static int DestroyRtgGrp(int grpId)
179{
180    struct RtgGrpData grpData;
181    int ret;
182    int fd = BasicOpenRtgNode();
183    if (fd < 0) {
184        return fd;
185    }
186    (void)memset_s(&grpData, sizeof(struct RtgGrpData), 0, sizeof(struct RtgGrpData));
187    grpData.rtgCmd = CMD_DESTROY_RTG_GRP;
188    grpData.grpId = grpId;
189    ret = ioctl(fd, CMD_ID_SET_RTG, &grpData);
190
191    close(fd);
192    return ret;
193}
194
195static int AddThreadToRtg(int tid, int grpId, int prioType)
196{
197    struct RtgGrpData grpData;
198    int ret;
199    int fd = BasicOpenRtgNode();
200    if (fd < 0) {
201        return fd;
202    }
203    (void)memset_s(&grpData, sizeof(struct RtgGrpData), 0, sizeof(struct RtgGrpData));
204    grpData.tidNum = 1;
205    grpData.tids[0] = tid;
206    grpData.grpId = grpId;
207    grpData.rtgCmd = CMD_ADD_RTG_THREAD;
208    grpData.prioType = prioType;
209    ret = ioctl(fd, CMD_ID_SET_RTG, &grpData);
210
211    close(fd);
212    return ret;
213}
214
215static int BeginFrameFreq(int stateParam)
216{
217    int ret = 0;
218    struct ProcStateData stateData;
219    stateData.stateParam = stateParam;
220    int fd = BasicOpenRtgNode();
221    if (fd < 0) {
222        return fd;
223    }
224    ret = ioctl(fd, CMD_ID_BEGIN_FRAME_FREQ, &stateData);
225
226    close(fd);
227    return ret;
228}
229
230static int EndFrameFreq(int stateParam)
231{
232    int ret = 0;
233    struct ProcStateData stateData;
234    stateData.stateParam = stateParam;
235    int fd = BasicOpenRtgNode();
236    if (fd < 0) {
237            return fd;
238        }
239    ret = ioctl(fd, CMD_ID_END_FRAME_FREQ, &stateData);
240
241    close(fd);
242    return ret;
243}
244
245static int EndScene(int grpId)
246{
247    int ret = 0;
248    struct ProcStateData stateData;
249    stateData.grpId = grpId;
250
251    int fd = BasicOpenRtgNode();
252    if (fd < 0) {
253        return fd;
254    }
255    ret = ioctl(fd, CMD_ID_END_SCENE, &stateData);
256
257    close(fd);
258    return ret;
259}
260
261static int SetStateParam(unsigned int cmd, int stateParam)
262{
263    int ret = 0;
264    struct ProcStateData stateData;
265    stateData.stateParam = stateParam;
266
267    int fd = BasicOpenRtgNode();
268    if (fd < 0) {
269        return fd;
270    }
271    ret = ioctl(fd, cmd, &stateData);
272
273    close(fd);
274    return ret;
275}
276
277static int SetFrameRateAndPrioType(int rtgId, int rate, int rtgType)
278{
279    int ret = 0;
280    char formatData[MAX_LENGTH] = {};
281    (void)sprintf_s(formatData, sizeof(formatData), "rtgId:%d;rate:%d;type:%d", rtgId, rate, rtgType);
282    struct RtgStrData strData;
283    strData.len = strlen(formatData);
284    strData.data = formatData;
285
286    int fd = BasicOpenRtgNode();
287    if (fd < 0) {
288        return fd;
289    }
290    ret = ioctl(fd, CMD_ID_SET_RTG_ATTR, &strData);
291
292    close(fd);
293    return ret;
294}
295
296static int AddThreadsToRtg(vector<int> tids, int grpId, int prioType)
297{
298    struct RtgGrpData grpData;
299    int ret;
300
301    int fd = BasicOpenRtgNode();
302    if (fd < 0) {
303        return fd;
304    }
305    (void)memset_s(&grpData, sizeof(struct RtgGrpData), 0, sizeof(struct RtgGrpData));
306    int num = static_cast<int>(tids.size());
307    if (num > MAX_TID_NUM) {
308        return -1;
309    }
310    grpData.tidNum = num;
311    grpData.grpId = grpId;
312    grpData.rtgCmd = CMD_ADD_RTG_THREAD;
313    grpData.prioType = prioType;
314    for (int i = 0; i < num; i++) {
315        if (tids[i] < 0) {
316            return -1;
317        }
318        grpData.tids[i] = tids[i];
319    }
320    ret = ioctl(fd, CMD_ID_SET_RTG, &grpData);
321
322    close(fd);
323    return ret;
324}
325
326void RtgTest::SetUp()
327{
328    // must enable rtg before use the interface
329    int ret = EnableRtg(true);
330    ASSERT_EQ(RTG_SUCC, ret);
331}
332
333void RtgTest::TearDown()
334{
335    // disable rtg after use the interface
336    int ret = EnableRtg(false);
337    ASSERT_EQ(RTG_SUCC, ret);
338}
339
340void RtgTest::SetUpTestCase() {}
341
342void RtgTest::TearDownTestCase() {}
343
344/**
345 * @tc.name: setEnableSucc
346 * @tc.desc: Verify the enable rtg function.
347 * @tc.type: FUNC
348 */
349HWTEST_F(RtgTest, setEnableSucc, Function | MediumTest | Level1)
350{
351    int ret;
352
353    // test set enable again
354    ret = EnableRtg(true);
355    ASSERT_EQ(RTG_SUCC, ret);
356
357    // test set disable again
358    ret = EnableRtg(false);
359    ASSERT_EQ(RTG_SUCC, ret);
360}
361
362/**
363 * @tc.name: createAndDestroyRtgSucc
364 * @tc.desc: Verify the create and destroy rtggrp function.
365 * @tc.type: FUNC
366 */
367HWTEST_F(RtgTest, createAndDestroyRtgSucc, Function | MediumTest | Level1)
368{
369    int ret;
370    int grpId;
371
372    grpId = CreateNewRtgGrp(NORMAL_TASK, 0);
373    ASSERT_GT(grpId, 0);
374    ret = DestroyRtgGrp(grpId);
375    ASSERT_EQ(ret, 0);
376}
377
378/**
379 * @tc.name: destoryErrorRtgGrp
380 * @tc.desc: Verify Destroy function with error param.
381 * @tc.type: FUNC
382 */
383HWTEST_F(RtgTest, destoryErrorRtgGrp, Function | MediumTest | Level1)
384{
385    int ret;
386    ret = DestroyRtgGrp(-1);
387    ASSERT_NE(RTG_SUCC, ret);
388}
389
390/**
391 * @tc.name: addRtgGrpSucc
392 * @tc.desc: Verify add rtg function.
393 * @tc.type: FUNC
394 */
395HWTEST_F(RtgTest, addRtgGrpSucc, Function | MediumTest | Level1)
396{
397    int ret;
398    int grpId;
399    int pid = getpid();
400
401    grpId = CreateNewRtgGrp(VIP, 0);
402    ASSERT_GT(grpId, 0);
403    ret = AddThreadToRtg(pid, grpId, VIP);
404    ASSERT_EQ(ret, 0);
405    ret = DestroyRtgGrp(grpId);
406    ASSERT_EQ(ret, 0);
407}
408
409/**
410 * @tc.name: addRtgGrpFail
411 * @tc.desc: Verify add rtg function with error param.
412 * @tc.type: FUNC
413 */
414HWTEST_F(RtgTest, addRtgGrpFail, Function | MediumTest | Level1)
415{
416    int ret;
417    int grpId;
418    int pid = getpid();
419
420    grpId = CreateNewRtgGrp(VIP, 0);
421    ASSERT_GT(grpId, 0);
422
423    // error tid
424    ret = AddThreadToRtg(-1, grpId, VIP);
425    ASSERT_NE(ret, 0);
426
427    // error grpid
428    ret = AddThreadToRtg(pid, -1, VIP);
429    ASSERT_NE(ret, RTG_SUCC);
430    ret = DestroyRtgGrp(grpId);
431    ASSERT_EQ(ret, 0);
432}
433
434/**
435 * @tc.name: begainFrameFreqSucc
436 * @tc.desc: Verify rtg frame start function.
437 * @tc.type: FUNC
438 */
439HWTEST_F(RtgTest, begainFrameFreqSucc, Function | MediumTest | Level1)
440{
441    int ret;
442    int grpId;
443    int pid = getpid();
444    vector<int> pids = {};
445    pids.push_back(pid);
446    grpId = CreateNewRtgGrp(VIP, 0);
447    ASSERT_GT(grpId, 0);
448    ret = AddThreadsToRtg(pids, grpId, VIP);
449    ASSERT_EQ(ret, 0);
450    ret = BeginFrameFreq(0);
451    ASSERT_EQ(ret, 0);
452    ret = DestroyRtgGrp(grpId);
453    ASSERT_EQ(ret, 0);
454}
455
456/**
457 * @tc.name: RtgInterfaceBeginFrameFreqWithNoAddThreadtoGrp
458 * @tc.desc: Verify rtg frame start function with NoAddThreadtoGrp.
459 * @tc.type: FUNC
460 */
461HWTEST_F(RtgTest, RtgInterfaceBeginFrameFreqWithNoAddThreadtoGrp, Function | MediumTest | Level1)
462{
463    int ret;
464    int grpId;
465    grpId = CreateNewRtgGrp(VIP, 0);
466    ASSERT_GT(grpId, 0);
467    ret = BeginFrameFreq(0);
468    ASSERT_NE(ret, 0);
469    ret = DestroyRtgGrp(grpId);
470    ASSERT_EQ(ret, 0);
471}
472
473/**
474 * @tc.name: endFrameFreqSucc
475 * @tc.desc: Verify rtg frame end function.
476 * @tc.type: FUNC
477 */
478HWTEST_F(RtgTest, endFrameFreqSucc, Function | MediumTest | Level1)
479{
480    int ret;
481    int grpId;
482    int pid = getpid();
483    vector<int> pids = {};
484    pids.push_back(pid);
485    grpId = CreateNewRtgGrp(VIP, 0);
486    ASSERT_GT(grpId, 0);
487    ret = AddThreadsToRtg(pids, grpId, VIP);
488    ASSERT_EQ(ret, 0);
489    ret = EndFrameFreq(0);
490    ASSERT_EQ(ret, RTG_SUCC);
491    ret = DestroyRtgGrp(grpId);
492    ASSERT_EQ(ret, RTG_SUCC);
493}
494
495/**
496 * @tc.name: endFrameFreqWithNoAddThreadtoGrp
497 * @tc.desc: Verify rtg frame end function with NoAddThreadtoGrp.
498 * @tc.type: FUNC
499 */
500HWTEST_F(RtgTest, endFrameFreqWithNoAddThreadtoGrp, Function | MediumTest | Level1)
501{
502    int ret;
503    int grpId;
504    grpId = CreateNewRtgGrp(VIP, 0);
505    ASSERT_GT(grpId, 0);
506    ret = EndFrameFreq(0);
507    ASSERT_NE(ret, RTG_SUCC);
508    ret = DestroyRtgGrp(grpId);
509    ASSERT_EQ(ret, RTG_SUCC);
510}
511
512
513/**
514 * @tc.name: endSceneSucc
515 * @tc.desc: Verify scene end function.
516 * @tc.type: FUNC
517 */
518HWTEST_F(RtgTest, endSceneSucc, Function | MediumTest | Level1)
519{
520    int ret;
521    int grpId;
522    int pid = getpid();
523    vector<int> pids = {};
524    pids.push_back(pid);
525    grpId = CreateNewRtgGrp(VIP, 0);
526    ASSERT_GT(grpId, 0);
527    ret = AddThreadsToRtg(pids, grpId, VIP);
528    ASSERT_EQ(ret, 0);
529    ret = EndScene(grpId);
530    ASSERT_EQ(ret, RTG_SUCC);
531    ret = DestroyRtgGrp(grpId);
532    ASSERT_EQ(ret, RTG_SUCC);
533}
534
535/**
536 * @tc.name: endSceneFail
537 * @tc.desc: Verify scene end function.
538 * @tc.type: FUNC
539 */
540HWTEST_F(RtgTest, endSceneFail, Function | MediumTest | Level1)
541{
542    int ret;
543
544    ret = EndScene(-1);
545    ASSERT_NE(ret, RTG_SUCC);
546}
547
548/**
549 * @tc.name: setMinUtilSucc
550 * @tc.desc: Verify set min util function.
551 * @tc.type: FUNC
552 */
553HWTEST_F(RtgTest, setMinUtilSucc, Function | MediumTest | Level1)
554{
555    int ret;
556    int grpId;
557    int pid = getpid();
558    vector<int> pids = {};
559    pids.push_back(pid);
560    grpId = CreateNewRtgGrp(VIP, 0);
561    ASSERT_GT(grpId, 0);
562    ret = AddThreadsToRtg(pids, grpId, VIP);
563    ASSERT_EQ(ret, 0);
564    ret = SetStateParam(CMD_ID_SET_MIN_UTIL, 0);
565    ASSERT_EQ(ret, RTG_SUCC);
566    ret = DestroyRtgGrp(grpId);
567    ASSERT_EQ(ret, RTG_SUCC);
568}
569
570/**
571 * @tc.name: setMinUtilWithNoAddThreadtoGrp
572 * @tc.desc: Verify set min util function with NoAddThreadtoGrp.
573 * @tc.type: FUNC
574 */
575HWTEST_F(RtgTest, setMinUtilWithNoAddThreadtoGrp, Function | MediumTest | Level1)
576{
577    int ret;
578    int grpId;
579    grpId = CreateNewRtgGrp(VIP, 0);
580    ASSERT_GT(grpId, 0);
581    ret = SetStateParam(CMD_ID_SET_MIN_UTIL, 0);
582    ASSERT_NE(ret, RTG_SUCC);
583    ret = DestroyRtgGrp(grpId);
584    ASSERT_EQ(ret, RTG_SUCC);
585}
586
587/**
588 * @tc.name: setMarginSucc
589 * @tc.desc: Verify set min margin function.
590 * @tc.type: FUNC
591 */
592HWTEST_F(RtgTest, setMarginSucc, Function | MediumTest | Level1)
593{
594    int ret;
595    int grpId;
596    int pid = getpid();
597    vector<int> pids = {};
598    pids.push_back(pid);
599    grpId = CreateNewRtgGrp(VIP, 0);
600    ASSERT_GT(grpId, 0);
601    ret = AddThreadsToRtg(pids, grpId, VIP);
602    ASSERT_EQ(ret, 0);
603    ret = SetStateParam(CMD_ID_SET_MARGIN, 0);
604    ASSERT_EQ(ret, RTG_SUCC);
605    ret = DestroyRtgGrp(grpId);
606    ASSERT_EQ(ret, RTG_SUCC);
607}
608
609/**
610 * @tc.name: setMarginWithNoAddThreadtoGrp
611 * @tc.desc: Verify set min margin function with NoAddThreadtoGrp.
612 * @tc.type: FUNC
613 */
614HWTEST_F(RtgTest, setMarginWithNoAddThreadtoGrp, Function | MediumTest | Level1)
615{
616    int ret;
617    int grpId;
618    grpId = CreateNewRtgGrp(VIP, 0);
619    ASSERT_GT(grpId, 0);
620    ret = SetStateParam(CMD_ID_SET_MARGIN, 0);
621    ASSERT_NE(ret, RTG_SUCC);
622    ret = DestroyRtgGrp(grpId);
623    ASSERT_EQ(ret, RTG_SUCC);
624}
625
626/**
627 * @tc.name: SetRtgAttrSucc
628 * @tc.desc: Verify rtg attr set function.
629 * @tc.type: FUNC
630 */
631HWTEST_F(RtgTest, SetRtgAttrSucc, Function | MediumTest | Level1)
632{
633    int ret;
634    int grpId;
635
636    grpId = CreateNewRtgGrp(VIP, 0);
637    ASSERT_GT(grpId, 0);
638    ret = SetFrameRateAndPrioType(grpId, 60, VIP);
639    ASSERT_EQ(ret, RTG_SUCC);
640    ret = DestroyRtgGrp(grpId);
641    ASSERT_EQ(ret, RTG_SUCC);
642}
643
644/**
645 * @tc.name: SetRtgAttrFail
646 * @tc.desc: Verify rtg attr set function with error param.
647 * @tc.type: FUNC
648 */
649HWTEST_F(RtgTest, SetRtgAttrFail, Function | MediumTest | Level1)
650{
651    int ret;
652    int grpId;
653    grpId = CreateNewRtgGrp(VIP, 0);
654    ASSERT_GT(grpId, 0);
655    ret = SetFrameRateAndPrioType(grpId, 90, -1);
656    ASSERT_NE(ret, RTG_SUCC);
657    ret = DestroyRtgGrp(grpId);
658    ASSERT_EQ(ret, RTG_SUCC);
659}
660
661/**
662 * @tc.name: RtgAddMutipleThreadsSucc
663 * @tc.desc: Verify rtg multiple add function.
664 * @tc.type: FUNC
665 */
666HWTEST_F(RtgTest, RtgAddMutipleThreadsSucc, Function | MediumTest | Level1)
667{
668    int ret;
669    int pid[3];
670    vector<int> threads;
671    int grpId;
672
673    for (int i = 0; i < 3; i++) {
674        pid[i] = fork();
675        ASSERT_TRUE(pid[i] >= 0) << "> parent: fork errno = " << errno;
676        if (pid[i] == 0) {
677            usleep(50000);
678            _Exit(0);
679        }
680        threads.push_back(pid[i]);
681    }
682    grpId = CreateNewRtgGrp(NORMAL_TASK, 0);
683    ASSERT_GT(grpId, 0);
684    ret = AddThreadsToRtg(threads, grpId, NORMAL_TASK);
685    ASSERT_EQ(ret, RTG_SUCC);
686    ret = DestroyRtgGrp(grpId);
687    ASSERT_EQ(ret, RTG_SUCC);
688}
689
690/**
691 * @tc.name: RtgAddMutipleThreadsOutOfLimit
692 * @tc.desc: Verify rtg multiple add function with out of limit threads.
693 * @tc.type: FUNC
694 */
695HWTEST_F(RtgTest, RtgAddMutipleThreadsOutOfLimit, Function | MediumTest | Level1)
696{
697    int ret;
698    int pid[8];
699    vector<int> threads;
700    int grpId;
701
702    for (int i = 0; i < 8; i++) {
703        pid[i] = fork();
704        ASSERT_TRUE(pid[i] >= 0) << "> parent: fork errno = " << errno;
705        if (pid[i] == 0) {
706            usleep(50000);
707            _Exit(0);
708        }
709    threads.push_back(pid[i]);
710    }
711    grpId = CreateNewRtgGrp(NORMAL_TASK, 0);
712    ASSERT_GT(grpId, 0);
713    ret = AddThreadsToRtg(threads, grpId, NORMAL_TASK);
714    ASSERT_NE(ret, RTG_SUCC);
715    ret = DestroyRtgGrp(grpId);
716    ASSERT_EQ(ret, RTG_SUCC);
717}
718