bp_timer_gtest.cpp revision 9eda18ac
1/*
2 Hanoh Haim
3 Cisco Systems, Inc.
4*/
5
6/*
7Copyright (c) 2015-2015 Cisco Systems, Inc.
8
9Licensed under the Apache License, Version 2.0 (the "License");
10you may not use this file except in compliance with the License.
11You may obtain a copy of the License at
12
13    http://www.apache.org/licenses/LICENSE-2.0
14
15Unless required by applicable law or agreed to in writing, software
16distributed under the License is distributed on an "AS IS" BASIS,
17WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18See the License for the specific language governing permissions and
19limitations under the License.
20*/
21
22#include <common/gtest.h>
23#include <common/basic_utils.h>
24#include "h_timer.h"
25#include <common/utl_gcc_diag.h>
26
27
28
29class gt_r_timer  : public testing::Test {
30
31protected:
32  virtual void SetUp() {
33  }
34
35  virtual void TearDown() {
36  }
37public:
38};
39
40
41
42
43TEST_F(gt_r_timer, timer1) {
44    CHTimerObj timer;
45    timer.reset();
46    timer.Dump(stdout);
47}
48
49
50
51TEST_F(gt_r_timer, timer2) {
52
53    CHTimerOneWheel timer;
54
55    EXPECT_EQ( timer.Create(513),RC_HTW_ERR_NO_LOG2);
56
57}
58
59TEST_F(gt_r_timer, timer3) {
60
61    CHTimerOneWheel timer;
62    EXPECT_EQ( timer.Create(512),RC_HTW_OK);
63    EXPECT_EQ( timer.Delete(),RC_HTW_OK);
64}
65
66
67void tw_on_tick_cb_test1(void *userdata,
68                         CHTimerObj *tmr){
69    //int tick=(int)((uintptr_t)userdata);
70
71    printf(" action %lu \n",(ulong)tmr->m_pad[0]);
72}
73
74
75TEST_F(gt_r_timer, timer4) {
76
77    CHTimerOneWheel timer;
78    CHTimerObj  tmr1;
79    CHTimerObj  tmr2;
80    tmr1.reset();
81    tmr2.reset();
82
83    tmr1.m_ticks_left=0;
84    tmr1.m_pad[0]=1;
85    tmr2.m_ticks_left=0;
86    tmr2.m_pad[0]=2;
87
88    EXPECT_EQ( timer.Create(512),RC_HTW_OK);
89    timer.timer_start(&tmr1,7);
90    timer.timer_start(&tmr2,7);
91    timer.dump_link_list(1,0,tw_on_tick_cb_test1,stdout);
92    timer.dump_link_list(7,0,tw_on_tick_cb_test1,stdout);
93
94
95    EXPECT_EQ( timer.Delete(),RC_HTW_OK);
96}
97
98TEST_F(gt_r_timer, timer5) {
99
100    CHTimerOneWheel timer;
101    CHTimerObj  tmr1;
102    CHTimerObj  tmr2;
103    tmr1.reset();
104    tmr2.reset();
105
106    tmr1.m_ticks_left=0;
107    tmr1.m_pad[0]=1;
108    tmr2.m_ticks_left=0;
109    tmr2.m_pad[0]=2;
110
111    EXPECT_EQ( timer.Create(512),RC_HTW_OK);
112    timer.timer_start(&tmr1,7);
113    timer.timer_start(&tmr2,7);
114    timer.dump_link_list(1,0,tw_on_tick_cb_test1,stdout);
115    timer.dump_link_list(7,0,tw_on_tick_cb_test1,stdout);
116
117    assert( timer.pop_event()==0);
118    int i;
119    for (i=0; i<7; i++) {
120        timer.timer_tick();
121    }
122    CHTimerObj * obj=timer.pop_event();
123    assert(obj==&tmr1);
124
125    timer.dump_link_list(7,0,tw_on_tick_cb_test1,stdout);
126
127
128    obj=timer.pop_event();
129    assert(obj==&tmr2);
130
131    EXPECT_EQ( timer.Delete(),RC_HTW_OK);
132}
133
134class CMyTestObject {
135public:
136    CMyTestObject(){
137        m_id=0;
138        m_d_tick=0;
139        m_t_tick=0;
140        m_timer.reset();
141    }
142    uint32_t    m_id;
143    uint32_t    m_d_tick;
144    uint32_t    m_t_tick;
145    CHTimerObj  m_timer;
146};
147
148
149#define MY_OFFSET_OF(cls,member) ((uintptr_t)(&(cls *0)->member) )
150
151void my_test_on_tick_cb(void *userdata,CHTimerObj *tmr){
152
153
154    CHTimerWheel * lp=(CHTimerWheel *)userdata;
155    UNSAFE_CONTAINER_OF_PUSH
156    CMyTestObject *lpobj=(CMyTestObject *)((uint8_t*)tmr-offsetof (CMyTestObject,m_timer));
157    UNSAFE_CONTAINER_OF_POP
158    printf(" [event %d ]",lpobj->m_id);
159    lp->timer_start(tmr,2);
160}
161
162TEST_F(gt_r_timer, timer6) {
163
164    CHTimerWheel timer;
165
166    CMyTestObject tmr1;
167    tmr1.m_id=12;
168
169
170    EXPECT_EQ( timer.Create(8,3),RC_HTW_OK);
171    timer.timer_start(&tmr1.m_timer,3);
172
173    int i;
174    for (i=0; i<20; i++) {
175        printf(" tick %d :",i);
176        timer.on_tick((void *)&timer,my_test_on_tick_cb);
177        printf(" \n");
178    }
179
180    EXPECT_EQ( timer.Delete(),RC_HTW_OK);
181}
182
183void my_test_on_tick_cb7(void *userdata,CHTimerObj *tmr){
184
185
186    CHTimerWheel * lp=(CHTimerWheel *)userdata;
187    UNSAFE_CONTAINER_OF_PUSH
188    CMyTestObject *lpobj=(CMyTestObject *)((uint8_t*)tmr-offsetof (CMyTestObject,m_timer));
189    UNSAFE_CONTAINER_OF_POP
190    printf(" [event %d ]",lpobj->m_id);
191    lp->timer_start(tmr,9);
192}
193
194void my_test_on_tick_cb_free(void *userdata,CHTimerObj *tmr){
195
196
197    //CHTimerWheel * lp=(CHTimerWheel *)userdata;
198    UNSAFE_CONTAINER_OF_PUSH
199    CMyTestObject *lpobj=(CMyTestObject *)((uint8_t*)tmr-offsetof (CMyTestObject,m_timer));
200    UNSAFE_CONTAINER_OF_POP
201    printf(" [event %d ]",lpobj->m_id);
202    delete lpobj;
203}
204
205
206TEST_F(gt_r_timer, timer7) {
207
208    CHTimerWheel timer;
209
210    CMyTestObject tmr1;
211    tmr1.m_id=12;
212
213
214    EXPECT_EQ( timer.Create(4,4),RC_HTW_OK);
215    timer.timer_start(&tmr1.m_timer,80);
216
217    int i;
218    for (i=0; i<150; i++) {
219        //printf(" tick %d :",i);
220        timer.on_tick((void *)&timer,my_test_on_tick_cb7);
221        //printf(" \n");
222    }
223
224    EXPECT_EQ( timer.Delete(),RC_HTW_OK);
225}
226
227
228
229class CHTimerWheelTest1Cfg {
230public:
231    uint32_t m_wheel_size;
232    uint32_t m_num_wheels;
233    uint32_t m_start_tick;
234    uint32_t m_restart_tick;
235    uint32_t m_total_ticks;
236    bool     m_verbose;
237    bool     m_dont_assert;
238};
239
240class CHTimerWheelBase {
241public:
242    virtual void on_tick(CMyTestObject *lpobj)=0;
243};
244
245
246class CHTimerWheelTest1 : public CHTimerWheelBase {
247
248public:
249    bool Create(CHTimerWheelTest1Cfg & cfg);
250    void Delete();
251    void start_test();
252    virtual void on_tick(CMyTestObject *lpobj);
253
254private:
255    CHTimerWheelTest1Cfg  m_cfg;
256    CHTimerWheel          m_timer;
257    CMyTestObject         m_event;
258    uint32_t              m_ticks;
259    uint32_t              m_total_ticks;
260    uint32_t              m_expected_total_ticks;
261
262    uint32_t              m_expect_tick;
263};
264
265void my_test_on_tick_cb8(void *userdata,CHTimerObj *tmr){
266    CHTimerWheelBase * lp=(CHTimerWheelBase *)userdata;
267    UNSAFE_CONTAINER_OF_PUSH
268    CMyTestObject *lpobj=(CMyTestObject *)((uint8_t*)tmr-offsetof (CMyTestObject,m_timer));
269    UNSAFE_CONTAINER_OF_POP
270    lp->on_tick(lpobj);
271}
272
273
274void CHTimerWheelTest1::on_tick(CMyTestObject *lpobj){
275    assert(lpobj->m_id==17);
276    m_total_ticks++;
277    if (m_cfg.m_verbose) {
278        printf(" [event %d ]",lpobj->m_id);
279    }
280    if (!m_cfg.m_dont_assert){
281        assert( m_ticks == m_expect_tick);
282    }
283    m_timer.timer_start(&lpobj->m_timer,m_cfg.m_restart_tick);
284    m_expect_tick+=m_cfg.m_restart_tick;
285}
286
287
288void CHTimerWheelTest1::start_test(){
289
290    if (m_cfg.m_verbose) {
291        printf(" test start %d,restart: %d \n",m_cfg.m_start_tick,m_cfg.m_restart_tick);
292    }
293    int i;
294    m_expected_total_ticks=0;
295    uint32_t cnt=m_cfg.m_start_tick;
296    for (i=0; i<m_cfg.m_total_ticks; i++) {
297        if (i==cnt) {
298            m_expected_total_ticks++;
299            cnt+=m_cfg.m_restart_tick;
300        }
301    }
302
303    m_total_ticks=0;
304    m_event.m_id=17;
305    m_timer.timer_start(&m_event.m_timer,m_cfg.m_start_tick);
306
307    m_ticks=0;
308    m_expect_tick= m_cfg.m_start_tick;
309
310    for (i=0; i<m_cfg.m_total_ticks; i++) {
311        if (m_cfg.m_verbose) {
312          printf(" tick %d :",i);
313        }
314        m_ticks=i;
315        m_timer.on_tick((void *)this,my_test_on_tick_cb8);
316        if (m_cfg.m_verbose) {
317          printf(" \n");
318        }
319    }
320    if (m_cfg.m_verbose) {
321       printf(" %d == %d \n",m_expected_total_ticks,m_total_ticks);
322    }
323    if (!m_cfg.m_dont_assert){
324      assert(m_expected_total_ticks ==m_total_ticks);
325    }
326}
327
328
329bool CHTimerWheelTest1::Create(CHTimerWheelTest1Cfg & cfg){
330    m_cfg = cfg;
331    assert(m_timer.Create(m_cfg.m_wheel_size,m_cfg.m_num_wheels)==RC_HTW_OK);
332    m_ticks=0;
333    return (true);
334}
335
336void CHTimerWheelTest1::Delete(){
337    assert(m_timer.Delete()==RC_HTW_OK);
338}
339
340
341TEST_F(gt_r_timer, timer8) {
342
343    CHTimerWheelTest1 test;
344
345
346    CHTimerWheelTest1Cfg  cfg ={
347        .m_wheel_size   = 4,
348        .m_num_wheels   = 4,
349        .m_start_tick   = 2,
350        .m_restart_tick = 2,
351        .m_total_ticks  =100,
352        .m_verbose=0
353    };
354    test.Create(cfg);
355    test.start_test();
356    test.Delete();
357}
358
359TEST_F(gt_r_timer, timer9) {
360
361    CHTimerWheelTest1 test;
362
363
364    CHTimerWheelTest1Cfg  cfg ={
365        .m_wheel_size   = 4,
366        .m_num_wheels   = 4,
367        .m_start_tick   = 4,
368        .m_restart_tick = 2,
369        .m_total_ticks  =20
370    };
371    test.Create(cfg);
372    test.start_test();
373    test.Delete();
374}
375
376TEST_F(gt_r_timer, timer10) {
377
378    CHTimerWheelTest1 test;
379
380
381    CHTimerWheelTest1Cfg  cfg ={
382        .m_wheel_size   = 4,
383        .m_num_wheels   = 4,
384        .m_start_tick   = 80,
385        .m_restart_tick = 9,
386        .m_total_ticks  =100
387    };
388    test.Create(cfg);
389    test.start_test();
390    test.Delete();
391}
392
393
394TEST_F(gt_r_timer, timer11) {
395
396    int i,j;
397
398    for (i=0; i<100; i++) {
399        for (j=1; j<100; j++) {
400            CHTimerWheelTest1 test;
401            CHTimerWheelTest1Cfg  cfg ={
402                .m_wheel_size   = 4,
403                .m_num_wheels   = 4,
404                .m_start_tick   = (uint32_t)i,
405                .m_restart_tick = (uint32_t)j,
406                .m_total_ticks  = 0
407            };
408            cfg.m_total_ticks= (uint32_t)(i*2+j*10);
409            test.Create(cfg);
410            test.start_test();
411            test.Delete();
412        }
413    }
414}
415
416TEST_F(gt_r_timer, timer12) {
417
418    int i;
419
420    for (i=0; i<100; i++) {
421            CHTimerWheelTest1 test;
422            CHTimerWheelTest1Cfg  cfg ={
423                .m_wheel_size   = 4,
424                .m_num_wheels   = 4,
425                .m_start_tick   = (uint32_t)i,
426                .m_restart_tick = (uint32_t)i,
427                .m_total_ticks  = 0
428            };
429            cfg.m_total_ticks= (uint32_t)(i*10);
430            test.Create(cfg);
431            test.start_test();
432            test.Delete();
433    }
434}
435
436TEST_F(gt_r_timer, timer_verylog) {
437
438
439        CHTimerWheelTest1 test;
440        CHTimerWheelTest1Cfg  cfg ={
441            .m_wheel_size   = 4,
442            .m_num_wheels   = 2,
443            .m_start_tick   = 30,
444            .m_restart_tick = 40,
445            .m_total_ticks  = 100,
446            //.m_verbose =true,
447            //.m_dont_assert=true
448
449        };
450        test.Create(cfg);
451        test.start_test();
452        test.Delete();
453}
454
455
456/////////////////////////////////////////////////////////////////////////
457
458
459class CHTimerWheelTest2Cfg {
460public:
461    uint32_t m_wheel_size;
462    uint32_t m_num_wheels;
463    uint32_t m_number_of_con_event;
464    uint32_t m_total_ticks;
465    bool     m_random;
466    bool     m_verbose;
467    bool     m_dont_check;
468};
469
470class CHTimerWheelTest2 : public CHTimerWheelBase {
471
472public:
473    bool Create(CHTimerWheelTest2Cfg & cfg);
474    void Delete();
475    void start_test();
476    virtual void on_tick(CMyTestObject *lpobj);
477
478private:
479    CHTimerWheelTest2Cfg  m_cfg;
480    CHTimerWheel          m_timer;
481    uint32_t              m_ticks;
482};
483
484bool CHTimerWheelTest2::Create(CHTimerWheelTest2Cfg & cfg){
485    m_cfg = cfg;
486    assert(m_timer.Create(m_cfg.m_wheel_size,m_cfg.m_num_wheels)==RC_HTW_OK);
487    m_ticks=0;
488    return (true);
489}
490
491void CHTimerWheelTest2::Delete(){
492    assert(m_timer.Delete()==RC_HTW_OK);
493}
494
495
496void CHTimerWheelTest2::start_test(){
497
498    CMyTestObject *  m_events = new CMyTestObject[m_cfg.m_number_of_con_event];
499    int i;
500    for (i=0; i<m_cfg.m_number_of_con_event; i++) {
501        CMyTestObject * lp=&m_events[i];
502        lp->m_id=i+1;
503        if (m_cfg.m_random) {
504            lp->m_d_tick = ((rand() % m_cfg.m_number_of_con_event)+1);
505            if (m_cfg.m_verbose) {
506                printf(" flow %d : %d \n",i,lp->m_d_tick);
507            }
508        }else{
509            lp->m_d_tick=i+1;
510        }
511        lp->m_t_tick=lp->m_d_tick;
512        m_timer.timer_start(&lp->m_timer,lp->m_d_tick);
513    }
514
515    for (i=0; i<m_cfg.m_total_ticks; i++) {
516        if (m_cfg.m_verbose) {
517          printf(" tick %d :",i);
518        }
519        m_ticks=i;
520        m_timer.on_tick((void *)this,my_test_on_tick_cb8);
521        if (m_cfg.m_verbose) {
522          printf(" \n");
523        }
524    }
525    delete []m_events;
526}
527
528
529void CHTimerWheelTest2::on_tick(CMyTestObject *lp){
530
531    if (!m_cfg.m_random) {
532        assert(lp->m_id==lp->m_d_tick);
533    }
534    if (m_cfg.m_verbose) {
535        printf(" [event %d ]",lp->m_id);
536    }
537    m_timer.timer_start(&lp->m_timer,lp->m_d_tick);
538    if (!m_cfg.m_dont_check){
539        assert(m_ticks == lp->m_t_tick);
540    }
541    lp->m_t_tick+=lp->m_d_tick;
542}
543
544TEST_F(gt_r_timer, timer13) {
545
546        CHTimerWheelTest2 test;
547        CHTimerWheelTest2Cfg  cfg ={
548            .m_wheel_size   = 4,
549            .m_num_wheels   = 4,
550            .m_number_of_con_event   = 10,
551            .m_total_ticks =1000,
552            .m_random=false,
553            .m_verbose =false
554        };
555        test.Create(cfg);
556        test.start_test();
557        test.Delete();
558}
559
560TEST_F(gt_r_timer, timer14) {
561
562        CHTimerWheelTest2 test;
563        CHTimerWheelTest2Cfg  cfg ={
564            .m_wheel_size   = 8,
565            .m_num_wheels   = 3,
566            .m_number_of_con_event   = 10,
567            .m_total_ticks =1000,
568            .m_random=false,
569            .m_verbose =false
570        };
571        test.Create(cfg);
572        test.start_test();
573        test.Delete();
574}
575
576TEST_F(gt_r_timer, timer15) {
577
578        CHTimerWheelTest2 test;
579        CHTimerWheelTest2Cfg  cfg ={
580            .m_wheel_size   = 1024,
581            .m_num_wheels   = 3,
582            .m_number_of_con_event   = 100,
583            .m_total_ticks =10000,
584            .m_random=false,
585            .m_verbose =false
586        };
587        test.Create(cfg);
588        test.start_test();
589        test.Delete();
590}
591
592TEST_F(gt_r_timer, timer16) {
593
594        CHTimerWheelTest2 test;
595        CHTimerWheelTest2Cfg  cfg ={
596            .m_wheel_size   = 32,
597            .m_num_wheels   = 4,
598            .m_number_of_con_event   = 111,
599            .m_total_ticks =20000,
600            .m_random=true,
601            .m_verbose =false,
602            .m_dont_check=false
603        };
604        test.Create(cfg);
605        test.start_test();
606        test.Delete();
607}
608
609
610/* test free of iterator */
611TEST_F(gt_r_timer, timer17) {
612
613    CHTimerWheel  timer;
614
615    CMyTestObject * tmr1;
616    tmr1 = new CMyTestObject();
617    tmr1->m_id=12;
618
619    CMyTestObject * tmr2;
620    tmr2 = new CMyTestObject();
621    tmr2->m_id=13;
622
623    CMyTestObject * tmr3;
624    tmr3 = new CMyTestObject();
625    tmr3->m_id=14;
626
627
628    EXPECT_EQ( timer.Create(4,4),RC_HTW_OK);
629    timer.timer_start(&tmr1->m_timer,80);
630    timer.timer_start(&tmr2->m_timer,1);
631    timer.timer_start(&tmr3->m_timer,0);
632
633    timer.detach_all((void *)&timer,my_test_on_tick_cb_free);
634    EXPECT_EQ( timer.Delete(),RC_HTW_OK);
635}
636
637
638TEST_F(gt_r_timer, timer18) {
639
640    RC_HTW_t res[]={
641        RC_HTW_OK,
642        RC_HTW_ERR_NO_RESOURCES,
643        RC_HTW_ERR_TIMER_IS_ON,
644        RC_HTW_ERR_NO_LOG2,
645        RC_HTW_ERR_MAX_WHEELS,
646        RC_HTW_ERR_NOT_ENOUGH_BITS
647    };
648
649    int i;
650    for (i=0; i<sizeof(res)/sizeof(RC_HTW_t); i++) {
651        CHTimerWheelErrorStr err(res[i]);
652        printf(" %-30s  - %s \n",err.get_str(),err.get_help_str());
653    }
654}
655
656
657
658/////////////////////////////////////////////////////////////////
659/* test for NA class */
660
661class CNATimerWheelTest1Cfg {
662public:
663    uint32_t m_wheel_size;
664    uint32_t m_level1_div;
665    uint32_t m_start_tick;
666    uint32_t m_restart_tick;
667    uint32_t m_total_ticks;
668    int     m_verbose;
669    bool     m_dont_assert;
670};
671
672
673class CNATimerWheelTest1 : public CHTimerWheelBase {
674
675public:
676    bool Create(CNATimerWheelTest1Cfg & cfg);
677    void Delete();
678    void start_test();
679    virtual void on_tick(CMyTestObject *lpobj);
680
681private:
682    CNATimerWheelTest1Cfg m_cfg;
683    CNATimerWheel         m_timer;
684    CMyTestObject         m_event;
685    uint32_t              m_ticks;
686    uint32_t              m_total_ticks;
687    uint32_t              m_expected_total_ticks;
688    uint32_t              m_div_err;
689
690    uint32_t              m_expect_tick;
691    double                m_max_err;
692};
693
694void my_test_on_tick_cb18(void *userdata,CHTimerObj *tmr){
695    CHTimerWheelBase * lp=(CHTimerWheelBase *)userdata;
696    UNSAFE_CONTAINER_OF_PUSH
697    CMyTestObject *lpobj=(CMyTestObject *)((uint8_t*)tmr-offsetof (CMyTestObject,m_timer));
698    UNSAFE_CONTAINER_OF_POP
699    lp->on_tick(lpobj);
700}
701
702
703void CNATimerWheelTest1::on_tick(CMyTestObject *lpobj){
704    assert(lpobj->m_id==17);
705    m_total_ticks++;
706    if (m_cfg.m_verbose) {
707        printf(" [event(%d)-%d]",lpobj->m_timer.m_wheel,lpobj->m_id);
708    }
709    if (!m_cfg.m_dont_assert){
710        uint32_t expect_min=m_expect_tick;
711        if (expect_min>m_div_err) {
712            expect_min-=m_div_err*2;
713        }
714        double pre=abs(100.0-100.0*(double)m_ticks/(double)m_expect_tick);
715        if (pre>m_max_err){
716            m_max_err=pre;
717        }
718        if (pre>(200.0/(double)m_div_err)) {
719            printf(" =====>tick:%d expect [%d -%d] %f \n",m_ticks,expect_min,m_expect_tick+(m_div_err*2),pre);
720        }
721    }
722    m_timer.timer_start(&lpobj->m_timer,m_cfg.m_restart_tick);
723    m_expect_tick+=m_cfg.m_restart_tick;
724}
725
726
727void CNATimerWheelTest1::start_test(){
728
729    if (m_cfg.m_verbose) {
730        printf(" test start %d,restart: %d \n",m_cfg.m_start_tick,m_cfg.m_restart_tick);
731    }
732    int i;
733    m_expected_total_ticks=0;
734    uint32_t cnt=m_cfg.m_start_tick;
735    for (i=0; i<m_cfg.m_total_ticks; i++) {
736        if (i==cnt) {
737            m_expected_total_ticks++;
738            cnt+=m_cfg.m_restart_tick;
739        }
740    }
741
742    m_div_err =m_cfg.m_wheel_size/m_cfg.m_level1_div;
743    m_total_ticks=0;
744    m_event.m_id=17;
745    m_timer.timer_start(&m_event.m_timer,m_cfg.m_start_tick);
746
747    m_ticks=0;
748    m_expect_tick= m_cfg.m_start_tick;
749
750    for (i=0; i<m_cfg.m_total_ticks; i++) {
751        if (m_cfg.m_verbose) {
752          printf(" tick %d :",i);
753        }
754        m_ticks=i;
755        m_timer.on_tick_level0((void *)this,my_test_on_tick_cb18);
756        /* level 2 */
757        if ((i>=m_div_err) && (i%m_div_err==0)) {
758            int cnt_rerty=0;
759            while (true){
760                if (m_cfg.m_verbose>1) {
761                  printf("\n level1 - try %d \n",cnt_rerty);
762                }
763
764                na_htw_state_num_t state;
765                state = m_timer.on_tick_level1((void *)this,my_test_on_tick_cb18);
766                if (m_cfg.m_verbose>1) {
767                  printf("\n state - %lu \n",(ulong)state);
768                }
769
770                if ( state !=TW_NEXT_BATCH){
771                    break;
772                }
773                cnt_rerty++;
774            }
775            if (m_cfg.m_verbose>1) {
776               printf("\n level1 - stop %d \n",cnt_rerty);
777            }
778        }
779        if (m_cfg.m_verbose) {
780          printf(" \n");
781        }
782    }
783    if (m_cfg.m_verbose) {
784       printf(" %d == %d \n",m_expected_total_ticks,m_total_ticks);
785    }
786    if (!m_cfg.m_dont_assert){
787      //assert( (m_expected_total_ticks==m_total_ticks) || ((m_expected_total_ticks+1) ==m_total_ticks) );
788    }
789}
790
791
792bool CNATimerWheelTest1::Create(CNATimerWheelTest1Cfg & cfg){
793    m_cfg = cfg;
794    m_max_err=0.0;
795    assert(m_timer.Create(m_cfg.m_wheel_size,m_cfg.m_level1_div)==RC_HTW_OK);
796    m_ticks=0;
797    return (true);
798}
799
800void CNATimerWheelTest1::Delete(){
801    //printf (" %f \n",m_max_err);
802    assert(m_timer.Delete()==RC_HTW_OK);
803}
804
805
806TEST_F(gt_r_timer, timer20) {
807
808    CNATimerWheelTest1 test;
809
810    CNATimerWheelTest1Cfg  cfg ={
811        .m_wheel_size    = 32,
812        .m_level1_div    = 4,
813        .m_start_tick    = 2,
814        .m_restart_tick  = 2,
815        .m_total_ticks   = 1024,
816        .m_verbose=0
817    };
818    test.Create(cfg);
819    test.start_test();
820    test.Delete();
821}
822
823TEST_F(gt_r_timer, timer21) {
824
825    CNATimerWheelTest1 test;
826
827    CNATimerWheelTest1Cfg  cfg ={
828        .m_wheel_size    = 32,
829        .m_level1_div    = 4,
830        .m_start_tick    = 2,
831        .m_restart_tick  = 34,
832        .m_total_ticks   = 100,
833        .m_verbose=0
834    };
835    test.Create(cfg);
836    test.start_test();
837    test.Delete();
838}
839
840
841TEST_F(gt_r_timer, timer22) {
842
843    CNATimerWheelTest1 test;
844
845    CNATimerWheelTest1Cfg  cfg ={
846        .m_wheel_size    = 32,
847        .m_level1_div    = 4,
848        .m_start_tick    = 2,
849        .m_restart_tick  = 55,
850        .m_total_ticks   = 1000,
851        .m_verbose=0,
852        .m_dont_assert =0
853    };
854    test.Create(cfg);
855    test.start_test();
856    test.Delete();
857}
858
859TEST_F(gt_r_timer, timer23) {
860
861    int i,j;
862
863    for (i=0; i<100; i++) {
864        for (j=1; j<100; j++) {
865            CNATimerWheelTest1 test;
866            CNATimerWheelTest1Cfg  cfg ={
867                .m_wheel_size    = 32,
868                .m_level1_div    = 4,
869                .m_start_tick    = (uint32_t)i,
870                .m_restart_tick  = (uint32_t)j,
871                .m_total_ticks   = 1000,
872                .m_verbose=0,
873                .m_dont_assert =0
874            };
875
876            cfg.m_total_ticks= (uint32_t)(i*2+j*10);
877            test.Create(cfg);
878            test.start_test();
879            test.Delete();
880        }
881    }
882}
883
884
885
886#if 0
887// too long, skip for now
888TEST_F(gt_r_timer, timer24) {
889
890    int i,j;
891
892    for (i=0; i<2048; i++) {
893        printf(" %d \n",i);
894        for (j=1024; j<2048; j=j+7) {
895            CNATimerWheelTest1 test;
896            CNATimerWheelTest1Cfg  cfg ={
897                .m_wheel_size    = 1024,
898                .m_level1_div    = 32,
899                .m_start_tick    = (uint32_t)i,
900                .m_restart_tick  = (uint32_t)j,
901                .m_total_ticks   = 3000,
902                .m_verbose=0,
903                .m_dont_assert =0
904            };
905
906            cfg.m_total_ticks= (uint32_t)(i*2+j*10);
907            test.Create(cfg);
908            test.start_test();
909            test.Delete();
910        }
911    }
912}
913#endif
914
915/* very long flow, need to restart it */
916TEST_F(gt_r_timer, timer25) {
917
918
919        CNATimerWheelTest1 test;
920
921        CNATimerWheelTest1Cfg  cfg ={
922            .m_wheel_size    = 32,
923            .m_level1_div    = 4,
924            .m_start_tick    = 2,
925            .m_restart_tick  = 512,
926            .m_total_ticks   = 1000,
927            .m_verbose=0,
928            .m_dont_assert =0
929        };
930
931        test.Create(cfg);
932        test.start_test();
933        test.Delete();
934}
935
936
937
938////////////////////////////////////////////////////////
939
940class CNATimerWheelTest2Cfg {
941public:
942    uint32_t m_wheel_size;
943    uint32_t m_level1_div;
944    uint32_t m_number_of_con_event;
945    uint32_t m_total_ticks;
946    bool     m_random;
947    bool     m_burst;
948    int      m_verbose;
949    bool     m_dont_check;
950};
951
952class CNATimerWheelTest2 : public CHTimerWheelBase {
953
954public:
955    bool Create(CNATimerWheelTest2Cfg & cfg);
956    void Delete();
957    void start_test();
958    virtual void on_tick(CMyTestObject *lpobj);
959
960private:
961    CNATimerWheelTest2Cfg  m_cfg;
962    CNATimerWheel          m_timer;
963    uint32_t              m_ticks;
964    uint32_t              m_div_err;
965};
966
967bool CNATimerWheelTest2::Create(CNATimerWheelTest2Cfg & cfg){
968    m_cfg = cfg;
969    assert(m_timer.Create(m_cfg.m_wheel_size,m_cfg.m_level1_div)==RC_HTW_OK);
970    m_ticks=0;
971    return (true);
972}
973
974void CNATimerWheelTest2::Delete(){
975    assert(m_timer.Delete()==RC_HTW_OK);
976}
977
978
979void CNATimerWheelTest2::start_test(){
980
981    CMyTestObject *  m_events = new CMyTestObject[m_cfg.m_number_of_con_event];
982    int i;
983    for (i=0; i<m_cfg.m_number_of_con_event; i++) {
984        CMyTestObject * lp=&m_events[i];
985        lp->m_id=i+1;
986        if (m_cfg.m_random) {
987            lp->m_d_tick = ((rand() % m_cfg.m_number_of_con_event)+1);
988            if (m_cfg.m_verbose) {
989                printf(" flow %d : %d \n",i,lp->m_d_tick);
990            }
991        }else{
992            if (m_cfg.m_burst){
993                lp->m_d_tick = m_cfg.m_wheel_size*2; /* all in the same bucket */
994            }else{
995                lp->m_d_tick=i+1;
996            }
997        }
998        lp->m_t_tick=lp->m_d_tick;
999        m_timer.timer_start(&lp->m_timer,lp->m_d_tick);
1000    }
1001
1002    m_div_err =m_cfg.m_wheel_size/m_cfg.m_level1_div;
1003
1004    for (i=0; i<m_cfg.m_total_ticks; i++) {
1005        if (m_cfg.m_verbose) {
1006          printf(" tick %d :",i);
1007        }
1008        m_ticks=i;
1009        m_timer.on_tick_level0((void *)this,my_test_on_tick_cb18);
1010
1011        if ((i>=m_div_err) && (i%m_div_err==0)) {
1012            int cnt_rerty=0;
1013            while (true){
1014                if (m_cfg.m_verbose>1) {
1015                  printf("\n level1 - try %d \n",cnt_rerty);
1016                }
1017
1018                na_htw_state_num_t state;
1019                state = m_timer.on_tick_level1((void *)this,my_test_on_tick_cb18);
1020                if (m_cfg.m_verbose>1) {
1021                  printf("\n state - %lu \n",(ulong)state);
1022                }
1023
1024                if ( state !=TW_NEXT_BATCH){
1025                    break;
1026                }
1027
1028                cnt_rerty++;
1029            }
1030            if (m_cfg.m_verbose>1) {
1031               printf("\n level1 - stop %d \n",cnt_rerty);
1032            }
1033        }
1034
1035
1036        if (m_cfg.m_verbose) {
1037          printf(" \n");
1038        }
1039    }
1040    delete []m_events;
1041}
1042
1043
1044void CNATimerWheelTest2::on_tick(CMyTestObject *lp){
1045
1046    if (!m_cfg.m_random && !m_cfg.m_burst) {
1047        assert(lp->m_id==lp->m_d_tick);
1048    }
1049    if (m_cfg.m_verbose) {
1050        printf(" [event %d ]",lp->m_id);
1051    }
1052    m_timer.timer_start(&lp->m_timer,lp->m_d_tick);
1053    if (!m_cfg.m_dont_check){
1054        double pre=abs(100.0-100.0*(double)m_ticks/(double)lp->m_t_tick);
1055        if (pre>(200.0/(double)m_div_err)) {
1056            printf(" =====>tick:%d  %f \n",m_ticks,pre);
1057            assert(0);
1058        }
1059    }
1060    lp->m_t_tick+=lp->m_d_tick;
1061}
1062
1063
1064TEST_F(gt_r_timer, timer30) {
1065
1066        CNATimerWheelTest2 test;
1067        CNATimerWheelTest2Cfg  cfg ={
1068            .m_wheel_size    = 32,
1069            .m_level1_div    = 4,
1070            .m_number_of_con_event   = 100,
1071            .m_total_ticks =1000,
1072            .m_random=false,
1073            .m_burst=false,
1074            .m_verbose =false
1075        };
1076        test.Create(cfg);
1077        test.start_test();
1078        test.Delete();
1079}
1080
1081TEST_F(gt_r_timer, timer31) {
1082
1083        CNATimerWheelTest2 test;
1084        CNATimerWheelTest2Cfg  cfg ={
1085            .m_wheel_size    = 32,
1086            .m_level1_div    = 4,
1087            .m_number_of_con_event   = 500,
1088            .m_total_ticks =5000,
1089            .m_random=true,
1090            .m_burst=false,
1091            .m_verbose =false
1092        };
1093        test.Create(cfg);
1094        test.start_test();
1095        test.Delete();
1096}
1097
1098TEST_F(gt_r_timer, timer32) {
1099
1100        CNATimerWheelTest2 test;
1101        CNATimerWheelTest2Cfg  cfg ={
1102            .m_wheel_size    = 32,
1103            .m_level1_div    = 4,
1104            .m_number_of_con_event   = 500,
1105            .m_total_ticks =100,
1106            .m_random=false,
1107            .m_burst=true,
1108            .m_verbose =0
1109        };
1110        test.Create(cfg);
1111        test.start_test();
1112        test.Delete();
1113}
1114
1115