From eb6b6685f09fbc4822492a1db9eaa367f46c657c Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Mon, 16 Oct 2017 15:09:11 +0000 Subject: Enhancements in the test engine, not finished. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10835 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- test/rt/.cproject | 2 +- test/rt/configuration.xml | 2615 ++++++++++++++-------------- test/rt/source/test/rt_test_root.c | 165 ++ test/rt/source/test/rt_test_root.h | 102 ++ test/rt/source/test/rt_test_sequence_001.c | 229 +++ test/rt/source/test/rt_test_sequence_001.h | 27 + test/rt/source/test/rt_test_sequence_002.c | 282 +++ test/rt/source/test/rt_test_sequence_002.h | 27 + test/rt/source/test/rt_test_sequence_003.c | 344 ++++ test/rt/source/test/rt_test_sequence_003.h | 27 + test/rt/source/test/rt_test_sequence_004.c | 130 ++ test/rt/source/test/rt_test_sequence_004.h | 27 + test/rt/source/test/rt_test_sequence_005.c | 508 ++++++ test/rt/source/test/rt_test_sequence_005.h | 27 + test/rt/source/test/rt_test_sequence_006.c | 1069 ++++++++++++ test/rt/source/test/rt_test_sequence_006.h | 27 + test/rt/source/test/rt_test_sequence_007.c | 123 ++ test/rt/source/test/rt_test_sequence_007.h | 27 + test/rt/source/test/rt_test_sequence_008.c | 569 ++++++ test/rt/source/test/rt_test_sequence_008.h | 27 + test/rt/source/test/rt_test_sequence_009.c | 409 +++++ test/rt/source/test/rt_test_sequence_009.h | 27 + test/rt/source/test/rt_test_sequence_010.c | 297 ++++ test/rt/source/test/rt_test_sequence_010.h | 27 + test/rt/source/test/rt_test_sequence_011.c | 272 +++ test/rt/source/test/rt_test_sequence_011.h | 27 + test/rt/source/test/rt_test_sequence_012.c | 284 +++ test/rt/source/test/rt_test_sequence_012.h | 27 + test/rt/source/test/rt_test_sequence_013.c | 1031 +++++++++++ test/rt/source/test/rt_test_sequence_013.h | 27 + test/rt/source/test/test_root.c | 165 -- test/rt/source/test/test_root.h | 102 -- test/rt/source/test/test_sequence_001.c | 229 --- test/rt/source/test/test_sequence_001.h | 27 - test/rt/source/test/test_sequence_002.c | 282 --- test/rt/source/test/test_sequence_002.h | 27 - test/rt/source/test/test_sequence_003.c | 344 ---- test/rt/source/test/test_sequence_003.h | 27 - test/rt/source/test/test_sequence_004.c | 130 -- test/rt/source/test/test_sequence_004.h | 27 - test/rt/source/test/test_sequence_005.c | 508 ------ test/rt/source/test/test_sequence_005.h | 27 - test/rt/source/test/test_sequence_006.c | 1069 ------------ test/rt/source/test/test_sequence_006.h | 27 - test/rt/source/test/test_sequence_007.c | 123 -- test/rt/source/test/test_sequence_007.h | 27 - test/rt/source/test/test_sequence_008.c | 569 ------ test/rt/source/test/test_sequence_008.h | 27 - test/rt/source/test/test_sequence_009.c | 409 ----- test/rt/source/test/test_sequence_009.h | 27 - test/rt/source/test/test_sequence_010.c | 297 ---- test/rt/source/test/test_sequence_010.h | 27 - test/rt/source/test/test_sequence_011.c | 272 --- test/rt/source/test/test_sequence_011.h | 27 - test/rt/source/test/test_sequence_012.c | 284 --- test/rt/source/test/test_sequence_012.h | 27 - test/rt/source/test/test_sequence_013.c | 1031 ----------- test/rt/source/test/test_sequence_013.h | 27 - test/rt/test.mk | 28 +- 59 files changed, 7489 insertions(+), 7486 deletions(-) create mode 100644 test/rt/source/test/rt_test_root.c create mode 100644 test/rt/source/test/rt_test_root.h create mode 100644 test/rt/source/test/rt_test_sequence_001.c create mode 100644 test/rt/source/test/rt_test_sequence_001.h create mode 100644 test/rt/source/test/rt_test_sequence_002.c create mode 100644 test/rt/source/test/rt_test_sequence_002.h create mode 100644 test/rt/source/test/rt_test_sequence_003.c create mode 100644 test/rt/source/test/rt_test_sequence_003.h create mode 100644 test/rt/source/test/rt_test_sequence_004.c create mode 100644 test/rt/source/test/rt_test_sequence_004.h create mode 100644 test/rt/source/test/rt_test_sequence_005.c create mode 100644 test/rt/source/test/rt_test_sequence_005.h create mode 100644 test/rt/source/test/rt_test_sequence_006.c create mode 100644 test/rt/source/test/rt_test_sequence_006.h create mode 100644 test/rt/source/test/rt_test_sequence_007.c create mode 100644 test/rt/source/test/rt_test_sequence_007.h create mode 100644 test/rt/source/test/rt_test_sequence_008.c create mode 100644 test/rt/source/test/rt_test_sequence_008.h create mode 100644 test/rt/source/test/rt_test_sequence_009.c create mode 100644 test/rt/source/test/rt_test_sequence_009.h create mode 100644 test/rt/source/test/rt_test_sequence_010.c create mode 100644 test/rt/source/test/rt_test_sequence_010.h create mode 100644 test/rt/source/test/rt_test_sequence_011.c create mode 100644 test/rt/source/test/rt_test_sequence_011.h create mode 100644 test/rt/source/test/rt_test_sequence_012.c create mode 100644 test/rt/source/test/rt_test_sequence_012.h create mode 100644 test/rt/source/test/rt_test_sequence_013.c create mode 100644 test/rt/source/test/rt_test_sequence_013.h delete mode 100644 test/rt/source/test/test_root.c delete mode 100644 test/rt/source/test/test_root.h delete mode 100644 test/rt/source/test/test_sequence_001.c delete mode 100644 test/rt/source/test/test_sequence_001.h delete mode 100644 test/rt/source/test/test_sequence_002.c delete mode 100644 test/rt/source/test/test_sequence_002.h delete mode 100644 test/rt/source/test/test_sequence_003.c delete mode 100644 test/rt/source/test/test_sequence_003.h delete mode 100644 test/rt/source/test/test_sequence_004.c delete mode 100644 test/rt/source/test/test_sequence_004.h delete mode 100644 test/rt/source/test/test_sequence_005.c delete mode 100644 test/rt/source/test/test_sequence_005.h delete mode 100644 test/rt/source/test/test_sequence_006.c delete mode 100644 test/rt/source/test/test_sequence_006.h delete mode 100644 test/rt/source/test/test_sequence_007.c delete mode 100644 test/rt/source/test/test_sequence_007.h delete mode 100644 test/rt/source/test/test_sequence_008.c delete mode 100644 test/rt/source/test/test_sequence_008.h delete mode 100644 test/rt/source/test/test_sequence_009.c delete mode 100644 test/rt/source/test/test_sequence_009.h delete mode 100644 test/rt/source/test/test_sequence_010.c delete mode 100644 test/rt/source/test/test_sequence_010.h delete mode 100644 test/rt/source/test/test_sequence_011.c delete mode 100644 test/rt/source/test/test_sequence_011.h delete mode 100644 test/rt/source/test/test_sequence_012.c delete mode 100644 test/rt/source/test/test_sequence_012.h delete mode 100644 test/rt/source/test/test_sequence_013.c delete mode 100644 test/rt/source/test/test_sequence_013.h (limited to 'test/rt') diff --git a/test/rt/.cproject b/test/rt/.cproject index e92ac3785..e849ada7d 100644 --- a/test/rt/.cproject +++ b/test/rt/.cproject @@ -36,8 +36,8 @@ - + diff --git a/test/rt/configuration.xml b/test/rt/configuration.xml index 056687afe..75e1b1966 100644 --- a/test/rt/configuration.xml +++ b/test/rt/configuration.xml @@ -10,20 +10,20 @@ - @@ -31,118 +31,121 @@ + + rt_ + - - @@ -194,20 +197,20 @@ systime_t test_wait_tick(void) { - @@ -243,107 +246,107 @@ test_println("");]]> - @@ -365,21 +368,21 @@ test_println("");]]> - @@ -413,9 +416,9 @@ static void vtcb(void *p) { - @@ -427,9 +430,9 @@ test_assert(result == false, "ready list check failed");]]> - @@ -441,9 +444,9 @@ test_assert(result == false, "virtual timers list check failed");]]> - @@ -455,9 +458,9 @@ test_assert(result == false, "registry list check failed");]]> - @@ -481,7 +484,7 @@ test_assert(result == false, "port layer check failed");]]> - @@ -494,7 +497,7 @@ virtual_timer_t vt;]]> - @@ -506,9 +509,9 @@ chSysRestoreStatusX(sts);]]> - @@ -520,8 +523,8 @@ chSysUnlock();]]> - @@ -533,8 +536,8 @@ chSysUnlock();]]> - @@ -546,10 +549,10 @@ chSysUnconditionalUnlock();]]> - @@ -585,9 +588,9 @@ test_assert(chVTIsArmed(&vt) == false, "timer still armed");]]> - @@ -623,11 +626,11 @@ chSysEnable();]]> - @@ -649,9 +652,9 @@ while (time == chVTGetSystemTimeX()) { - @@ -685,10 +688,10 @@ while (time == chVTGetSystemTimeX()) { - @@ -700,10 +703,10 @@ test_assert_time_window(time + 100, - @@ -715,10 +718,10 @@ test_assert_time_window(time + US2ST(100000), - @@ -730,10 +733,10 @@ test_assert_time_window(time + MS2ST(100), - @@ -745,10 +748,10 @@ test_assert_time_window(time + S2ST(1), - @@ -784,12 +787,12 @@ test_assert_time_window(time + 100, - @@ -801,12 +804,12 @@ test_assert_sequence("ABCDE", "invalid sequence");]]> - @@ -818,12 +821,12 @@ test_assert_sequence("ABCDE", "invalid sequence");]]> - @@ -859,9 +862,9 @@ test_assert_sequence("ABCDE", "invalid sequence");]]> - @@ -873,8 +876,8 @@ test_assert(chThdGetPriorityX() == prio + 1, "unexpected priority level");]]> - @@ -910,8 +913,8 @@ test_assert(chThdGetPriorityX() == prio, "unexpected priority level");]]> - prio += 2; + prio += 2; test_assert(chThdGetPriorityX() == prio + 2, "unexpected priority level");]]> @@ -923,9 +926,9 @@ test_assert(chThdGetPriorityX() == prio + 2, "unexpected priority level");]]> - prio == prio + 2, "unexpected priority level"); + prio == prio + 2, "unexpected priority level"); test_assert(chThdGetSelfX()->realprio == prio + 1, "unexpected returned real priority level");]]> @@ -937,9 +940,9 @@ test_assert(chThdGetSelfX()->realprio == prio + 1, "unexpected returned real pri - prio == prio + 3, "unexpected priority level"); + prio == prio + 3, "unexpected priority level"); test_assert(chThdGetSelfX()->realprio == prio + 3, "unexpected real priority level");]]> @@ -951,9 +954,9 @@ test_assert(chThdGetSelfX()->realprio == prio + 3, "unexpected real priority lev - prio = prio; -chThdGetSelfX()->realprio = prio; + prio = prio; +chThdGetSelfX()->realprio = prio; chSysUnlock();]]> @@ -975,15 +978,15 @@ chSysUnlock();]]> - @@ -1005,7 +1008,7 @@ static THD_FUNCTION(thread1, p) { - @@ -1018,12 +1021,12 @@ msg_t msg;]]> - @@ -1035,14 +1038,14 @@ test_wait_threads();]]> - @@ -1064,36 +1067,36 @@ test_assert(MSG_TIMEOUT == msg, "wrong returned message");]]> CH_CFG_USE_SEMAPHORES - @@ -1127,10 +1130,10 @@ static THD_FUNCTION(thread4, p) { - @@ -1142,7 +1145,7 @@ test_assert(MSG_OK == msg, "wrong returned message");]]> - @@ -1154,7 +1157,7 @@ test_assert_lock(chSemGetCounterI(&sem1) == 1, "wrong counter value");]]> - @@ -1190,10 +1193,10 @@ test_assert_lock(chSemGetCounterI(&sem1) == 2, "wrong counter value");]]> - @@ -1205,16 +1208,16 @@ threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()+2, thread1, " - @@ -1238,8 +1241,8 @@ test_assert_sequence("ABCDE", "invalid sequence"); - @@ -1252,9 +1255,9 @@ msg_t msg;]]> - @@ -1266,12 +1269,12 @@ test_assert(sem1.cnt == 0, "counter not zero");]]> - @@ -1283,16 +1286,16 @@ test_assert(sem1.cnt == 0, "counter not zero");]]> - @@ -1339,12 +1342,12 @@ test_assert_time_window(target_time, target_time + ALLOWED_DELAY, - @@ -1391,8 +1394,8 @@ test_assert_sequence("A", "invalid sequence");]]> - @@ -1404,8 +1407,8 @@ test_assert(sem1.cnt == 0, "counter not zero");]]> - @@ -1429,7 +1432,7 @@ test_assert(sem1.cnt == 0, "counter not zero");]]> - @@ -1442,7 +1445,7 @@ msg_t msg;]]> - @@ -1454,7 +1457,7 @@ test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken");]]> - @@ -1466,7 +1469,7 @@ test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken");]]> - @@ -1478,8 +1481,8 @@ test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken");]]> - @@ -1491,8 +1494,8 @@ test_assert(msg == MSG_OK, "unexpected message");]]> - @@ -1504,8 +1507,8 @@ test_assert_lock(chSemGetCounterI(&bsem.sem) == 1, "unexpected counter");]]> - @@ -1527,178 +1530,178 @@ test_assert_lock(chSemGetCounterI(&bsem.sem) == 1, "unexpected counter");]]>CH_CFG_USE_MUTEXES - @@ -1754,10 +1757,10 @@ static THD_FUNCTION(thread9, p) { - @@ -1769,9 +1772,9 @@ threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread1, "A");]]> - @@ -1818,10 +1821,10 @@ test_assert_sequence("ABCDE", "invalid sequence");]]> - @@ -1833,7 +1836,7 @@ test_assert_sequence("ABC", "invalid sequence");]]> - @@ -1851,7 +1854,7 @@ test_assert_sequence("ABC", "invalid sequence");]]> - @@ -1881,12 +1884,12 @@ chMtxObjectInit(&m2); /* Mutex A.*/]]> - @@ -1898,7 +1901,7 @@ test_assert_sequence("ABCDE", "invalid sequence");]]> - @@ -1917,7 +1920,7 @@ Thread A performs wait(50), lock(m1), unlock(m1), exit. Thread B performs wait(1 - @@ -1936,8 +1939,8 @@ chMtxObjectInit(&m2);]]> - @@ -1949,7 +1952,7 @@ pb = p + 2;]]> - @@ -1961,7 +1964,7 @@ threads[1] = chThdCreateStatic(wa[1], WA_SIZE, pb, thread4B, "B");]]> - @@ -1973,7 +1976,7 @@ test_assert(chThdGetPriorityX() == p, "wrong priority level");]]> - @@ -1985,7 +1988,7 @@ test_assert(chThdGetPriorityX() == pa, "wrong priority level");]]> - @@ -1997,7 +2000,7 @@ test_assert(chThdGetPriorityX() == pa, "wrong priority level");]]> - @@ -2009,7 +2012,7 @@ test_assert(chThdGetPriorityX() == pb, "wrong priority level");]]> - @@ -2021,7 +2024,7 @@ test_assert(chThdGetPriorityX() == pa, "wrong priority level");]]> - @@ -2045,7 +2048,7 @@ test_assert(chThdGetPriorityX() == p, "wrong priority level");]]> - @@ -2069,7 +2072,7 @@ tprio_t prio;]]> - @@ -2081,7 +2084,7 @@ test_assert(b, "already locked");]]> - @@ -2093,8 +2096,8 @@ test_assert(!b, "not locked");]]> - @@ -2117,13 +2120,13 @@ test_assert(queue_isempty(&m1.queue), "queue not empty");]]> - @@ -2158,7 +2161,7 @@ test_assert(queue_isempty(&m1.queue), "queue not empty");]]> - @@ -2182,7 +2185,7 @@ tprio_t prio;]]> - @@ -2194,7 +2197,7 @@ test_assert(b, "already locked");]]> - @@ -2206,7 +2209,7 @@ test_assert(b, "already locked");]]> - @@ -2218,8 +2221,8 @@ test_assert(m1.owner != NULL, "not owned");]]> - @@ -2242,18 +2245,18 @@ test_assert(queue_isempty(&m1.queue), "queue not empty");]]> - @@ -2265,16 +2268,16 @@ test_assert(m1.cnt == 0, "invalid recursion counter");]]> - @@ -2304,7 +2307,7 @@ The test expects the threads to reach their goal in increasing priority order re - @@ -2323,11 +2326,11 @@ chMtxObjectInit(&m1);]]> - @@ -2339,15 +2342,15 @@ threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread6, "A");]]> - @@ -2366,7 +2369,7 @@ The test expects the threads to reach their goal in increasing priority order re - @@ -2385,11 +2388,11 @@ chMtxObjectInit(&m1);]]> - @@ -2401,8 +2404,8 @@ threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread6, "A");]]> - @@ -2420,8 +2423,8 @@ test_assert_sequence("ABCDE", "invalid sequence");]]> - @@ -2506,7 +2509,7 @@ chMtxObjectInit(&m2);]]> - @@ -2528,12 +2531,12 @@ test_assert_sequence("ABC", "invalid sequence");]]> CH_CFG_USE_MESSAGES - @@ -2556,7 +2559,7 @@ The test expect to receive the messages in the correct sequence and to not find - @@ -2569,7 +2572,7 @@ msg_t msg;]]> - @@ -2581,15 +2584,15 @@ msg_t msg;]]> - @@ -2611,26 +2614,26 @@ test_assert_sequence("ABCD", "invalid sequence");]]> CH_CFG_USE_EVENTS - @@ -2676,8 +2679,8 @@ The test expects that the even source has listeners after the registrations and - @@ -2689,7 +2692,7 @@ test_assert_lock(chEvtIsListeningI(&es1), "no listener");]]> - @@ -2701,7 +2704,7 @@ test_assert_lock(chEvtIsListeningI(&es1), "no listener");]]> - @@ -2737,7 +2740,7 @@ test_assert_lock(!chEvtIsListeningI(&es1), "stuck listener");]]> - @@ -2761,7 +2764,7 @@ test_assert_sequence("ABC", "invalid sequence");]]> - @@ -2785,13 +2788,13 @@ systime_t target_time;]]> - @@ -2803,8 +2806,8 @@ test_assert(m == 0, "stuck event");]]> - @@ -2816,12 +2819,12 @@ threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, - @@ -2845,7 +2848,7 @@ test_wait_threads();]]> - @@ -2869,9 +2872,9 @@ systime_t target_time;]]> - @@ -2883,8 +2886,8 @@ test_assert(m == 0, "stuck event");]]> - @@ -2896,12 +2899,12 @@ threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, - @@ -2925,7 +2928,7 @@ test_wait_threads();]]> - @@ -2949,9 +2952,9 @@ systime_t target_time;]]> - @@ -2974,8 +2977,8 @@ test_assert(m == 0, "stuck event");]]> - @@ -2987,12 +2990,12 @@ threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, - @@ -3028,11 +3031,11 @@ test_wait_threads();]]> - @@ -3044,11 +3047,11 @@ test_assert(m == 0, "spurious event");]]> - @@ -3066,16 +3069,16 @@ test_assert(m == 0, "spurious event");]]> - - @@ -3088,7 +3091,7 @@ systime_t target_time;]]> - @@ -3100,8 +3103,8 @@ chEvtRegisterMask(&es2, &el2, 4);]]> - @@ -3113,11 +3116,11 @@ threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, - @@ -3129,9 +3132,9 @@ test_wait_threads();]]> - @@ -3153,9 +3156,9 @@ test_assert(!chEvtIsListeningI(&es2), "stuck listener");]]> CH_CFG_USE_MAILBOXES - @@ -3177,7 +3180,7 @@ static MAILBOX_DECL(mb1, mb_buffer, MB_SIZE);]]> - @@ -3201,10 +3204,10 @@ unsigned i;]]> - @@ -3216,12 +3219,12 @@ test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base");]] - @@ -3233,11 +3236,11 @@ chMBResumeX(&mb1);]]> - @@ -3249,8 +3252,8 @@ test_assert(msg1 == MSG_OK, "wrong wake-up message");]]> - @@ -3262,11 +3265,11 @@ test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned");]]> - @@ -3278,9 +3281,9 @@ test_assert_sequence("ABCD", "wrong get sequence");]]> - @@ -3292,9 +3295,9 @@ test_assert(msg1 == MSG_OK, "wrong wake-up message");]]> - @@ -3318,7 +3321,7 @@ test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base");]]> - @@ -3342,13 +3345,13 @@ unsigned i;]]> - @@ -3360,15 +3363,15 @@ chMBResumeX(&mb1);]]> - @@ -3380,8 +3383,8 @@ test_assert(msg1 == MSG_OK, "wrong wake-up message");]]> - @@ -3393,13 +3396,13 @@ test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned");]]> - @@ -3411,9 +3414,9 @@ test_assert_sequence("ABCD", "wrong get sequence");]]> - @@ -3425,9 +3428,9 @@ test_assert(msg1 == MSG_OK, "wrong wake-up message");]]> - @@ -3451,7 +3454,7 @@ test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base");]]> - @@ -3464,9 +3467,9 @@ unsigned i;]]> - @@ -3478,17 +3481,17 @@ unsigned i;]]> - @@ -3500,7 +3503,7 @@ test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");]]> - @@ -3512,11 +3515,11 @@ chMBResumeX(&mb1);]]> - @@ -3538,21 +3541,21 @@ test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");]]> CH_CFG_USE_MEMPOOLS - @@ -3597,7 +3600,7 @@ static void *null_provider(size_t size, unsigned align) { - @@ -3620,7 +3623,7 @@ static void *null_provider(size_t size, unsigned align) { - @@ -3632,7 +3635,7 @@ static void *null_provider(size_t size, unsigned align) { - @@ -3655,7 +3658,7 @@ static void *null_provider(size_t size, unsigned align) { - @@ -3702,7 +3705,7 @@ test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");]]> - @@ -3725,7 +3728,7 @@ test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");]]> - @@ -3737,7 +3740,7 @@ test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");]]> - @@ -3784,7 +3787,7 @@ test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");]]> - + @@ -3805,9 +3808,9 @@ test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");]]> CH_CFG_USE_HEAP - @@ -3829,7 +3832,7 @@ memory_heap_t test_heap;]]> - @@ -3853,7 +3856,7 @@ size_t n, sz;]]> - @@ -3865,8 +3868,8 @@ test_assert(p1 == NULL, "allocation not failed");]]> - @@ -3878,11 +3881,11 @@ chHeapFree(p1);]]> - = ALLOC_SIZE, "unexpected heap state"); + = ALLOC_SIZE, "unexpected heap state"); test_assert(total_size == largest_size, "unexpected heap state");]]> @@ -3894,12 +3897,12 @@ test_assert(total_size == largest_size, "unexpected heap state");]]> - @@ -3911,12 +3914,12 @@ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");]]> - @@ -3928,17 +3931,17 @@ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");]]> - @@ -3950,13 +3953,13 @@ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");]]> - @@ -3968,10 +3971,10 @@ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");]]> - @@ -3983,7 +3986,7 @@ chHeapFree(p1);]]> - @@ -4007,7 +4010,7 @@ test_assert(n == sz, "size changed");]]> - @@ -4020,9 +4023,9 @@ size_t total_size, largest_size;]]> - @@ -4034,7 +4037,7 @@ chHeapFree(p1);]]> - @@ -4056,16 +4059,16 @@ test_assert(p1 == NULL, "allocation not failed");]]> CH_CFG_USE_DYNAMIC - @@ -4088,8 +4091,8 @@ The test expects the first two threads to successfully start and the third one t - @@ -4113,7 +4116,7 @@ tprio_t prio;]]> - @@ -4125,10 +4128,10 @@ test_assert(n1 == 1, "heap fragmented");]]> - @@ -4140,10 +4143,10 @@ test_assert(threads[0] != NULL, "thread creation failed");]]> - @@ -4155,10 +4158,10 @@ test_assert(threads[1] != NULL, "thread creation failed");]]> - @@ -4170,7 +4173,7 @@ test_assert(threads[2] == NULL, "thread creation not failed");]]> - @@ -4182,9 +4185,9 @@ test_assert_sequence("AB", "invalid sequence");]]> - @@ -4209,7 +4212,7 @@ The test expects the first four threads to successfully start and the last one t - @@ -4222,7 +4225,7 @@ tprio_t prio;]]> - @@ -4245,10 +4248,10 @@ tprio_t prio;]]> - @@ -4260,12 +4263,12 @@ threads[4] = chThdCreateFromMemoryPool(&mp1, "dyn5", prio-5, dyn_thread1, "E");] - @@ -4277,7 +4280,7 @@ test_assert(threads[4] == NULL, - @@ -4289,8 +4292,8 @@ test_assert_sequence("ABCD", "invalid sequence");]]> - @@ -4313,85 +4316,85 @@ Objective of the test sequence is to provide a performance index for the most cr - u.rdymsg; - } while (msg == MSG_OK); - chSysUnlock(); -} - -#if CH_CFG_USE_SEMAPHORES -static THD_FUNCTION(bmk_thread7, p) { - - (void)p; - while (!chThdShouldTerminateX()) - chSemWait(&sem1); -} -#endif - -static THD_FUNCTION(bmk_thread8, p) { - - do { - chThdYield(); - chThdYield(); - chThdYield(); - chThdYield(); - (*(uint32_t *)p) += 4; -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } while(!chThdShouldTerminateX()); + u.rdymsg; + } while (msg == MSG_OK); + chSysUnlock(); +} + +#if CH_CFG_USE_SEMAPHORES +static THD_FUNCTION(bmk_thread7, p) { + + (void)p; + while (!chThdShouldTerminateX()) + chSemWait(&sem1); +} +#endif + +static THD_FUNCTION(bmk_thread8, p) { + + do { + chThdYield(); + chThdYield(); + chThdYield(); + chThdYield(); + (*(uint32_t *)p) += 4; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while(!chThdShouldTerminateX()); }]]> @@ -4436,7 +4439,7 @@ static THD_FUNCTION(bmk_thread8, p) { - @@ -4448,10 +4451,10 @@ test_wait_threads();]]> - @@ -4498,7 +4501,7 @@ test_println(" ctxswc/S");]]> - @@ -4510,10 +4513,10 @@ test_wait_threads();]]> - @@ -4560,9 +4563,9 @@ test_println(" ctxswc/S");]]> - @@ -4574,7 +4577,7 @@ threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-5, bmk_thread - @@ -4586,10 +4589,10 @@ test_wait_threads();]]> - @@ -4614,7 +4617,7 @@ The Context Switch performance is calculated by measuring the number of iteratio - @@ -4627,7 +4630,7 @@ uint32_t n;]]> - @@ -4639,22 +4642,22 @@ uint32_t n;]]> - @@ -4666,9 +4669,9 @@ do { - @@ -4680,8 +4683,8 @@ test_wait_threads();]]> - @@ -4706,8 +4709,8 @@ The performance is calculated by measuring the number of iterations after a seco - @@ -4720,15 +4723,15 @@ systime_t start, end;]]> - @@ -4740,8 +4743,8 @@ do { - @@ -4765,8 +4768,8 @@ test_println(" threads/S");]]> - @@ -4779,19 +4782,19 @@ systime_t start, end;]]> - @@ -4803,8 +4806,8 @@ do { - @@ -4841,10 +4844,10 @@ The performance is calculated by measuring the number of iterations after a seco - @@ -4856,17 +4859,17 @@ threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()+1, bmk_thread - @@ -4878,8 +4881,8 @@ do { - @@ -4891,10 +4894,10 @@ test_wait_threads();]]> - @@ -4931,12 +4934,12 @@ The performance is calculated by measuring the number of iterations after a seco - @@ -4948,8 +4951,8 @@ threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, bmk_thread - @@ -4961,8 +4964,8 @@ test_wait_threads();]]> - @@ -4987,7 +4990,7 @@ The performance is calculated by measuring the number of iterations after a seco - @@ -5000,22 +5003,22 @@ uint32_t n;]]> - @@ -5027,8 +5030,8 @@ do { - @@ -5065,24 +5068,24 @@ The performance is calculated by measuring the number of iterations after a seco - @@ -5094,8 +5097,8 @@ do { - @@ -5132,24 +5135,24 @@ The performance is calculated by measuring the number of iterations after a seco - @@ -5161,8 +5164,8 @@ do { - @@ -5198,8 +5201,8 @@ test_println(" lock+unlock/S");]]> - @@ -5211,8 +5214,8 @@ test_println(" bytes");]]> - @@ -5224,8 +5227,8 @@ test_println(" bytes");]]> - @@ -5237,10 +5240,10 @@ test_println(" bytes");]]> - @@ -5252,10 +5255,10 @@ test_println(" bytes"); - @@ -5267,10 +5270,10 @@ test_println(" bytes"); - @@ -5282,10 +5285,10 @@ test_println(" bytes"); - @@ -5297,10 +5300,10 @@ test_println(" bytes"); - @@ -5312,10 +5315,10 @@ test_println(" bytes"); - diff --git a/test/rt/source/test/rt_test_root.c b/test/rt/source/test/rt_test_root.c new file mode 100644 index 000000000..8692e3ba1 --- /dev/null +++ b/test/rt/source/test/rt_test_root.c @@ -0,0 +1,165 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @mainpage Test Suite Specification + * Test suite for ChibiOS/RT. The purpose of this suite is to perform + * unit tests on the RT modules and to converge to 100% code coverage + * through successive improvements. + * + *

Test Sequences

+ * - @subpage rt_test_sequence_001 + * - @subpage rt_test_sequence_002 + * - @subpage rt_test_sequence_003 + * - @subpage rt_test_sequence_004 + * - @subpage rt_test_sequence_005 + * - @subpage rt_test_sequence_006 + * - @subpage rt_test_sequence_007 + * - @subpage rt_test_sequence_008 + * - @subpage rt_test_sequence_009 + * - @subpage rt_test_sequence_010 + * - @subpage rt_test_sequence_011 + * - @subpage rt_test_sequence_012 + * - @subpage rt_test_sequence_013 + * . + */ + +/** + * @file rt_test_root.c + * @brief Test Suite root structures code. + */ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +#if !defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/** + * @brief Array of all the test sequences. + */ +const testcase_t * const *rt_test_suite[] = { + rt_test_sequence_001, + rt_test_sequence_002, + rt_test_sequence_003, + rt_test_sequence_004, +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) + rt_test_sequence_005, +#endif +#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) + rt_test_sequence_006, +#endif +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) + rt_test_sequence_007, +#endif +#if (CH_CFG_USE_EVENTS) || defined(__DOXYGEN__) + rt_test_sequence_008, +#endif +#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__) + rt_test_sequence_009, +#endif +#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) + rt_test_sequence_010, +#endif +#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) + rt_test_sequence_011, +#endif +#if (CH_CFG_USE_DYNAMIC) || defined(__DOXYGEN__) + rt_test_sequence_012, +#endif + rt_test_sequence_013, + NULL +}; + +/*===========================================================================*/ +/* Shared code. */ +/*===========================================================================*/ + +void test_print_port_info(void) { + +#ifdef PORT_COMPILER_NAME + test_print("*** Compiler: "); + test_println(PORT_COMPILER_NAME); +#endif + test_print("*** Architecture: "); + test_println(PORT_ARCHITECTURE_NAME); +#ifdef PORT_CORE_VARIANT_NAME + test_print("*** Core Variant: "); + test_println(PORT_CORE_VARIANT_NAME); +#endif +#ifdef PORT_INFO + test_print("*** Port Info: "); + test_println(PORT_INFO); +#endif +} + +/* + * Global test buffer holding 5 working areas. + */ +ALIGNED_VAR(PORT_WORKING_AREA_ALIGN) uint8_t test_buffer[WA_SIZE * 5]; + +/* + * Pointers to the spawned threads. + */ +thread_t *threads[MAX_THREADS]; + +/* + * Pointers to the working areas. + */ +void * ROMCONST wa[5] = {test_buffer + (WA_SIZE * 0), + test_buffer + (WA_SIZE * 1), + test_buffer + (WA_SIZE * 2), + test_buffer + (WA_SIZE * 3), + test_buffer + (WA_SIZE * 4)}; + +/* + * Sets a termination request in all the test-spawned threads. + */ +void test_terminate_threads(void) { + unsigned i; + + for (i = 0; i < MAX_THREADS; i++) + if (threads[i]) + chThdTerminate(threads[i]); +} + +/* + * Waits for the completion of all the test-spawned threads. + */ +void test_wait_threads(void) { + unsigned i; + + for (i = 0; i < MAX_THREADS; i++) + if (threads[i] != NULL) { + chThdWait(threads[i]); + threads[i] = NULL; + } +} + +/* + * Delays execution until next system time tick. + */ +systime_t test_wait_tick(void) { + + chThdSleep(1); + return chVTGetSystemTime(); +} + +#endif /* !defined(__DOXYGEN__) */ diff --git a/test/rt/source/test/rt_test_root.h b/test/rt/source/test/rt_test_root.h new file mode 100644 index 000000000..81d661176 --- /dev/null +++ b/test/rt/source/test/rt_test_root.h @@ -0,0 +1,102 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_root.h + * @brief Test Suite root structures header. + */ + +#ifndef RT_TEST_ROOT_H +#define RT_TEST_ROOT_H + +#include "rt_test_sequence_001.h" +#include "rt_test_sequence_002.h" +#include "rt_test_sequence_003.h" +#include "rt_test_sequence_004.h" +#include "rt_test_sequence_005.h" +#include "rt_test_sequence_006.h" +#include "rt_test_sequence_007.h" +#include "rt_test_sequence_008.h" +#include "rt_test_sequence_009.h" +#include "rt_test_sequence_010.h" +#include "rt_test_sequence_011.h" +#include "rt_test_sequence_012.h" +#include "rt_test_sequence_013.h" + +#if !defined(__DOXYGEN__) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +extern const testcase_t * const *rt_test_suite[]; + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Shared definitions. */ +/*===========================================================================*/ + +#define TEST_SUITE_NAME "ChibiOS/RT Test Suite" + +/* + * Allowed delay in timeout checks. + */ +#define ALLOWED_DELAY TIME_MS2I(2) + +/* + * Maximum number of test threads. + */ +#define MAX_THREADS 5 + +/* + * Stack size of test threads. + */ +#if defined(CH_ARCHITECTURE_AVR) || defined(CH_ARCHITECTURE_MSP430) +#define THREADS_STACK_SIZE 48 +#elif defined(CH_ARCHITECTURE_STM8) +#define THREADS_STACK_SIZE 64 +#elif defined(CH_ARCHITECTURE_SIMIA32) +#define THREADS_STACK_SIZE 512 +#else +#define THREADS_STACK_SIZE 128 +#endif + +/* + * Working Area size of test threads. + */ +#define WA_SIZE MEM_ALIGN_NEXT(THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), \ + PORT_WORKING_AREA_ALIGN) + +#define TEST_REPORT_HOOK_HEADER test_print_port_info(); + +extern uint8_t test_buffer[WA_SIZE * 5]; +extern thread_t *threads[MAX_THREADS]; +extern void * ROMCONST wa[5]; + +void test_print_port_info(void); +void test_terminate_threads(void); +void test_wait_threads(void); +systime_t test_wait_tick(void); + +#endif /* !defined(__DOXYGEN__) */ + +#endif /* RT_TEST_ROOT_H */ diff --git a/test/rt/source/test/rt_test_sequence_001.c b/test/rt/source/test/rt_test_sequence_001.c new file mode 100644 index 000000000..1db1b491e --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_001.c @@ -0,0 +1,229 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_001.c + * @brief Test Sequence 001 code. + * + * @page rt_test_sequence_001 [1] Information + * + * File: @ref rt_test_sequence_001.c + * + *

Description

+ * This sequence reports configuration and version information about + * the RT kernel. + * + *

Test Cases

+ * - @subpage rt_test_001_001 + * - @subpage rt_test_001_002 + * . + */ + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +#include "ch.h" + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page rt_test_001_001 [1.1] Kernel Info + * + *

Description

+ * The version numbers are reported. + * + *

Test Steps

+ * - [1.1.1] Prints the version string. + * . + */ + +static void rt_test_001_001_execute(void) { + + /* [1.1.1] Prints the version string.*/ + test_set_step(1); + { + test_println("--- Product: ChibiOS/RT"); + test_print("--- Stable Flag: "); + test_printn(CH_KERNEL_STABLE); + test_println(""); + test_print("--- Version String: "); + test_println(CH_KERNEL_VERSION); + test_print("--- Major Number: "); + test_printn(CH_KERNEL_MAJOR); + test_println(""); + test_print("--- Minor Number: "); + test_printn(CH_KERNEL_MINOR); + test_println(""); + test_print("--- Patch Number: "); + test_printn(CH_KERNEL_PATCH); + test_println(""); + } +} + +static const testcase_t rt_test_001_001 = { + "Kernel Info", + NULL, + NULL, + rt_test_001_001_execute +}; + +/** + * @page rt_test_001_002 [1.2] Kernel Settings + * + *

Description

+ * The static kernel settings are reported. + * + *

Test Steps

+ * - [1.2.1] Prints the configuration options settings. + * . + */ + +static void rt_test_001_002_execute(void) { + + /* [1.2.1] Prints the configuration options settings.*/ + test_set_step(1); + { + test_print("--- CH_CFG_ST_RESOLUTION: "); + test_printn(CH_CFG_ST_RESOLUTION); + test_println(""); + test_print("--- CH_CFG_ST_FREQUENCY: "); + test_printn(CH_CFG_ST_FREQUENCY); + test_println(""); + test_print("--- CH_CFG_ST_TIMEDELTA: "); + test_printn(CH_CFG_ST_TIMEDELTA); + test_println(""); + test_print("--- CH_CFG_TIME_QUANTUM: "); + test_printn(CH_CFG_TIME_QUANTUM); + test_println(""); + test_print("--- CH_CFG_MEMCORE_SIZE: "); + test_printn(CH_CFG_MEMCORE_SIZE); + test_println(""); + test_print("--- CH_CFG_NO_IDLE_THREAD: "); + test_printn(CH_CFG_NO_IDLE_THREAD); + test_println(""); + test_print("--- CH_CFG_OPTIMIZE_SPEED: "); + test_printn(CH_CFG_OPTIMIZE_SPEED); + test_println(""); + test_print("--- CH_CFG_USE_TM: "); + test_printn(CH_CFG_USE_TM); + test_println(""); + test_print("--- CH_CFG_USE_REGISTRY: "); + test_printn(CH_CFG_USE_REGISTRY); + test_println(""); + test_print("--- CH_CFG_USE_WAITEXIT: "); + test_printn(CH_CFG_USE_WAITEXIT); + test_println(""); + test_print("--- CH_CFG_USE_SEMAPHORES: "); + test_printn(CH_CFG_USE_SEMAPHORES); + test_println(""); + test_print("--- CH_CFG_USE_SEMAPHORES_PRI: "); + test_printn(CH_CFG_USE_SEMAPHORES_PRIORITY); + test_println(""); + test_print("--- CH_CFG_USE_MUTEXES: "); + test_printn(CH_CFG_USE_MUTEXES); + test_println(""); + test_print("--- CH_CFG_USE_MUTEXES_RECURS: "); + test_printn(CH_CFG_USE_MUTEXES_RECURSIVE); + test_println(""); + test_print("--- CH_CFG_USE_CONDVARS: "); + test_printn(CH_CFG_USE_CONDVARS); + test_println(""); + test_print("--- CH_CFG_USE_CONDVARS_TIMEO: "); + test_printn(CH_CFG_USE_CONDVARS_TIMEOUT); + test_println(""); + test_print("--- CH_CFG_USE_EVENTS: "); + test_printn(CH_CFG_USE_EVENTS); + test_println(""); + test_print("--- CH_CFG_USE_EVENTS_TIMEOUT: "); + test_printn(CH_CFG_USE_EVENTS_TIMEOUT); + test_println(""); + test_print("--- CH_CFG_USE_MESSAGES: "); + test_printn(CH_CFG_USE_MESSAGES); + test_println(""); + test_print("--- CH_CFG_USE_MESSAGES_PRI: "); + test_printn(CH_CFG_USE_MESSAGES_PRIORITY); + test_println(""); + test_print("--- CH_CFG_USE_MAILBOXES: "); + test_printn(CH_CFG_USE_MAILBOXES); + test_println(""); + test_print("--- CH_CFG_USE_MEMCORE: "); + test_printn(CH_CFG_USE_MEMCORE); + test_println(""); + test_print("--- CH_CFG_USE_HEAP: "); + test_printn(CH_CFG_USE_HEAP); + test_println(""); + test_print("--- CH_CFG_USE_MEMPOOLS: "); + test_printn(CH_CFG_USE_MEMPOOLS); + test_println(""); + test_print("--- CH_CFG_USE_DYNAMIC: "); + test_printn(CH_CFG_USE_DYNAMIC); + test_println(""); + test_print("--- CH_DBG_STATISTICS: "); + test_printn(CH_DBG_STATISTICS); + test_println(""); + test_print("--- CH_DBG_SYSTEM_STATE_CHECK: "); + test_printn(CH_DBG_SYSTEM_STATE_CHECK); + test_println(""); + test_print("--- CH_DBG_ENABLE_CHECKS: "); + test_printn(CH_DBG_ENABLE_CHECKS); + test_println(""); + test_print("--- CH_DBG_ENABLE_ASSERTS: "); + test_printn(CH_DBG_ENABLE_ASSERTS); + test_println(""); + test_print("--- CH_DBG_TRACE_MASK: "); + test_printn(CH_DBG_TRACE_MASK); + test_println(""); + test_print("--- CH_DBG_TRACE_BUFFER_SIZE: "); + test_printn(CH_DBG_TRACE_BUFFER_SIZE); + test_println(""); + test_print("--- CH_DBG_ENABLE_STACK_CHECK: "); + test_printn(CH_DBG_ENABLE_STACK_CHECK); + test_println(""); + test_print("--- CH_DBG_FILL_THREADS: "); + test_printn(CH_DBG_FILL_THREADS); + test_println(""); + test_print("--- CH_DBG_THREADS_PROFILING: "); + test_printn(CH_DBG_THREADS_PROFILING); + test_println(""); + } +} + +static const testcase_t rt_test_001_002 = { + "Kernel Settings", + NULL, + NULL, + rt_test_001_002_execute +}; + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Information. + */ +const testcase_t * const rt_test_sequence_001[] = { + &rt_test_001_001, + &rt_test_001_002, + NULL +}; diff --git a/test/rt/source/test/rt_test_sequence_001.h b/test/rt/source/test/rt_test_sequence_001.h new file mode 100644 index 000000000..b760bda6c --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_001.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_001.h + * @brief Test Sequence 001 header. + */ + +#ifndef RT_TEST_SEQUENCE_001_H +#define RT_TEST_SEQUENCE_001_H + +extern const testcase_t * const rt_test_sequence_001[]; + +#endif /* RT_TEST_SEQUENCE_001_H */ diff --git a/test/rt/source/test/rt_test_sequence_002.c b/test/rt/source/test/rt_test_sequence_002.c new file mode 100644 index 000000000..9d82e6a48 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_002.c @@ -0,0 +1,282 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_002.c + * @brief Test Sequence 002 code. + * + * @page rt_test_sequence_002 [2] System layer and port interface + * + * File: @ref rt_test_sequence_002.c + * + *

Description

+ * The functionality of the system layer and port interface is tested. + * Basic RT functionality is taken for granted or this test suite could + * not even be executed. Errors in implementation are detected by + * executing this sequence with the state checker enabled + * (CH_DBG_STATE_CHECKER=TRUE). + * + *

Test Cases

+ * - @subpage rt_test_002_001 + * - @subpage rt_test_002_002 + * - @subpage rt_test_002_003 + * - @subpage rt_test_002_004 + * . + */ + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +/* Timer callback for testing system functions in ISR context.*/ +static void vtcb(void *p) { + syssts_t sts; + + (void)p; + + /* Testing normal case.*/ + chSysLockFromISR(); + chSysUnlockFromISR(); + + /* Reentrant case.*/ + chSysLockFromISR(); + sts = chSysGetStatusAndLockX(); + chSysRestoreStatusX(sts); + chSysUnlockFromISR(); +} + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page rt_test_002_001 [2.1] System integrity functionality + * + *

Description

+ * The system self-test functionality is invoked in order to make an + * initial system state assessment and for coverage. + * + *

Test Steps

+ * - [2.1.1] Testing Ready List integrity. + * - [2.1.2] Testing Virtual Timers List integrity. + * - [2.1.3] Testing Registry List integrity. + * - [2.1.4] Testing Port-defined integrity. + * . + */ + +static void rt_test_002_001_execute(void) { + bool result; + + /* [2.1.1] Testing Ready List integrity.*/ + test_set_step(1); + { + chSysLock(); + result = chSysIntegrityCheckI(CH_INTEGRITY_RLIST); + chSysUnlock(); + test_assert(result == false, "ready list check failed"); + } + + /* [2.1.2] Testing Virtual Timers List integrity.*/ + test_set_step(2); + { + chSysLock(); + result = chSysIntegrityCheckI(CH_INTEGRITY_VTLIST); + chSysUnlock(); + test_assert(result == false, "virtual timers list check failed"); + } + + /* [2.1.3] Testing Registry List integrity.*/ + test_set_step(3); + { + chSysLock(); + result = chSysIntegrityCheckI(CH_INTEGRITY_REGISTRY); + chSysUnlock(); + test_assert(result == false, "registry list check failed"); + } + + /* [2.1.4] Testing Port-defined integrity.*/ + test_set_step(4); + { + chSysLock(); + result = chSysIntegrityCheckI(CH_INTEGRITY_PORT); + chSysUnlock(); + test_assert(result == false, "port layer check failed"); + } +} + +static const testcase_t rt_test_002_001 = { + "System integrity functionality", + NULL, + NULL, + rt_test_002_001_execute +}; + +/** + * @page rt_test_002_002 [2.2] Critical zones functionality + * + *

Description

+ * The critical zones API is invoked for coverage. + * + *

Test Steps

+ * - [2.2.1] Testing chSysGetStatusAndLockX() and + * chSysRestoreStatusX(), non reentrant case. + * - [2.2.2] Testing chSysGetStatusAndLockX() and + * chSysRestoreStatusX(), reentrant case. + * - [2.2.3] Testing chSysUnconditionalLock(). + * - [2.2.4] Testing chSysUnconditionalUnlock(). + * - [2.2.5] Testing from ISR context using a virtual timer. + * . + */ + +static void rt_test_002_002_execute(void) { + syssts_t sts; + virtual_timer_t vt; + + /* [2.2.1] Testing chSysGetStatusAndLockX() and + chSysRestoreStatusX(), non reentrant case.*/ + test_set_step(1); + { + sts = chSysGetStatusAndLockX(); + chSysRestoreStatusX(sts); + } + + /* [2.2.2] Testing chSysGetStatusAndLockX() and + chSysRestoreStatusX(), reentrant case.*/ + test_set_step(2); + { + chSysLock(); + sts = chSysGetStatusAndLockX(); + chSysRestoreStatusX(sts); + chSysUnlock(); + } + + /* [2.2.3] Testing chSysUnconditionalLock().*/ + test_set_step(3); + { + chSysUnconditionalLock(); + chSysUnconditionalLock(); + chSysUnlock(); + } + + /* [2.2.4] Testing chSysUnconditionalUnlock().*/ + test_set_step(4); + { + chSysLock(); + chSysUnconditionalUnlock(); + chSysUnconditionalUnlock(); + } + + /* [2.2.5] Testing from ISR context using a virtual timer.*/ + test_set_step(5); + { + chVTObjectInit(&vt); + chVTSet(&vt, 1, vtcb, NULL); + chThdSleep(10); + + test_assert(chVTIsArmed(&vt) == false, "timer still armed"); + } +} + +static const testcase_t rt_test_002_002 = { + "Critical zones functionality", + NULL, + NULL, + rt_test_002_002_execute +}; + +/** + * @page rt_test_002_003 [2.3] Interrupts handling functionality + * + *

Description

+ * The interrupts handling API is invoked for coverage. + * + *

Test Steps

+ * - [2.3.1] Testing chSysSuspend(), chSysDisable() and chSysEnable(). + * . + */ + +static void rt_test_002_003_execute(void) { + + /* [2.3.1] Testing chSysSuspend(), chSysDisable() and + chSysEnable().*/ + test_set_step(1); + { + chSysSuspend(); + chSysDisable(); + chSysSuspend(); + chSysEnable(); + } +} + +static const testcase_t rt_test_002_003 = { + "Interrupts handling functionality", + NULL, + NULL, + rt_test_002_003_execute +}; + +/** + * @page rt_test_002_004 [2.4] System Tick Counter functionality + * + *

Description

+ * The functionality of the API @p chVTGetSystemTimeX() is tested. + * + *

Test Steps

+ * - [2.4.1] A System Tick Counter increment is expected, the test + * simply hangs if it does not happen. + * . + */ + +static void rt_test_002_004_execute(void) { + + /* [2.4.1] A System Tick Counter increment is expected, the test + simply hangs if it does not happen.*/ + test_set_step(1); + { + systime_t time = chVTGetSystemTimeX(); + while (time == chVTGetSystemTimeX()) { +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } + } +} + +static const testcase_t rt_test_002_004 = { + "System Tick Counter functionality", + NULL, + NULL, + rt_test_002_004_execute +}; + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief System layer and port interface. + */ +const testcase_t * const rt_test_sequence_002[] = { + &rt_test_002_001, + &rt_test_002_002, + &rt_test_002_003, + &rt_test_002_004, + NULL +}; diff --git a/test/rt/source/test/rt_test_sequence_002.h b/test/rt/source/test/rt_test_sequence_002.h new file mode 100644 index 000000000..8575165c3 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_002.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_002.h + * @brief Test Sequence 002 header. + */ + +#ifndef RT_TEST_SEQUENCE_002_H +#define RT_TEST_SEQUENCE_002_H + +extern const testcase_t * const rt_test_sequence_002[]; + +#endif /* RT_TEST_SEQUENCE_002_H */ diff --git a/test/rt/source/test/rt_test_sequence_003.c b/test/rt/source/test/rt_test_sequence_003.c new file mode 100644 index 000000000..b481e68c6 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_003.c @@ -0,0 +1,344 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_003.c + * @brief Test Sequence 003 code. + * + * @page rt_test_sequence_003 [3] Threads Functionality + * + * File: @ref rt_test_sequence_003.c + * + *

Description

+ * This sequence tests the ChibiOS/RT functionalities related to + * threading. + * + *

Test Cases

+ * - @subpage rt_test_003_001 + * - @subpage rt_test_003_002 + * - @subpage rt_test_003_003 + * - @subpage rt_test_003_004 + * . + */ + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +static THD_FUNCTION(thread, p) { + + test_emit_token(*(char *)p); +} + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page rt_test_003_001 [3.1] Thread Sleep functionality + * + *

Description

+ * The functionality of @p chThdSleep() and derivatives is tested. + * + *

Test Steps

+ * - [3.1.1] The current system time is read then a sleep is performed + * for 100 system ticks and on exit the system time is verified + * again. + * - [3.1.2] The current system time is read then a sleep is performed + * for 100000 microseconds and on exit the system time is verified + * again. + * - [3.1.3] The current system time is read then a sleep is performed + * for 100 milliseconds and on exit the system time is verified + * again. + * - [3.1.4] The current system time is read then a sleep is performed + * for 1 second and on exit the system time is verified again. + * - [3.1.5] Function chThdSleepUntil() is tested with a timeline of + * "now" + 100 ticks. + * . + */ + +static void rt_test_003_001_execute(void) { + systime_t time; + + /* [3.1.1] The current system time is read then a sleep is performed + for 100 system ticks and on exit the system time is verified + again.*/ + test_set_step(1); + { + time = chVTGetSystemTimeX(); + chThdSleep(100); + test_assert_time_window(time + 100, + time + 100 + CH_CFG_ST_TIMEDELTA + 1, + "out of time window"); + } + + /* [3.1.2] The current system time is read then a sleep is performed + for 100000 microseconds and on exit the system time is verified + again.*/ + test_set_step(2); + { + time = chVTGetSystemTimeX(); + chThdSleepMicroseconds(100000); + test_assert_time_window(time + TIME_US2I(100000), + time + TIME_US2I(100000) + CH_CFG_ST_TIMEDELTA + 1, + "out of time window"); + } + + /* [3.1.3] The current system time is read then a sleep is performed + for 100 milliseconds and on exit the system time is verified + again.*/ + test_set_step(3); + { + time = chVTGetSystemTimeX(); + chThdSleepMilliseconds(100); + test_assert_time_window(time + TIME_MS2I(100), + time + TIME_MS2I(100) + CH_CFG_ST_TIMEDELTA + 1, + "out of time window"); + } + + /* [3.1.4] The current system time is read then a sleep is performed + for 1 second and on exit the system time is verified again.*/ + test_set_step(4); + { + time = chVTGetSystemTimeX(); + chThdSleepSeconds(1); + test_assert_time_window(time + TIME_S2I(1), + time + TIME_S2I(1) + CH_CFG_ST_TIMEDELTA + 1, + "out of time window"); + } + + /* [3.1.5] Function chThdSleepUntil() is tested with a timeline of + "now" + 100 ticks.*/ + test_set_step(5); + { + time = chVTGetSystemTimeX(); + chThdSleepUntil(time + 100); + test_assert_time_window(time + 100, + time + 100 + CH_CFG_ST_TIMEDELTA + 1, + "out of time window"); + } +} + +static const testcase_t rt_test_003_001 = { + "Thread Sleep functionality", + NULL, + NULL, + rt_test_003_001_execute +}; + +/** + * @page rt_test_003_002 [3.2] Ready List functionality, threads priority order + * + *

Description

+ * Five threads, are enqueued in the ready list and atomically + * executed. The test expects the threads to perform their operations + * in correct priority order regardless of the initial order. + * + *

Test Steps

+ * - [3.2.1] Creating 5 threads with increasing priority, execution + * sequence is tested. + * - [3.2.2] Creating 5 threads with decreasing priority, execution + * sequence is tested. + * - [3.2.3] Creating 5 threads with pseudo-random priority, execution + * sequence is tested. + * . + */ + +static void rt_test_003_002_execute(void) { + + /* [3.2.1] Creating 5 threads with increasing priority, execution + sequence is tested.*/ + test_set_step(1); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E"); + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D"); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C"); + threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B"); + threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A"); + test_wait_threads(); + test_assert_sequence("ABCDE", "invalid sequence"); + } + + /* [3.2.2] Creating 5 threads with decreasing priority, execution + sequence is tested.*/ + test_set_step(2); + { + threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A"); + threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B"); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C"); + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D"); + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E"); + test_wait_threads(); + test_assert_sequence("ABCDE", "invalid sequence"); + } + + /* [3.2.3] Creating 5 threads with pseudo-random priority, execution + sequence is tested.*/ + test_set_step(3); + { + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D"); + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E"); + threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A"); + threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B"); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C"); + test_wait_threads(); + test_assert_sequence("ABCDE", "invalid sequence"); + } +} + +static const testcase_t rt_test_003_002 = { + "Ready List functionality, threads priority order", + NULL, + NULL, + rt_test_003_002_execute +}; + +/** + * @page rt_test_003_003 [3.3] Priority change test + * + *

Description

+ * A series of priority changes are performed on the current thread in + * order to verify that the priority change happens as expected. + * + *

Test Steps

+ * - [3.3.1] Thread priority is increased by one then a check is + * performed. + * - [3.3.2] Thread priority is returned to the previous value then a + * check is performed. + * . + */ + +static void rt_test_003_003_execute(void) { + tprio_t prio, p1; + + /* [3.3.1] Thread priority is increased by one then a check is + performed.*/ + test_set_step(1); + { + prio = chThdGetPriorityX(); + p1 = chThdSetPriority(prio + 1); + test_assert(p1 == prio, "unexpected returned priority level"); + test_assert(chThdGetPriorityX() == prio + 1, "unexpected priority level"); + } + + /* [3.3.2] Thread priority is returned to the previous value then a + check is performed.*/ + test_set_step(2); + { + p1 = chThdSetPriority(p1); + test_assert(p1 == prio + 1, "unexpected returned priority level"); + test_assert(chThdGetPriorityX() == prio, "unexpected priority level"); + } +} + +static const testcase_t rt_test_003_003 = { + "Priority change test", + NULL, + NULL, + rt_test_003_003_execute +}; + +#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) +/** + * @page rt_test_003_004 [3.4] Priority change test with Priority Inheritance + * + *

Description

+ * A series of priority changes are performed on the current thread in + * order to verify that the priority change happens as expected. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MUTEXES + * . + * + *

Test Steps

+ * - [3.4.1] Simulating a priority boost situation (prio > realprio). + * - [3.4.2] Raising thread priority above original priority but below + * the boosted level. + * - [3.4.3] Raising thread priority above the boosted level. + * - [3.4.4] Restoring original conditions. + * . + */ + +static void rt_test_003_004_execute(void) { + tprio_t prio, p1; + + /* [3.4.1] Simulating a priority boost situation (prio > realprio).*/ + test_set_step(1); + { + prio = chThdGetPriorityX(); + chThdGetSelfX()->prio += 2; + test_assert(chThdGetPriorityX() == prio + 2, "unexpected priority level"); + } + + /* [3.4.2] Raising thread priority above original priority but below + the boosted level.*/ + test_set_step(2); + { + p1 = chThdSetPriority(prio + 1); + test_assert(p1 == prio, "unexpected returned priority level"); + test_assert(chThdGetSelfX()->prio == prio + 2, "unexpected priority level"); + test_assert(chThdGetSelfX()->realprio == prio + 1, "unexpected returned real priority level"); + } + + /* [3.4.3] Raising thread priority above the boosted level.*/ + test_set_step(3); + { + p1 = chThdSetPriority(prio + 3); + test_assert(p1 == prio + 1, "unexpected returned priority level"); + test_assert(chThdGetSelfX()->prio == prio + 3, "unexpected priority level"); + test_assert(chThdGetSelfX()->realprio == prio + 3, "unexpected real priority level"); + } + + /* [3.4.4] Restoring original conditions.*/ + test_set_step(4); + { + chSysLock(); + chThdGetSelfX()->prio = prio; + chThdGetSelfX()->realprio = prio; + chSysUnlock(); + } +} + +static const testcase_t rt_test_003_004 = { + "Priority change test with Priority Inheritance", + NULL, + NULL, + rt_test_003_004_execute +}; +#endif /* CH_CFG_USE_MUTEXES */ + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Threads Functionality. + */ +const testcase_t * const rt_test_sequence_003[] = { + &rt_test_003_001, + &rt_test_003_002, + &rt_test_003_003, +#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) + &rt_test_003_004, +#endif + NULL +}; diff --git a/test/rt/source/test/rt_test_sequence_003.h b/test/rt/source/test/rt_test_sequence_003.h new file mode 100644 index 000000000..ac7917de2 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_003.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_003.h + * @brief Test Sequence 003 header. + */ + +#ifndef RT_TEST_SEQUENCE_003_H +#define RT_TEST_SEQUENCE_003_H + +extern const testcase_t * const rt_test_sequence_003[]; + +#endif /* RT_TEST_SEQUENCE_003_H */ diff --git a/test/rt/source/test/rt_test_sequence_004.c b/test/rt/source/test/rt_test_sequence_004.c new file mode 100644 index 000000000..0b1e8646a --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_004.c @@ -0,0 +1,130 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_004.c + * @brief Test Sequence 004 code. + * + * @page rt_test_sequence_004 [4] Suspend/Resume + * + * File: @ref rt_test_sequence_004.c + * + *

Description

+ * This sequence tests the ChibiOS/RT functionalities related to + * threads suspend/resume. + * + *

Test Cases

+ * - @subpage rt_test_004_001 + * . + */ + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +static thread_reference_t tr1; + +static THD_FUNCTION(thread1, p) { + + chSysLock(); + chThdResumeI(&tr1, MSG_OK); + chSchRescheduleS(); + chSysUnlock(); + test_emit_token(*(char *)p); +} + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page rt_test_004_001 [4.1] Suspend and Resume functionality + * + *

Description

+ * The functionality of chThdSuspendTimeoutS() and chThdResumeI() is + * tested. + * + *

Test Steps

+ * - [4.1.1] The function chThdSuspendTimeoutS() is invoked, the thread + * is remotely resumed with message @p MSG_OK. On return the message + * and the state of the reference are tested. + * - [4.1.2] The function chThdSuspendTimeoutS() is invoked, the thread + * is not resumed so a timeout must occur. On return the message and + * the state of the reference are tested. + * . + */ + +static void rt_test_004_001_setup(void) { + tr1 = NULL; +} + +static void rt_test_004_001_execute(void) { + systime_t time; + msg_t msg; + + /* [4.1.1] The function chThdSuspendTimeoutS() is invoked, the thread + is remotely resumed with message @p MSG_OK. On return the message + and the state of the reference are tested.*/ + test_set_step(1); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-1, thread1, "A"); + chSysLock(); + msg = chThdSuspendTimeoutS(&tr1, TIME_INFINITE); + chSysUnlock(); + test_assert(NULL == tr1, "not NULL"); + test_assert(MSG_OK == msg,"wrong returned message"); + test_wait_threads(); + } + + /* [4.1.2] The function chThdSuspendTimeoutS() is invoked, the thread + is not resumed so a timeout must occur. On return the message and + the state of the reference are tested.*/ + test_set_step(2); + { + chSysLock(); + time = chVTGetSystemTimeX(); + msg = chThdSuspendTimeoutS(&tr1, TIME_MS2I(1000)); + chSysUnlock(); + test_assert_time_window(time + TIME_MS2I(1000), + time + TIME_MS2I(1000) + CH_CFG_ST_TIMEDELTA + 1, + "out of time window"); + test_assert(NULL == tr1, "not NULL"); + test_assert(MSG_TIMEOUT == msg, "wrong returned message"); + } +} + +static const testcase_t rt_test_004_001 = { + "Suspend and Resume functionality", + rt_test_004_001_setup, + NULL, + rt_test_004_001_execute +}; + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Suspend/Resume. + */ +const testcase_t * const rt_test_sequence_004[] = { + &rt_test_004_001, + NULL +}; diff --git a/test/rt/source/test/rt_test_sequence_004.h b/test/rt/source/test/rt_test_sequence_004.h new file mode 100644 index 000000000..30cb4aa6b --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_004.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_004.h + * @brief Test Sequence 004 header. + */ + +#ifndef RT_TEST_SEQUENCE_004_H +#define RT_TEST_SEQUENCE_004_H + +extern const testcase_t * const rt_test_sequence_004[]; + +#endif /* RT_TEST_SEQUENCE_004_H */ diff --git a/test/rt/source/test/rt_test_sequence_005.c b/test/rt/source/test/rt_test_sequence_005.c new file mode 100644 index 000000000..5005e1fc2 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_005.c @@ -0,0 +1,508 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_005.c + * @brief Test Sequence 005 code. + * + * @page rt_test_sequence_005 [5] Counter and Binary Semaphores + * + * File: @ref rt_test_sequence_005.c + * + *

Description

+ * This sequence tests the ChibiOS/RT functionalities related to + * counter semaphores. + * + *

Conditions

+ * This sequence is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_SEMAPHORES + * . + * + *

Test Cases

+ * - @subpage rt_test_005_001 + * - @subpage rt_test_005_002 + * - @subpage rt_test_005_003 + * - @subpage rt_test_005_004 + * - @subpage rt_test_005_005 + * - @subpage rt_test_005_006 + * . + */ + +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +#include "ch.h" + +static semaphore_t sem1; + +static THD_FUNCTION(thread1, p) { + + chSemWait(&sem1); + test_emit_token(*(char *)p); +} + +static THD_FUNCTION(thread2, p) { + + (void)p; + chThdSleepMilliseconds(50); + chSysLock(); + chSemSignalI(&sem1); /* For coverage reasons */ + chSchRescheduleS(); + chSysUnlock(); +} + +static THD_FUNCTION(thread3, p) { + + (void)p; + chSemWait(&sem1); + chSemSignal(&sem1); +} + +static THD_FUNCTION(thread4, p) { + + chBSemSignal((binary_semaphore_t *)p); +} + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page rt_test_005_001 [5.1] Semaphore primitives, no state change + * + *

Description

+ * Wait, Signal and Reset primitives are tested. The testing thread + * does not trigger a state change. + * + *

Test Steps

+ * - [5.1.1] The function chSemWait() is invoked, after return the + * counter and the returned message are tested. + * - [5.1.2] The function chSemSignal() is invoked, after return the + * counter is tested. + * - [5.1.3] The function chSemReset() is invoked, after return the + * counter is tested. + * . + */ + +static void rt_test_005_001_setup(void) { + chSemObjectInit(&sem1, 1); +} + +static void rt_test_005_001_teardown(void) { + chSemReset(&sem1, 0); +} + +static void rt_test_005_001_execute(void) { + + /* [5.1.1] The function chSemWait() is invoked, after return the + counter and the returned message are tested.*/ + test_set_step(1); + { + msg_t msg; + + msg = chSemWait(&sem1); + test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value"); + test_assert(MSG_OK == msg, "wrong returned message"); + } + + /* [5.1.2] The function chSemSignal() is invoked, after return the + counter is tested.*/ + test_set_step(2); + { + chSemSignal(&sem1); + test_assert_lock(chSemGetCounterI(&sem1) == 1, "wrong counter value"); + } + + /* [5.1.3] The function chSemReset() is invoked, after return the + counter is tested.*/ + test_set_step(3); + { + chSemReset(&sem1, 2); + test_assert_lock(chSemGetCounterI(&sem1) == 2, "wrong counter value"); + } +} + +static const testcase_t rt_test_005_001 = { + "Semaphore primitives, no state change", + rt_test_005_001_setup, + rt_test_005_001_teardown, + rt_test_005_001_execute +}; + +/** + * @page rt_test_005_002 [5.2] Semaphore enqueuing test + * + *

Description

+ * Five threads with randomized priorities are enqueued to a semaphore + * then awakened one at time. The test expects that the threads reach + * their goal in FIFO order or priority order depending on the @p + * CH_CFG_USE_SEMAPHORES_PRIORITY configuration setting. + * + *

Test Steps

+ * - [5.2.1] Five threads are created with mixed priority levels (not + * increasing nor decreasing). Threads enqueue on a semaphore + * initialized to zero. + * - [5.2.2] The semaphore is signaled 5 times. The thread activation + * sequence is tested. + * . + */ + +static void rt_test_005_002_setup(void) { + chSemObjectInit(&sem1, 0); +} + +static void rt_test_005_002_execute(void) { + + /* [5.2.1] Five threads are created with mixed priority levels (not + increasing nor decreasing). Threads enqueue on a semaphore + initialized to zero.*/ + test_set_step(1); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+5, thread1, "A"); + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()+1, thread1, "B"); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()+3, thread1, "C"); + threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()+4, thread1, "D"); + threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()+2, thread1, "E"); + } + + /* [5.2.2] The semaphore is signaled 5 times. The thread activation + sequence is tested.*/ + test_set_step(2); + { + chSemSignal(&sem1); + chSemSignal(&sem1); + chSemSignal(&sem1); + chSemSignal(&sem1); + chSemSignal(&sem1); + test_wait_threads(); +#if CH_CFG_USE_SEMAPHORES_PRIORITY + test_assert_sequence("ADCEB", "invalid sequence"); +#else + test_assert_sequence("ABCDE", "invalid sequence"); +#endif + } +} + +static const testcase_t rt_test_005_002 = { + "Semaphore enqueuing test", + rt_test_005_002_setup, + NULL, + rt_test_005_002_execute +}; + +/** + * @page rt_test_005_003 [5.3] Semaphore timeout test + * + *

Description

+ * The three possible semaphore waiting modes (do not wait, wait with + * timeout, wait without timeout) are explored. The test expects that + * the semaphore wait function returns the correct value in each of the + * above scenario and that the semaphore structure status is correct + * after each operation. + * + *

Test Steps

+ * - [5.3.1] Testing special case TIME_IMMEDIATE. + * - [5.3.2] Testing non-timeout condition. + * - [5.3.3] Testing timeout condition. + * . + */ + +static void rt_test_005_003_setup(void) { + chSemObjectInit(&sem1, 0); +} + +static void rt_test_005_003_execute(void) { + unsigned i; + systime_t target_time; + msg_t msg; + + /* [5.3.1] Testing special case TIME_IMMEDIATE.*/ + test_set_step(1); + { + msg = chSemWaitTimeout(&sem1, TIME_IMMEDIATE); + test_assert(msg == MSG_TIMEOUT, "wrong wake-up message"); + test_assert(queue_isempty(&sem1.queue), "queue not empty"); + test_assert(sem1.cnt == 0, "counter not zero"); + } + + /* [5.3.2] Testing non-timeout condition.*/ + test_set_step(2); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, + thread2, 0); + msg = chSemWaitTimeout(&sem1, TIME_MS2I(500)); + test_wait_threads(); + test_assert(msg == MSG_OK, "wrong wake-up message"); + test_assert(queue_isempty(&sem1.queue), "queue not empty"); + test_assert(sem1.cnt == 0, "counter not zero"); + } + + /* [5.3.3] Testing timeout condition.*/ + test_set_step(3); + { + target_time = test_wait_tick() + TIME_MS2I(5 * 50); + for (i = 0; i < 5; i++) { + test_emit_token('A' + i); + msg = chSemWaitTimeout(&sem1, TIME_MS2I(50)); + test_assert(msg == MSG_TIMEOUT, "wrong wake-up message"); + test_assert(queue_isempty(&sem1.queue), "queue not empty"); + test_assert(sem1.cnt == 0, "counter not zero"); + } + test_assert_sequence("ABCDE", "invalid sequence"); + test_assert_time_window(target_time, target_time + ALLOWED_DELAY, + "out of time window"); + } +} + +static const testcase_t rt_test_005_003 = { + "Semaphore timeout test", + rt_test_005_003_setup, + NULL, + rt_test_005_003_execute +}; + +/** + * @page rt_test_005_004 [5.4] Testing chSemAddCounterI() functionality + * + *

Description

+ * The functon is tested by waking up a thread then the semaphore + * counter value is tested. + * + *

Test Steps

+ * - [5.4.1] A thread is created, it goes to wait on the semaphore. + * - [5.4.2] The semaphore counter is increased by two, it is then + * tested to be one, the thread must have completed. + * . + */ + +static void rt_test_005_004_setup(void) { + chSemObjectInit(&sem1, 0); +} + +static void rt_test_005_004_execute(void) { + + /* [5.4.1] A thread is created, it goes to wait on the semaphore.*/ + test_set_step(1); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, thread1, "A"); + } + + /* [5.4.2] The semaphore counter is increased by two, it is then + tested to be one, the thread must have completed.*/ + test_set_step(2); + { + chSysLock(); + chSemAddCounterI(&sem1, 2); + chSchRescheduleS(); + chSysUnlock(); + test_wait_threads(); + test_assert_lock(chSemGetCounterI(&sem1) == 1, "invalid counter"); + test_assert_sequence("A", "invalid sequence"); + } +} + +static const testcase_t rt_test_005_004 = { + "Testing chSemAddCounterI() functionality", + rt_test_005_004_setup, + NULL, + rt_test_005_004_execute +}; + +/** + * @page rt_test_005_005 [5.5] Testing chSemWaitSignal() functionality + * + *

Description

+ * This test case explicitly addresses the @p chSemWaitSignal() + * function. A thread is created that performs a wait and a signal + * operations. The tester thread is awakened from an atomic wait/signal + * operation. The test expects that the semaphore wait function returns + * the correct value in each of the above scenario and that the + * semaphore structure status is correct after each operation. + * + *

Test Steps

+ * - [5.5.1] An higher priority thread is created that performs + * non-atomical wait and signal operations on a semaphore. + * - [5.5.2] The function chSemSignalWait() is invoked by specifying + * the same semaphore for the wait and signal phases. The counter + * value must be one on exit. + * - [5.5.3] The function chSemSignalWait() is invoked again by + * specifying the same semaphore for the wait and signal phases. The + * counter value must be one on exit. + * . + */ + +static void rt_test_005_005_setup(void) { + chSemObjectInit(&sem1, 0); +} + +static void rt_test_005_005_teardown(void) { + test_wait_threads(); +} + +static void rt_test_005_005_execute(void) { + + /* [5.5.1] An higher priority thread is created that performs + non-atomical wait and signal operations on a semaphore.*/ + test_set_step(1); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, thread3, 0); + } + + /* [5.5.2] The function chSemSignalWait() is invoked by specifying + the same semaphore for the wait and signal phases. The counter + value must be one on exit.*/ + test_set_step(2); + { + chSemSignalWait(&sem1, &sem1); + test_assert(queue_isempty(&sem1.queue), "queue not empty"); + test_assert(sem1.cnt == 0, "counter not zero"); + } + + /* [5.5.3] The function chSemSignalWait() is invoked again by + specifying the same semaphore for the wait and signal phases. The + counter value must be one on exit.*/ + test_set_step(3); + { + chSemSignalWait(&sem1, &sem1); + test_assert(queue_isempty(&sem1.queue), "queue not empty"); + test_assert(sem1.cnt == 0, "counter not zero"); + } +} + +static const testcase_t rt_test_005_005 = { + "Testing chSemWaitSignal() functionality", + rt_test_005_005_setup, + rt_test_005_005_teardown, + rt_test_005_005_execute +}; + +/** + * @page rt_test_005_006 [5.6] Testing Binary Semaphores special case + * + *

Description

+ * This test case tests the binary semaphores functionality. The test + * both checks the binary semaphore status and the expected status of + * the underlying counting semaphore. + * + *

Test Steps

+ * - [5.6.1] Creating a binary semaphore in "taken" state, the state is + * checked. + * - [5.6.2] Resetting the binary semaphore in "taken" state, the state + * must not change. + * - [5.6.3] Starting a signaler thread at a lower priority. + * - [5.6.4] Waiting for the binary semaphore to be signaled, the + * semaphore is expected to be taken. + * - [5.6.5] Signaling the binary semaphore, checking the binary + * semaphore state to be "not taken" and the underlying counter + * semaphore counter to be one. + * - [5.6.6] Signaling the binary semaphore again, the internal state + * must not change from "not taken". + * . + */ + +static void rt_test_005_006_teardown(void) { + test_wait_threads(); +} + +static void rt_test_005_006_execute(void) { + binary_semaphore_t bsem; + msg_t msg; + + /* [5.6.1] Creating a binary semaphore in "taken" state, the state is + checked.*/ + test_set_step(1); + { + chBSemObjectInit(&bsem, true); + test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken"); + } + + /* [5.6.2] Resetting the binary semaphore in "taken" state, the state + must not change.*/ + test_set_step(2); + { + chBSemReset(&bsem, true); + test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken"); + } + + /* [5.6.3] Starting a signaler thread at a lower priority.*/ + test_set_step(3); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, + chThdGetPriorityX()-1, thread4, &bsem); + } + + /* [5.6.4] Waiting for the binary semaphore to be signaled, the + semaphore is expected to be taken.*/ + test_set_step(4); + { + msg = chBSemWait(&bsem); + test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken"); + test_assert(msg == MSG_OK, "unexpected message"); + } + + /* [5.6.5] Signaling the binary semaphore, checking the binary + semaphore state to be "not taken" and the underlying counter + semaphore counter to be one.*/ + test_set_step(5); + { + chBSemSignal(&bsem); + test_assert_lock(chBSemGetStateI(&bsem) ==false, "still taken"); + test_assert_lock(chSemGetCounterI(&bsem.sem) == 1, "unexpected counter"); + } + + /* [5.6.6] Signaling the binary semaphore again, the internal state + must not change from "not taken".*/ + test_set_step(6); + { + chBSemSignal(&bsem); + test_assert_lock(chBSemGetStateI(&bsem) == false, "taken"); + test_assert_lock(chSemGetCounterI(&bsem.sem) == 1, "unexpected counter"); + } +} + +static const testcase_t rt_test_005_006 = { + "Testing Binary Semaphores special case", + NULL, + rt_test_005_006_teardown, + rt_test_005_006_execute +}; + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Counter and Binary Semaphores. + */ +const testcase_t * const rt_test_sequence_005[] = { + &rt_test_005_001, + &rt_test_005_002, + &rt_test_005_003, + &rt_test_005_004, + &rt_test_005_005, + &rt_test_005_006, + NULL +}; + +#endif /* CH_CFG_USE_SEMAPHORES */ diff --git a/test/rt/source/test/rt_test_sequence_005.h b/test/rt/source/test/rt_test_sequence_005.h new file mode 100644 index 000000000..3ef60743b --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_005.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_005.h + * @brief Test Sequence 005 header. + */ + +#ifndef RT_TEST_SEQUENCE_005_H +#define RT_TEST_SEQUENCE_005_H + +extern const testcase_t * const rt_test_sequence_005[]; + +#endif /* RT_TEST_SEQUENCE_005_H */ diff --git a/test/rt/source/test/rt_test_sequence_006.c b/test/rt/source/test/rt_test_sequence_006.c new file mode 100644 index 000000000..7c6847b51 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_006.c @@ -0,0 +1,1069 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_006.c + * @brief Test Sequence 006 code. + * + * @page rt_test_sequence_006 [6] Mutexes, Condition Variables and Priority Inheritance + * + * File: @ref rt_test_sequence_006.c + * + *

Description

+ * This sequence tests the ChibiOS/RT functionalities related to + * mutexes, condition variables and priority inheritance algorithm. + * + *

Conditions

+ * This sequence is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MUTEXES + * . + * + *

Test Cases

+ * - @subpage rt_test_006_001 + * - @subpage rt_test_006_002 + * - @subpage rt_test_006_003 + * - @subpage rt_test_006_004 + * - @subpage rt_test_006_005 + * - @subpage rt_test_006_006 + * - @subpage rt_test_006_007 + * - @subpage rt_test_006_008 + * - @subpage rt_test_006_009 + * . + */ + +#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +static MUTEX_DECL(m1); +static MUTEX_DECL(m2); +#if CH_CFG_USE_CONDVARS || defined(__DOXYGEN__) +static CONDVAR_DECL(c1); +#endif + +#if CH_DBG_THREADS_PROFILING || defined(__DOXYGEN__) +/** + * @brief CPU pulse. + * @note The current implementation is not totally reliable. + * + * @param[in] duration CPU pulse duration in milliseconds + */ +void test_cpu_pulse(unsigned duration) { + systime_t start, end, now; + + start = chThdGetTicksX(chThdGetSelfX()); + end = start + TIME_MS2I(duration); + do { + now = chThdGetTicksX(chThdGetSelfX()); +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } + while (chVTIsTimeWithinX(now, start, end)); +} +#endif /* CH_DBG_THREADS_PROFILING */ + +static THD_FUNCTION(thread1, p) { + + chMtxLock(&m1); + test_emit_token(*(char *)p); + chMtxUnlock(&m1); +} + +#if CH_DBG_THREADS_PROFILING || defined(__DOXYGEN__) +/* Low priority thread */ +static THD_FUNCTION(thread2L, p) { + + (void)p; + chMtxLock(&m1); + test_cpu_pulse(40); + chMtxUnlock(&m1); + test_cpu_pulse(10); + test_emit_token('C'); +} + +/* Medium priority thread */ +static THD_FUNCTION(thread2M, p) { + + (void)p; + chThdSleepMilliseconds(20); + test_cpu_pulse(40); + test_emit_token('B'); +} + +/* High priority thread */ +static THD_FUNCTION(thread2H, p) { + + (void)p; + chThdSleepMilliseconds(40); + chMtxLock(&m1); + test_cpu_pulse(10); + chMtxUnlock(&m1); + test_emit_token('A'); +} + +/* Lowest priority thread */ +static THD_FUNCTION(thread3LL, p) { + + (void)p; + chMtxLock(&m1); + test_cpu_pulse(30); + chMtxUnlock(&m1); + test_emit_token('E'); +} + +/* Low priority thread */ +static THD_FUNCTION(thread3L, p) { + + (void)p; + chThdSleepMilliseconds(10); + chMtxLock(&m2); + test_cpu_pulse(20); + chMtxLock(&m1); + test_cpu_pulse(10); + chMtxUnlock(&m1); + test_cpu_pulse(10); + chMtxUnlock(&m2); + test_emit_token('D'); +} + +/* Medium priority thread */ +static THD_FUNCTION(thread3M, p) { + + (void)p; + chThdSleepMilliseconds(20); + chMtxLock(&m2); + test_cpu_pulse(10); + chMtxUnlock(&m2); + test_emit_token('C'); +} + +/* High priority thread */ +static THD_FUNCTION(thread3H, p) { + + (void)p; + chThdSleepMilliseconds(40); + test_cpu_pulse(20); + test_emit_token('B'); +} + +/* Highest priority thread */ +static THD_FUNCTION(thread3HH, p) { + + (void)p; + chThdSleepMilliseconds(50); + chMtxLock(&m2); + test_cpu_pulse(10); + chMtxUnlock(&m2); + test_emit_token('A'); +} +#endif /* CH_DBG_THREADS_PROFILING */ + +static THD_FUNCTION(thread4A, p) { + + (void)p; + chThdSleepMilliseconds(50); + chMtxLock(&m1); + chMtxUnlock(&m1); +} + +static THD_FUNCTION(thread4B, p) { + + (void)p; + chThdSleepMilliseconds(150); + chSysLock(); + chMtxLockS(&m2); /* For coverage of the chMtxLockS() function variant.*/ + chMtxUnlockS(&m2); /* For coverage of the chMtxUnlockS() function variant.*/ + chSchRescheduleS(); + chSysUnlock(); +} + +#if CH_CFG_USE_CONDVARS || defined(__DOXYGEN__) +static THD_FUNCTION(thread6, p) { + + chMtxLock(&m1); + chCondWait(&c1); + test_emit_token(*(char *)p); + chMtxUnlock(&m1); +} + +static THD_FUNCTION(thread8, p) { + + chMtxLock(&m2); + chMtxLock(&m1); +#if CH_CFG_USE_CONDVARS_TIMEOUT || defined(__DOXYGEN__) + chCondWaitTimeout(&c1, TIME_INFINITE); +#else + chCondWait(&c1); +#endif + test_emit_token(*(char *)p); + chMtxUnlock(&m1); + chMtxUnlock(&m2); +} + +static THD_FUNCTION(thread9, p) { + + chMtxLock(&m2); + test_emit_token(*(char *)p); + chMtxUnlock(&m2); +} +#endif /* CH_CFG_USE_CONDVARS */ + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page rt_test_006_001 [6.1] Priority enqueuing test + * + *

Description

+ * Five threads, with increasing priority, are enqueued on a locked + * mutex then the mutex is unlocked. The test expects the threads to + * perform their operations in increasing priority order regardless of + * the initial order. + * + *

Test Steps

+ * - [6.1.1] Getting the initial priority. + * - [6.1.2] Locking the mutex. + * - [6.1.3] Five threads are created that try to lock and unlock the + * mutex then terminate. The threads are created in ascending + * priority order. + * - [6.1.4] Unlocking the mutex, the threads will wakeup in priority + * order because the mutext queue is an ordered one. + * . + */ + +static void rt_test_006_001_setup(void) { + chMtxObjectInit(&m1); +} + +static void rt_test_006_001_execute(void) { + tprio_t prio; + + /* [6.1.1] Getting the initial priority.*/ + test_set_step(1); + { + prio = chThdGetPriorityX(); + } + + /* [6.1.2] Locking the mutex.*/ + test_set_step(2); + { + chMtxLock(&m1); + } + + /* [6.1.3] Five threads are created that try to lock and unlock the + mutex then terminate. The threads are created in ascending + priority order.*/ + test_set_step(3); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread1, "E"); + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread1, "D"); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread1, "C"); + threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread1, "B"); + threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread1, "A"); + } + + /* [6.1.4] Unlocking the mutex, the threads will wakeup in priority + order because the mutext queue is an ordered one.*/ + test_set_step(4); + { + chMtxUnlock(&m1); + test_wait_threads(); + test_assert(prio == chThdGetPriorityX(), "wrong priority level"); + test_assert_sequence("ABCDE", "invalid sequence"); + } +} + +static const testcase_t rt_test_006_001 = { + "Priority enqueuing test", + rt_test_006_001_setup, + NULL, + rt_test_006_001_execute +}; + +#if (CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) +/** + * @page rt_test_006_002 [6.2] Priority inheritance, simple case + * + *

Description

+ * Three threads are involved in the classic priority inversion + * scenario, a medium priority thread tries to starve an high priority + * thread by blocking a low priority thread into a mutex lock zone. The + * test expects the threads to reach their goal in increasing priority + * order by rearranging their priorities in order to avoid the priority + * inversion trap. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_DBG_THREADS_PROFILING + * . + * + *

Test Steps

+ * - [6.2.1] Getting the system time for test duration measurement. + * - [6.2.2] The three contenders threads are created and let run + * atomically, the goals sequence is tested, the threads must + * complete in priority order. + * - [6.2.3] Testing that all threads completed within the specified + * time windows (100mS...100mS+ALLOWED_DELAY). + * . + */ + +static void rt_test_006_002_setup(void) { + chMtxObjectInit(&m1); +} + +static void rt_test_006_002_execute(void) { + systime_t time; + + /* [6.2.1] Getting the system time for test duration measurement.*/ + test_set_step(1); + { + time = test_wait_tick(); + } + + /* [6.2.2] The three contenders threads are created and let run + atomically, the goals sequence is tested, the threads must + complete in priority order.*/ + test_set_step(2); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-1, thread2H, 0); + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-2, thread2M, 0); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread2L, 0); + test_wait_threads(); + test_assert_sequence("ABC", "invalid sequence"); + } + + /* [6.2.3] Testing that all threads completed within the specified + time windows (100mS...100mS+ALLOWED_DELAY).*/ + test_set_step(3); + { + test_assert_time_window(time + TIME_MS2I(100), time + TIME_MS2I(100) + ALLOWED_DELAY, + "out of time window"); + } +} + +static const testcase_t rt_test_006_002 = { + "Priority inheritance, simple case", + rt_test_006_002_setup, + NULL, + rt_test_006_002_execute +}; +#endif /* CH_DBG_THREADS_PROFILING */ + +#if (CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) +/** + * @page rt_test_006_003 [6.3] Priority inheritance, complex case + * + *

Description

+ * Five threads are involved in the complex priority inversion + * scenario, the priority inheritance algorithm is tested for depths + * greater than one. The test expects the threads to perform their + * operations in increasing priority order by rearranging their + * priorities in order to avoid the priority inversion trap. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_DBG_THREADS_PROFILING + * . + * + *

Test Steps

+ * - [6.3.1] Getting the system time for test duration measurement. + * - [6.3.2] The five contenders threads are created and let run + * atomically, the goals sequence is tested, the threads must + * complete in priority order. + * - [6.3.3] Testing that all threads completed within the specified + * time windows (110mS...110mS+ALLOWED_DELAY). + * . + */ + +static void rt_test_006_003_setup(void) { + chMtxObjectInit(&m1); /* Mutex B.*/ + chMtxObjectInit(&m2); /* Mutex A.*/ +} + +static void rt_test_006_003_execute(void) { + systime_t time; + + /* [6.3.1] Getting the system time for test duration measurement.*/ + test_set_step(1); + { + time = test_wait_tick(); + } + + /* [6.3.2] The five contenders threads are created and let run + atomically, the goals sequence is tested, the threads must + complete in priority order.*/ + test_set_step(2); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread3LL, 0); + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread3L, 0); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread3M, 0); + threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread3H, 0); + threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread3HH, 0); + test_wait_threads(); + test_assert_sequence("ABCDE", "invalid sequence"); + } + + /* [6.3.3] Testing that all threads completed within the specified + time windows (110mS...110mS+ALLOWED_DELAY).*/ + test_set_step(3); + { + test_assert_time_window(time + TIME_MS2I(110), time + TIME_MS2I(110) + ALLOWED_DELAY, + "out of time window"); + } +} + +static const testcase_t rt_test_006_003 = { + "Priority inheritance, complex case", + rt_test_006_003_setup, + NULL, + rt_test_006_003_execute +}; +#endif /* CH_DBG_THREADS_PROFILING */ + +/** + * @page rt_test_006_004 [6.4] Priority return verification + * + *

Description

+ * Two threads are spawned that try to lock the mutexes already locked + * by the tester thread with precise timing. The test expects that the + * priority changes caused by the priority inheritance algorithm happen + * at the right moment and with the right values.
Thread A performs + * wait(50), lock(m1), unlock(m1), exit. Thread B performs wait(150), + * lock(m2), unlock(m2), exit. + * + *

Test Steps

+ * - [6.4.1] Getting current thread priority P(0) and assigning to the + * threads A and B priorities +1 and +2. + * - [6.4.2] Spawning threads A and B at priorities P(A) and P(B). + * - [6.4.3] Locking the mutex M1 before thread A has a chance to lock + * it. The priority must not change because A has not yet reached + * chMtxLock(M1). the mutex is not locked. + * - [6.4.4] Waiting 100mS, this makes thread A reach chMtxLock(M1) and + * get the mutex. This must boost the priority of the current thread + * at the same level of thread A. + * - [6.4.5] Locking the mutex M2 before thread B has a chance to lock + * it. The priority must not change because B has not yet reached + * chMtxLock(M2). the mutex is not locked. + * - [6.4.6] Waiting 100mS, this makes thread B reach chMtxLock(M2) and + * get the mutex. This must boost the priority of the current thread + * at the same level of thread B. + * - [6.4.7] Unlocking M2, the priority should fall back to P(A). + * - [6.4.8] Unlocking M1, the priority should fall back to P(0). + * . + */ + +static void rt_test_006_004_setup(void) { + chMtxObjectInit(&m1); + chMtxObjectInit(&m2); +} + +static void rt_test_006_004_teardown(void) { + test_wait_threads(); +} + +static void rt_test_006_004_execute(void) { + tprio_t p, pa, pb; + + /* [6.4.1] Getting current thread priority P(0) and assigning to the + threads A and B priorities +1 and +2.*/ + test_set_step(1); + { + p = chThdGetPriorityX(); + pa = p + 1; + pb = p + 2; + } + + /* [6.4.2] Spawning threads A and B at priorities P(A) and P(B).*/ + test_set_step(2); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, pa, thread4A, "A"); + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, pb, thread4B, "B"); + } + + /* [6.4.3] Locking the mutex M1 before thread A has a chance to lock + it. The priority must not change because A has not yet reached + chMtxLock(M1). the mutex is not locked.*/ + test_set_step(3); + { + chMtxLock(&m1); + test_assert(chThdGetPriorityX() == p, "wrong priority level"); + } + + /* [6.4.4] Waiting 100mS, this makes thread A reach chMtxLock(M1) and + get the mutex. This must boost the priority of the current thread + at the same level of thread A.*/ + test_set_step(4); + { + chThdSleepMilliseconds(100); + test_assert(chThdGetPriorityX() == pa, "wrong priority level"); + } + + /* [6.4.5] Locking the mutex M2 before thread B has a chance to lock + it. The priority must not change because B has not yet reached + chMtxLock(M2). the mutex is not locked.*/ + test_set_step(5); + { + chMtxLock(&m2); + test_assert(chThdGetPriorityX() == pa, "wrong priority level"); + } + + /* [6.4.6] Waiting 100mS, this makes thread B reach chMtxLock(M2) and + get the mutex. This must boost the priority of the current thread + at the same level of thread B.*/ + test_set_step(6); + { + chThdSleepMilliseconds(100); + test_assert(chThdGetPriorityX() == pb, "wrong priority level"); + } + + /* [6.4.7] Unlocking M2, the priority should fall back to P(A).*/ + test_set_step(7); + { + chMtxUnlock(&m2); + test_assert(chThdGetPriorityX() == pa, "wrong priority level"); + } + + /* [6.4.8] Unlocking M1, the priority should fall back to P(0).*/ + test_set_step(8); + { + chMtxUnlock(&m1); + test_assert(chThdGetPriorityX() == p, "wrong priority level"); + } +} + +static const testcase_t rt_test_006_004 = { + "Priority return verification", + rt_test_006_004_setup, + rt_test_006_004_teardown, + rt_test_006_004_execute +}; + +#if (!CH_CFG_USE_MUTEXES_RECURSIVE) || defined(__DOXYGEN__) +/** + * @page rt_test_006_005 [6.5] Repeated locks, non recursive scenario + * + *

Description

+ * The behavior of multiple mutex locks from the same thread is tested + * when recursion is disabled. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - !CH_CFG_USE_MUTEXES_RECURSIVE + * . + * + *

Test Steps

+ * - [6.5.1] Getting current thread priority for later checks. + * - [6.5.2] Locking the mutex first time, it must be possible because + * it is not owned. + * - [6.5.3] Locking the mutex second time, it must fail because it is + * already owned. + * - [6.5.4] Unlocking the mutex then it must not be owned anymore and + * the queue must be empty. + * - [6.5.5] Testing that priority has not changed after operations. + * - [6.5.6] Testing chMtxUnlockAll() behavior. + * - [6.5.7] Testing that priority has not changed after operations. + * . + */ + +static void rt_test_006_005_setup(void) { + chMtxObjectInit(&m1); +} + +static void rt_test_006_005_execute(void) { + bool b; + tprio_t prio; + + /* [6.5.1] Getting current thread priority for later checks.*/ + test_set_step(1); + { + prio = chThdGetPriorityX(); + } + + /* [6.5.2] Locking the mutex first time, it must be possible because + it is not owned.*/ + test_set_step(2); + { + b = chMtxTryLock(&m1); + test_assert(b, "already locked"); + } + + /* [6.5.3] Locking the mutex second time, it must fail because it is + already owned.*/ + test_set_step(3); + { + b = chMtxTryLock(&m1); + test_assert(!b, "not locked"); + } + + /* [6.5.4] Unlocking the mutex then it must not be owned anymore and + the queue must be empty.*/ + test_set_step(4); + { + chMtxUnlock(&m1); + test_assert(m1.owner == NULL, "still owned"); + test_assert(queue_isempty(&m1.queue), "queue not empty"); + } + + /* [6.5.5] Testing that priority has not changed after operations.*/ + test_set_step(5); + { + test_assert(chThdGetPriorityX() == prio, "wrong priority level"); + } + + /* [6.5.6] Testing chMtxUnlockAll() behavior.*/ + test_set_step(6); + { + b = chMtxTryLock(&m1); + test_assert(b, "already locked"); + b = chMtxTryLock(&m1); + test_assert(!b, "not locked"); + + chMtxUnlockAll(); + test_assert(m1.owner == NULL, "still owned"); + test_assert(queue_isempty(&m1.queue), "queue not empty"); + } + + /* [6.5.7] Testing that priority has not changed after operations.*/ + test_set_step(7); + { + test_assert(chThdGetPriorityX() == prio, "wrong priority level"); + } +} + +static const testcase_t rt_test_006_005 = { + "Repeated locks, non recursive scenario", + rt_test_006_005_setup, + NULL, + rt_test_006_005_execute +}; +#endif /* !CH_CFG_USE_MUTEXES_RECURSIVE */ + +#if (CH_CFG_USE_MUTEXES_RECURSIVE) || defined(__DOXYGEN__) +/** + * @page rt_test_006_006 [6.6] Repeated locks using, recursive scenario + * + *

Description

+ * The behavior of multiple mutex locks from the same thread is tested + * when recursion is enabled. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MUTEXES_RECURSIVE + * . + * + *

Test Steps

+ * - [6.6.1] Getting current thread priority for later checks. + * - [6.6.2] Locking the mutex first time, it must be possible because + * it is not owned. + * - [6.6.3] Locking the mutex second time, it must be possible because + * it is recursive. + * - [6.6.4] Unlocking the mutex then it must be still owned because + * recursivity. + * - [6.6.5] Unlocking the mutex then it must not be owned anymore and + * the queue must be empty. + * - [6.6.6] Testing that priority has not changed after operations. + * - [6.6.7] Testing consecutive chMtxTryLock()/chMtxTryLockS() calls + * and a final chMtxUnlockAllS(). + * - [6.6.8] Testing consecutive chMtxLock()/chMtxLockS() calls and a + * final chMtxUnlockAll(). + * - [6.6.9] Testing that priority has not changed after operations. + * . + */ + +static void rt_test_006_006_setup(void) { + chMtxObjectInit(&m1); +} + +static void rt_test_006_006_execute(void) { + bool b; + tprio_t prio; + + /* [6.6.1] Getting current thread priority for later checks.*/ + test_set_step(1); + { + prio = chThdGetPriorityX(); + } + + /* [6.6.2] Locking the mutex first time, it must be possible because + it is not owned.*/ + test_set_step(2); + { + b = chMtxTryLock(&m1); + test_assert(b, "already locked"); + } + + /* [6.6.3] Locking the mutex second time, it must be possible because + it is recursive.*/ + test_set_step(3); + { + b = chMtxTryLock(&m1); + test_assert(b, "already locked"); + } + + /* [6.6.4] Unlocking the mutex then it must be still owned because + recursivity.*/ + test_set_step(4); + { + chMtxUnlock(&m1); + test_assert(m1.owner != NULL, "not owned"); + } + + /* [6.6.5] Unlocking the mutex then it must not be owned anymore and + the queue must be empty.*/ + test_set_step(5); + { + chMtxUnlock(&m1); + test_assert(m1.owner == NULL, "still owned"); + test_assert(queue_isempty(&m1.queue), "queue not empty"); + } + + /* [6.6.6] Testing that priority has not changed after operations.*/ + test_set_step(6); + { + test_assert(chThdGetPriorityX() == prio, "wrong priority level"); + } + + /* [6.6.7] Testing consecutive chMtxTryLock()/chMtxTryLockS() calls + and a final chMtxUnlockAllS().*/ + test_set_step(7); + { + b = chMtxTryLock(&m1); + test_assert(b, "already locked"); + chSysLock(); + b = chMtxTryLockS(&m1); + chSysUnlock(); + test_assert(b, "already locked"); + test_assert(m1.cnt == 2, "invalid recursion counter"); + chSysLock(); + chMtxUnlockAllS(); + chSysUnlock(); + test_assert(m1.owner == NULL, "still owned"); + test_assert(queue_isempty(&m1.queue), "queue not empty"); + test_assert(m1.cnt == 0, "invalid recursion counter"); + } + + /* [6.6.8] Testing consecutive chMtxLock()/chMtxLockS() calls and a + final chMtxUnlockAll().*/ + test_set_step(8); + { + chMtxLock(&m1); + test_assert(m1.owner != NULL, "not owned"); + chSysLock(); + chMtxLockS(&m1); + chSysUnlock(); + test_assert(m1.owner != NULL, "not owned"); + test_assert(m1.cnt == 2, "invalid recursion counter"); + chMtxUnlockAll(); + test_assert(m1.owner == NULL, "still owned"); + test_assert(queue_isempty(&m1.queue), "queue not empty"); + test_assert(m1.cnt == 0, "invalid recursion counter"); + } + + /* [6.6.9] Testing that priority has not changed after operations.*/ + test_set_step(9); + { + test_assert(chThdGetPriorityX() == prio, "wrong priority level"); + } +} + +static const testcase_t rt_test_006_006 = { + "Repeated locks using, recursive scenario", + rt_test_006_006_setup, + NULL, + rt_test_006_006_execute +}; +#endif /* CH_CFG_USE_MUTEXES_RECURSIVE */ + +#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) +/** + * @page rt_test_006_007 [6.7] Condition Variable signal test + * + *

Description

+ * Five threads take a mutex and then enter a conditional variable + * queue, the tester thread then proceeds to signal the conditional + * variable five times atomically.
The test expects the threads to + * reach their goal in increasing priority order regardless of the + * initial order. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_CONDVARS + * . + * + *

Test Steps

+ * - [6.7.1] Starting the five threads with increasing priority, the + * threads will queue on the condition variable. + * - [6.7.2] Atomically signaling the condition variable five times + * then waiting for the threads to terminate in priority order, the + * order is tested. + * . + */ + +static void rt_test_006_007_setup(void) { + chCondObjectInit(&c1); + chMtxObjectInit(&m1); +} + +static void rt_test_006_007_execute(void) { + + /* [6.7.1] Starting the five threads with increasing priority, the + threads will queue on the condition variable.*/ + test_set_step(1); + { + tprio_t prio = chThdGetPriorityX(); + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread6, "E"); + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread6, "D"); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread6, "C"); + threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread6, "B"); + threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread6, "A"); + } + + /* [6.7.2] Atomically signaling the condition variable five times + then waiting for the threads to terminate in priority order, the + order is tested.*/ + test_set_step(2); + { + chSysLock(); + chCondSignalI(&c1); + chCondSignalI(&c1); + chCondSignalI(&c1); + chCondSignalI(&c1); + chCondSignalI(&c1); + chSchRescheduleS(); + chSysUnlock(); + test_wait_threads(); + test_assert_sequence("ABCDE", "invalid sequence"); + } +} + +static const testcase_t rt_test_006_007 = { + "Condition Variable signal test", + rt_test_006_007_setup, + NULL, + rt_test_006_007_execute +}; +#endif /* CH_CFG_USE_CONDVARS */ + +#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) +/** + * @page rt_test_006_008 [6.8] Condition Variable broadcast test + * + *

Description

+ * Five threads take a mutex and then enter a conditional variable + * queue, the tester thread then proceeds to broadcast the conditional + * variable.
The test expects the threads to reach their goal in + * increasing priority order regardless of the initial order. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_CONDVARS + * . + * + *

Test Steps

+ * - [6.8.1] Starting the five threads with increasing priority, the + * threads will queue on the condition variable. + * - [6.8.2] Broarcasting on the condition variable then waiting for + * the threads to terminate in priority order, the order is tested. + * . + */ + +static void rt_test_006_008_setup(void) { + chCondObjectInit(&c1); + chMtxObjectInit(&m1); +} + +static void rt_test_006_008_execute(void) { + + /* [6.8.1] Starting the five threads with increasing priority, the + threads will queue on the condition variable.*/ + test_set_step(1); + { + tprio_t prio = chThdGetPriorityX(); + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread6, "E"); + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread6, "D"); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread6, "C"); + threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread6, "B"); + threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread6, "A"); + } + + /* [6.8.2] Broarcasting on the condition variable then waiting for + the threads to terminate in priority order, the order is tested.*/ + test_set_step(2); + { + chCondBroadcast(&c1); + test_wait_threads(); + test_assert_sequence("ABCDE", "invalid sequence"); + } +} + +static const testcase_t rt_test_006_008 = { + "Condition Variable broadcast test", + rt_test_006_008_setup, + NULL, + rt_test_006_008_execute +}; +#endif /* CH_CFG_USE_CONDVARS */ + +#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) +/** + * @page rt_test_006_009 [6.9] Condition Variable priority boost test + * + *

Description

+ * This test case verifies the priority boost of a thread waiting on a + * conditional variable queue. It tests this very specific situation in + * order to improve code coverage. The created threads perform the + * following operations: TA{lock(M2), lock(M1), wait(C1), unlock(M1), + * unlock(M2)}, TB{lock(M2), wait(C1), unlock(M2)}. TC{lock(M1), + * unlock(M1)}. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_CONDVARS + * . + * + *

Test Steps

+ * - [6.9.1] Reading current base priority. + * - [6.9.2] Thread A is created at priority P(+1), it locks M2, locks + * M1 and goes to wait on C1. + * - [6.9.3] Thread C is created at priority P(+2), it enqueues on M1 + * and boosts TA priority at P(+2). + * - [6.9.4] Thread B is created at priority P(+3), it enqueues on M2 + * and boosts TA priority at P(+3). + * - [6.9.5] Signaling C1: TA wakes up, unlocks M1 and priority goes to + * P(+2). TB locks M1, unlocks M1 and completes. TA unlocks M2 and + * priority goes to P(+1). TC waits on C1. TA completes. + * - [6.9.6] Signaling C1: TC wakes up, unlocks M1 and completes. + * - [6.9.7] Checking the order of operations. + * . + */ + +static void rt_test_006_009_setup(void) { + chCondObjectInit(&c1); + chMtxObjectInit(&m1); + chMtxObjectInit(&m2); +} + +static void rt_test_006_009_execute(void) { + tprio_t prio; + + /* [6.9.1] Reading current base priority.*/ + test_set_step(1); + { + prio = chThdGetPriorityX(); + } + + /* [6.9.2] Thread A is created at priority P(+1), it locks M2, locks + M1 and goes to wait on C1.*/ + test_set_step(2); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread8, "A"); + } + + /* [6.9.3] Thread C is created at priority P(+2), it enqueues on M1 + and boosts TA priority at P(+2).*/ + test_set_step(3); + { + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread6, "C"); + } + + /* [6.9.4] Thread B is created at priority P(+3), it enqueues on M2 + and boosts TA priority at P(+3).*/ + test_set_step(4); + { + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread9, "B"); + } + + /* [6.9.5] Signaling C1: TA wakes up, unlocks M1 and priority goes to + P(+2). TB locks M1, unlocks M1 and completes. TA unlocks M2 and + priority goes to P(+1). TC waits on C1. TA completes.*/ + test_set_step(5); + { + chCondSignal(&c1); + } + + /* [6.9.6] Signaling C1: TC wakes up, unlocks M1 and completes.*/ + test_set_step(6); + { + chCondSignal(&c1); + } + + /* [6.9.7] Checking the order of operations.*/ + test_set_step(7); + { + test_wait_threads(); + test_assert_sequence("ABC", "invalid sequence"); + } +} + +static const testcase_t rt_test_006_009 = { + "Condition Variable priority boost test", + rt_test_006_009_setup, + NULL, + rt_test_006_009_execute +}; +#endif /* CH_CFG_USE_CONDVARS */ + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Mutexes, Condition Variables and Priority Inheritance. + */ +const testcase_t * const rt_test_sequence_006[] = { + &rt_test_006_001, +#if (CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) + &rt_test_006_002, +#endif +#if (CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) + &rt_test_006_003, +#endif + &rt_test_006_004, +#if (!CH_CFG_USE_MUTEXES_RECURSIVE) || defined(__DOXYGEN__) + &rt_test_006_005, +#endif +#if (CH_CFG_USE_MUTEXES_RECURSIVE) || defined(__DOXYGEN__) + &rt_test_006_006, +#endif +#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) + &rt_test_006_007, +#endif +#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) + &rt_test_006_008, +#endif +#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) + &rt_test_006_009, +#endif + NULL +}; + +#endif /* CH_CFG_USE_MUTEXES */ diff --git a/test/rt/source/test/rt_test_sequence_006.h b/test/rt/source/test/rt_test_sequence_006.h new file mode 100644 index 000000000..1e6fc5f1c --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_006.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_006.h + * @brief Test Sequence 006 header. + */ + +#ifndef RT_TEST_SEQUENCE_006_H +#define RT_TEST_SEQUENCE_006_H + +extern const testcase_t * const rt_test_sequence_006[]; + +#endif /* RT_TEST_SEQUENCE_006_H */ diff --git a/test/rt/source/test/rt_test_sequence_007.c b/test/rt/source/test/rt_test_sequence_007.c new file mode 100644 index 000000000..8344eb220 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_007.c @@ -0,0 +1,123 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_007.c + * @brief Test Sequence 007 code. + * + * @page rt_test_sequence_007 [7] Synchronous Messages + * + * File: @ref rt_test_sequence_007.c + * + *

Description

+ * This module implements the test sequence for the Synchronous + * Messages subsystem. + * + *

Conditions

+ * This sequence is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MESSAGES + * . + * + *

Test Cases

+ * - @subpage rt_test_007_001 + * . + */ + +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +static THD_FUNCTION(msg_thread1, p) { + + chMsgSend(p, 'A'); + chMsgSend(p, 'B'); + chMsgSend(p, 'C'); + chMsgSend(p, 'D'); +} + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page rt_test_007_001 [7.1] Messages Server loop + * + *

Description

+ * A messenger thread is spawned that sends four messages back to the + * tester thread.
The test expect to receive the messages in the + * correct sequence and to not find a fifth message waiting. + * + *

Test Steps

+ * - [7.1.1] Starting the messenger thread. + * - [7.1.2] Waiting for four messages then testing the receive order. + * . + */ + +static void rt_test_007_001_execute(void) { + thread_t *tp; + msg_t msg; + + /* [7.1.1] Starting the messenger thread.*/ + test_set_step(1); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() + 1, + msg_thread1, chThdGetSelfX()); + } + + /* [7.1.2] Waiting for four messages then testing the receive + order.*/ + test_set_step(2); + { + unsigned i; + + for (i = 0; i < 4; i++) { + tp = chMsgWait(); + msg = chMsgGet(tp); + chMsgRelease(tp, msg); + test_emit_token(msg); + } + test_wait_threads(); + test_assert_sequence("ABCD", "invalid sequence"); + } +} + +static const testcase_t rt_test_007_001 = { + "Messages Server loop", + NULL, + NULL, + rt_test_007_001_execute +}; + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Synchronous Messages. + */ +const testcase_t * const rt_test_sequence_007[] = { + &rt_test_007_001, + NULL +}; + +#endif /* CH_CFG_USE_MESSAGES */ diff --git a/test/rt/source/test/rt_test_sequence_007.h b/test/rt/source/test/rt_test_sequence_007.h new file mode 100644 index 000000000..09022befe --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_007.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_007.h + * @brief Test Sequence 007 header. + */ + +#ifndef RT_TEST_SEQUENCE_007_H +#define RT_TEST_SEQUENCE_007_H + +extern const testcase_t * const rt_test_sequence_007[]; + +#endif /* RT_TEST_SEQUENCE_007_H */ diff --git a/test/rt/source/test/rt_test_sequence_008.c b/test/rt/source/test/rt_test_sequence_008.c new file mode 100644 index 000000000..f66180feb --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_008.c @@ -0,0 +1,569 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_008.c + * @brief Test Sequence 008 code. + * + * @page rt_test_sequence_008 [8] Event Sources and Event Flags + * + * File: @ref rt_test_sequence_008.c + * + *

Description

+ * This module implements the test sequence for the Events subsystem. + * + *

Conditions

+ * This sequence is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_EVENTS + * . + * + *

Test Cases

+ * - @subpage rt_test_008_001 + * - @subpage rt_test_008_002 + * - @subpage rt_test_008_003 + * - @subpage rt_test_008_004 + * - @subpage rt_test_008_005 + * - @subpage rt_test_008_006 + * - @subpage rt_test_008_007 + * . + */ + +#if (CH_CFG_USE_EVENTS) || defined(__DOXYGEN__) + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +static EVENTSOURCE_DECL(es1); +static EVENTSOURCE_DECL(es2); + +static void h1(eventid_t id) {(void)id;test_emit_token('A');} +static void h2(eventid_t id) {(void)id;test_emit_token('B');} +static void h3(eventid_t id) {(void)id;test_emit_token('C');} +static ROMCONST evhandler_t evhndl[] = {h1, h2, h3}; + +static THD_FUNCTION(evt_thread3, p) { + + chThdSleepMilliseconds(50); + chEvtSignal((thread_t *)p, 1); +} + +static THD_FUNCTION(evt_thread7, p) { + + (void)p; + chEvtBroadcast(&es1); + chThdSleepMilliseconds(50); + chEvtBroadcast(&es2); +} + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page rt_test_008_001 [8.1] Events registration + * + *

Description

+ * Two event listeners are registered on an event source and then + * unregistered in the same order.
The test expects that the even + * source has listeners after the registrations and after the first + * unregistration, then, after the second unegistration, the test + * expects no more listeners. + * + *

Test Steps

+ * - [8.1.1] An Event Source is initialized. + * - [8.1.2] Two Event Listeners are registered on the Event Source, + * the Event Source is tested to have listeners. + * - [8.1.3] An Event Listener is unregistered, the Event Source must + * still have listeners. + * - [8.1.4] An Event Listener is unregistered, the Event Source must + * not have listeners. + * . + */ + +static void rt_test_008_001_execute(void) { + event_listener_t el1, el2; + + /* [8.1.1] An Event Source is initialized.*/ + test_set_step(1); + { + chEvtObjectInit(&es1); + } + + /* [8.1.2] Two Event Listeners are registered on the Event Source, + the Event Source is tested to have listeners.*/ + test_set_step(2); + { + chEvtRegisterMask(&es1, &el1, 1); + chEvtRegisterMask(&es1, &el2, 2); + test_assert_lock(chEvtIsListeningI(&es1), "no listener"); + } + + /* [8.1.3] An Event Listener is unregistered, the Event Source must + still have listeners.*/ + test_set_step(3); + { + chEvtUnregister(&es1, &el1); + test_assert_lock(chEvtIsListeningI(&es1), "no listener"); + } + + /* [8.1.4] An Event Listener is unregistered, the Event Source must + not have listeners.*/ + test_set_step(4); + { + chEvtUnregister(&es1, &el2); + test_assert_lock(!chEvtIsListeningI(&es1), "stuck listener"); + } +} + +static const testcase_t rt_test_008_001 = { + "Events registration", + NULL, + NULL, + rt_test_008_001_execute +}; + +/** + * @page rt_test_008_002 [8.2] Event Flags dispatching + * + *

Description

+ * The test dispatches three event flags and verifies that the + * associated event handlers are invoked in LSb-first order. + * + *

Test Steps

+ * - [8.2.1] Three evenf flag bits are raised then chEvtDispatch() is + * invoked, the sequence of handlers calls is tested. + * . + */ + +static void rt_test_008_002_setup(void) { + chEvtGetAndClearEvents(ALL_EVENTS); +} + +static void rt_test_008_002_execute(void) { + + /* [8.2.1] Three evenf flag bits are raised then chEvtDispatch() is + invoked, the sequence of handlers calls is tested.*/ + test_set_step(1); + { + chEvtDispatch(evhndl, 7); + test_assert_sequence("ABC", "invalid sequence"); + } +} + +static const testcase_t rt_test_008_002 = { + "Event Flags dispatching", + rt_test_008_002_setup, + NULL, + rt_test_008_002_execute +}; + +/** + * @page rt_test_008_003 [8.3] Events Flags wait using chEvtWaitOne() + * + *

Description

+ * Functionality of chEvtWaitOne() is tested under various scenarios. + * + *

Test Steps

+ * - [8.3.1] Setting three event flags. + * - [8.3.2] Calling chEvtWaitOne() three times, each time a single + * flag must be returned in order of priority. + * - [8.3.3] Getting current time and starting a signaler thread, the + * thread will set an event flag after 50mS. + * - [8.3.4] Calling chEvtWaitOne() then verifying that the event has + * been received after 50mS and that the event flags mask has been + * emptied. + * . + */ + +static void rt_test_008_003_setup(void) { + chEvtGetAndClearEvents(ALL_EVENTS); +} + +static void rt_test_008_003_execute(void) { + eventmask_t m; + systime_t target_time; + + /* [8.3.1] Setting three event flags.*/ + test_set_step(1); + { + chEvtAddEvents(7); + } + + /* [8.3.2] Calling chEvtWaitOne() three times, each time a single + flag must be returned in order of priority.*/ + test_set_step(2); + { + m = chEvtWaitOne(ALL_EVENTS); + test_assert(m == 1, "single event error"); + m = chEvtWaitOne(ALL_EVENTS); + test_assert(m == 2, "single event error"); + m = chEvtWaitOne(ALL_EVENTS); + test_assert(m == 4, "single event error"); + m = chEvtGetAndClearEvents(ALL_EVENTS); + test_assert(m == 0, "stuck event"); + } + + /* [8.3.3] Getting current time and starting a signaler thread, the + thread will set an event flag after 50mS.*/ + test_set_step(3); + { + target_time = test_wait_tick() + TIME_MS2I(50); + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, + evt_thread3, chThdGetSelfX()); + } + + /* [8.3.4] Calling chEvtWaitOne() then verifying that the event has + been received after 50mS and that the event flags mask has been + emptied.*/ + test_set_step(4); + { + m = chEvtWaitOne(ALL_EVENTS); + test_assert_time_window(target_time, target_time + ALLOWED_DELAY, + "out of time window"); + test_assert(m == 1, "event flag error"); + m = chEvtGetAndClearEvents(ALL_EVENTS); + test_assert(m == 0, "stuck event"); + test_wait_threads(); + } +} + +static const testcase_t rt_test_008_003 = { + "Events Flags wait using chEvtWaitOne()", + rt_test_008_003_setup, + NULL, + rt_test_008_003_execute +}; + +/** + * @page rt_test_008_004 [8.4] Events Flags wait using chEvtWaitAny() + * + *

Description

+ * Functionality of chEvtWaitAny() is tested under various scenarios. + * + *

Test Steps

+ * - [8.4.1] Setting two, non contiguous, event flags. + * - [8.4.2] Calling chEvtWaitAny() one time, the two flags must be + * returned. + * - [8.4.3] Getting current time and starting a signaler thread, the + * thread will set an event flag after 50mS. + * - [8.4.4] Calling chEvtWaitAny() then verifying that the event has + * been received after 50mS and that the event flags mask has been + * emptied. + * . + */ + +static void rt_test_008_004_setup(void) { + chEvtGetAndClearEvents(ALL_EVENTS); +} + +static void rt_test_008_004_execute(void) { + eventmask_t m; + systime_t target_time; + + /* [8.4.1] Setting two, non contiguous, event flags.*/ + test_set_step(1); + { + chEvtAddEvents(5); + } + + /* [8.4.2] Calling chEvtWaitAny() one time, the two flags must be + returned.*/ + test_set_step(2); + { + m = chEvtWaitAny(ALL_EVENTS); + test_assert(m == 5, "unexpected pending bit"); + m = chEvtGetAndClearEvents(ALL_EVENTS); + test_assert(m == 0, "stuck event"); + } + + /* [8.4.3] Getting current time and starting a signaler thread, the + thread will set an event flag after 50mS.*/ + test_set_step(3); + { + target_time = test_wait_tick() + TIME_MS2I(50); + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, + evt_thread3, chThdGetSelfX()); + } + + /* [8.4.4] Calling chEvtWaitAny() then verifying that the event has + been received after 50mS and that the event flags mask has been + emptied.*/ + test_set_step(4); + { + m = chEvtWaitAny(ALL_EVENTS); + test_assert_time_window(target_time, target_time + ALLOWED_DELAY, + "out of time window"); + test_assert(m == 1, "event flag error"); + m = chEvtGetAndClearEvents(ALL_EVENTS); + test_assert(m == 0, "stuck event"); + test_wait_threads(); + } +} + +static const testcase_t rt_test_008_004 = { + "Events Flags wait using chEvtWaitAny()", + rt_test_008_004_setup, + NULL, + rt_test_008_004_execute +}; + +/** + * @page rt_test_008_005 [8.5] Events Flags wait using chEvtWaitAll() + * + *

Description

+ * Functionality of chEvtWaitAll() is tested under various scenarios. + * + *

Test Steps

+ * - [8.5.1] Setting two, non contiguous, event flags. + * - [8.5.2] Calling chEvtWaitAll() one time, the two flags must be + * returned. + * - [8.5.3] Setting one event flag. + * - [8.5.4] Getting current time and starting a signaler thread, the + * thread will set another event flag after 50mS. + * - [8.5.5] Calling chEvtWaitAll() then verifying that both event + * flags have been received after 50mS and that the event flags mask + * has been emptied. + * . + */ + +static void rt_test_008_005_setup(void) { + chEvtGetAndClearEvents(ALL_EVENTS); +} + +static void rt_test_008_005_execute(void) { + eventmask_t m; + systime_t target_time; + + /* [8.5.1] Setting two, non contiguous, event flags.*/ + test_set_step(1); + { + chEvtAddEvents(5); + } + + /* [8.5.2] Calling chEvtWaitAll() one time, the two flags must be + returned.*/ + test_set_step(2); + { + m = chEvtWaitAll(5); + test_assert(m == 5, "unexpected pending bit"); + m = chEvtGetAndClearEvents(ALL_EVENTS); + test_assert(m == 0, "stuck event"); + } + + /* [8.5.3] Setting one event flag.*/ + test_set_step(3); + { + chEvtAddEvents(4); + } + + /* [8.5.4] Getting current time and starting a signaler thread, the + thread will set another event flag after 50mS.*/ + test_set_step(4); + { + target_time = test_wait_tick() + TIME_MS2I(50); + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, + evt_thread3, chThdGetSelfX()); + } + + /* [8.5.5] Calling chEvtWaitAll() then verifying that both event + flags have been received after 50mS and that the event flags mask + has been emptied.*/ + test_set_step(5); + { + m = chEvtWaitAll(5); + test_assert_time_window(target_time, target_time + ALLOWED_DELAY, + "out of time window"); + test_assert(m == 5, "event flags error"); + m = chEvtGetAndClearEvents(ALL_EVENTS); + test_assert(m == 0, "stuck event"); + test_wait_threads(); + } +} + +static const testcase_t rt_test_008_005 = { + "Events Flags wait using chEvtWaitAll()", + rt_test_008_005_setup, + NULL, + rt_test_008_005_execute +}; + +#if (CH_CFG_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__) +/** + * @page rt_test_008_006 [8.6] Events Flags wait timeouts + * + *

Description

+ * Timeout functionality is tested for chEvtWaitOneTimeout(), + * chEvtWaitAnyTimeout() and chEvtWaitAllTimeout(). + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_EVENTS_TIMEOUT + * . + * + *

Test Steps

+ * - [8.6.1] The functions are invoked first with TIME_IMMEDIATE + * timeout, the timeout condition is tested. + * - [8.6.2] The functions are invoked first with a 50mS timeout, the + * timeout condition is tested. + * . + */ + +static void rt_test_008_006_setup(void) { + chEvtGetAndClearEvents(ALL_EVENTS); +} + +static void rt_test_008_006_execute(void) { + eventmask_t m; + + /* [8.6.1] The functions are invoked first with TIME_IMMEDIATE + timeout, the timeout condition is tested.*/ + test_set_step(1); + { + m = chEvtWaitOneTimeout(ALL_EVENTS, TIME_IMMEDIATE); + test_assert(m == 0, "spurious event"); + m = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_IMMEDIATE); + test_assert(m == 0, "spurious event"); + m = chEvtWaitAllTimeout(ALL_EVENTS, TIME_IMMEDIATE); + test_assert(m == 0, "spurious event"); + } + + /* [8.6.2] The functions are invoked first with a 50mS timeout, the + timeout condition is tested.*/ + test_set_step(2); + { + m = chEvtWaitOneTimeout(ALL_EVENTS, TIME_MS2I(50)); + test_assert(m == 0, "spurious event"); + m = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(50)); + test_assert(m == 0, "spurious event"); + m = chEvtWaitAllTimeout(ALL_EVENTS, TIME_MS2I(50)); + test_assert(m == 0, "spurious event"); + } +} + +static const testcase_t rt_test_008_006 = { + "Events Flags wait timeouts", + rt_test_008_006_setup, + NULL, + rt_test_008_006_execute +}; +#endif /* CH_CFG_USE_EVENTS_TIMEOUT */ + +/** + * @page rt_test_008_007 [8.7] Broadcasting using chEvtBroadcast() + * + *

Description

+ * Functionality of chEvtBroadcast() is tested. + * + *

Test Steps

+ * - [8.7.1] Registering on two event sources associating them with + * flags 1 and 4. + * - [8.7.2] Getting current time and starting a broadcaster thread, + * the thread broadcast the first Event Source immediately and the + * other after 50mS. + * - [8.7.3] Calling chEvtWaitAll() then verifying that both event + * flags have been received after 50mS and that the event flags mask + * has been emptied. + * - [8.7.4] Unregistering from the Event Sources. + * . + */ + +static void rt_test_008_007_setup(void) { + chEvtGetAndClearEvents(ALL_EVENTS); + chEvtObjectInit(&es1); + chEvtObjectInit(&es2); +} + +static void rt_test_008_007_execute(void) { + eventmask_t m; + event_listener_t el1, el2; + systime_t target_time; + + /* [8.7.1] Registering on two event sources associating them with + flags 1 and 4.*/ + test_set_step(1); + { + chEvtRegisterMask(&es1, &el1, 1); + chEvtRegisterMask(&es2, &el2, 4); + } + + /* [8.7.2] Getting current time and starting a broadcaster thread, + the thread broadcast the first Event Source immediately and the + other after 50mS.*/ + test_set_step(2); + { + target_time = test_wait_tick() + TIME_MS2I(50); + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, + evt_thread7, "A"); + } + + /* [8.7.3] Calling chEvtWaitAll() then verifying that both event + flags have been received after 50mS and that the event flags mask + has been emptied.*/ + test_set_step(3); + { + m = chEvtWaitAll(5); + test_assert_time_window(target_time, target_time + ALLOWED_DELAY, + "out of time window"); + m = chEvtGetAndClearEvents(ALL_EVENTS); + test_assert(m == 0, "stuck event"); + test_wait_threads(); + } + + /* [8.7.4] Unregistering from the Event Sources.*/ + test_set_step(4); + { + chEvtUnregister(&es1, &el1); + chEvtUnregister(&es2, &el2); + test_assert(!chEvtIsListeningI(&es1), "stuck listener"); + test_assert(!chEvtIsListeningI(&es2), "stuck listener"); + } +} + +static const testcase_t rt_test_008_007 = { + "Broadcasting using chEvtBroadcast()", + rt_test_008_007_setup, + NULL, + rt_test_008_007_execute +}; + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Event Sources and Event Flags. + */ +const testcase_t * const rt_test_sequence_008[] = { + &rt_test_008_001, + &rt_test_008_002, + &rt_test_008_003, + &rt_test_008_004, + &rt_test_008_005, +#if (CH_CFG_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__) + &rt_test_008_006, +#endif + &rt_test_008_007, + NULL +}; + +#endif /* CH_CFG_USE_EVENTS */ diff --git a/test/rt/source/test/rt_test_sequence_008.h b/test/rt/source/test/rt_test_sequence_008.h new file mode 100644 index 000000000..3f9c4f412 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_008.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_008.h + * @brief Test Sequence 008 header. + */ + +#ifndef RT_TEST_SEQUENCE_008_H +#define RT_TEST_SEQUENCE_008_H + +extern const testcase_t * const rt_test_sequence_008[]; + +#endif /* RT_TEST_SEQUENCE_008_H */ diff --git a/test/rt/source/test/rt_test_sequence_009.c b/test/rt/source/test/rt_test_sequence_009.c new file mode 100644 index 000000000..d43bf0fec --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_009.c @@ -0,0 +1,409 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_009.c + * @brief Test Sequence 009 code. + * + * @page rt_test_sequence_009 [9] Mailboxes + * + * File: @ref rt_test_sequence_009.c + * + *

Description

+ * This sequence tests the ChibiOS/RT functionalities related to + * mailboxes. + * + *

Conditions

+ * This sequence is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MAILBOXES + * . + * + *

Test Cases

+ * - @subpage rt_test_009_001 + * - @subpage rt_test_009_002 + * - @subpage rt_test_009_003 + * . + */ + +#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__) + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +#define MB_SIZE 4 + +static msg_t mb_buffer[MB_SIZE]; +static MAILBOX_DECL(mb1, mb_buffer, MB_SIZE); + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page rt_test_009_001 [9.1] Mailbox normal API, non-blocking tests + * + *

Description

+ * The mailbox normal API is tested without triggering blocking + * conditions. + * + *

Test Steps

+ * - [9.1.1] Testing the mailbox size. + * - [9.1.2] Resetting the mailbox, conditions are checked, no errors + * expected. + * - [9.1.3] Testing the behavior of API when the mailbox is in reset + * state then return in active state. + * - [9.1.4] Filling the mailbox using chMBPostTimeout() and + * chMBPostAheadTimeout() once, no errors expected. + * - [9.1.5] Testing intermediate conditions. Data pointers must be + * aligned, semaphore counters are checked. + * - [9.1.6] Emptying the mailbox using chMBFetchTimeout(), no errors + * expected. + * - [9.1.7] Posting and then fetching one more message, no errors + * expected. + * - [9.1.8] Testing final conditions. Data pointers must be aligned to + * buffer start, semaphore counters are checked. + * . + */ + +static void rt_test_009_001_setup(void) { + chMBObjectInit(&mb1, mb_buffer, MB_SIZE); +} + +static void rt_test_009_001_teardown(void) { + chMBReset(&mb1); +} + +static void rt_test_009_001_execute(void) { + msg_t msg1, msg2; + unsigned i; + + /* [9.1.1] Testing the mailbox size.*/ + test_set_step(1); + { + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size"); + } + + /* [9.1.2] Resetting the mailbox, conditions are checked, no errors + expected.*/ + test_set_step(2); + { + chMBReset(&mb1); + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); + test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); + test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); + } + + /* [9.1.3] Testing the behavior of API when the mailbox is in reset + state then return in active state.*/ + test_set_step(3); + { + msg1 = chMBPostTimeout(&mb1, (msg_t)0, TIME_INFINITE); + test_assert(msg1 == MSG_RESET, "not in reset state"); + msg1 = chMBPostAheadTimeout(&mb1, (msg_t)0, TIME_INFINITE); + test_assert(msg1 == MSG_RESET, "not in reset state"); + msg1 = chMBFetchTimeout(&mb1, &msg2, TIME_INFINITE); + test_assert(msg1 == MSG_RESET, "not in reset state"); + chMBResumeX(&mb1); + } + + /* [9.1.4] Filling the mailbox using chMBPostTimeout() and + chMBPostAheadTimeout() once, no errors expected.*/ + test_set_step(4); + { + for (i = 0; i < MB_SIZE - 1; i++) { + msg1 = chMBPostTimeout(&mb1, 'B' + i, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + msg1 = chMBPostAheadTimeout(&mb1, 'A', TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + + /* [9.1.5] Testing intermediate conditions. Data pointers must be + aligned, semaphore counters are checked.*/ + test_set_step(5); + { + test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full"); + test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned"); + } + + /* [9.1.6] Emptying the mailbox using chMBFetchTimeout(), no errors + expected.*/ + test_set_step(6); + { + for (i = 0; i < MB_SIZE; i++) { + msg1 = chMBFetchTimeout(&mb1, &msg2, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + test_emit_token(msg2); + } + test_assert_sequence("ABCD", "wrong get sequence"); + } + + /* [9.1.7] Posting and then fetching one more message, no errors + expected.*/ + test_set_step(7); + { + msg1 = chMBPostTimeout(&mb1, 'B' + i, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + msg1 = chMBFetchTimeout(&mb1, &msg2, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + + /* [9.1.8] Testing final conditions. Data pointers must be aligned to + buffer start, semaphore counters are checked.*/ + test_set_step(8); + { + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); + test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); + test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); + } +} + +static const testcase_t rt_test_009_001 = { + "Mailbox normal API, non-blocking tests", + rt_test_009_001_setup, + rt_test_009_001_teardown, + rt_test_009_001_execute +}; + +/** + * @page rt_test_009_002 [9.2] Mailbox I-Class API, non-blocking tests + * + *

Description

+ * The mailbox I-Class API is tested without triggering blocking + * conditions. + * + *

Test Steps

+ * - [9.2.1] Testing the mailbox size. + * - [9.2.2] Resetting the mailbox, conditions are checked, no errors + * expected. The mailbox is then returned in active state. + * - [9.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI() + * once, no errors expected. + * - [9.2.4] Testing intermediate conditions. Data pointers must be + * aligned, semaphore counters are checked. + * - [9.2.5] Emptying the mailbox using chMBFetchI(), no errors + * expected. + * - [9.2.6] Posting and then fetching one more message, no errors + * expected. + * - [9.2.7] Testing final conditions. Data pointers must be aligned to + * buffer start, semaphore counters are checked. + * . + */ + +static void rt_test_009_002_setup(void) { + chMBObjectInit(&mb1, mb_buffer, MB_SIZE); +} + +static void rt_test_009_002_teardown(void) { + chMBReset(&mb1); +} + +static void rt_test_009_002_execute(void) { + msg_t msg1, msg2; + unsigned i; + + /* [9.2.1] Testing the mailbox size.*/ + test_set_step(1); + { + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size"); + } + + /* [9.2.2] Resetting the mailbox, conditions are checked, no errors + expected. The mailbox is then returned in active state.*/ + test_set_step(2); + { + chSysLock(); + chMBResetI(&mb1); + chSysUnlock(); + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); + test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); + test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); + chMBResumeX(&mb1); + } + + /* [9.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI() + once, no errors expected.*/ + test_set_step(3); + { + for (i = 0; i < MB_SIZE - 1; i++) { + chSysLock(); + msg1 = chMBPostI(&mb1, 'B' + i); + chSysUnlock(); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + chSysLock(); + msg1 = chMBPostAheadI(&mb1, 'A'); + chSysUnlock(); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + + /* [9.2.4] Testing intermediate conditions. Data pointers must be + aligned, semaphore counters are checked.*/ + test_set_step(4); + { + test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full"); + test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned"); + } + + /* [9.2.5] Emptying the mailbox using chMBFetchI(), no errors + expected.*/ + test_set_step(5); + { + for (i = 0; i < MB_SIZE; i++) { + chSysLock(); + msg1 = chMBFetchI(&mb1, &msg2); + chSysUnlock(); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + test_emit_token(msg2); + } + test_assert_sequence("ABCD", "wrong get sequence"); + } + + /* [9.2.6] Posting and then fetching one more message, no errors + expected.*/ + test_set_step(6); + { + msg1 = chMBPostTimeout(&mb1, 'B' + i, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + msg1 = chMBFetchTimeout(&mb1, &msg2, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + + /* [9.2.7] Testing final conditions. Data pointers must be aligned to + buffer start, semaphore counters are checked.*/ + test_set_step(7); + { + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); + test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); + test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); + } +} + +static const testcase_t rt_test_009_002 = { + "Mailbox I-Class API, non-blocking tests", + rt_test_009_002_setup, + rt_test_009_002_teardown, + rt_test_009_002_execute +}; + +/** + * @page rt_test_009_003 [9.3] Mailbox timeouts + * + *

Description

+ * The mailbox API is tested for timeouts. + * + *

Test Steps

+ * - [9.3.1] Filling the mailbox. + * - [9.3.2] Testing chMBPostTimeout(), chMBPostI(), + * chMBPostAheadTimeout() and chMBPostAheadI() timeout. + * - [9.3.3] Resetting the mailbox. The mailbox is then returned in + * active state. + * - [9.3.4] Testing chMBFetchTimeout() and chMBFetchI() timeout. + * . + */ + +static void rt_test_009_003_setup(void) { + chMBObjectInit(&mb1, mb_buffer, MB_SIZE); +} + +static void rt_test_009_003_teardown(void) { + chMBReset(&mb1); +} + +static void rt_test_009_003_execute(void) { + msg_t msg1, msg2; + unsigned i; + + /* [9.3.1] Filling the mailbox.*/ + test_set_step(1); + { + for (i = 0; i < MB_SIZE; i++) { + msg1 = chMBPostTimeout(&mb1, 'B' + i, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + } + + /* [9.3.2] Testing chMBPostTimeout(), chMBPostI(), + chMBPostAheadTimeout() and chMBPostAheadI() timeout.*/ + test_set_step(2); + { + msg1 = chMBPostTimeout(&mb1, 'X', 1); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); + chSysLock(); + msg1 = chMBPostI(&mb1, 'X'); + chSysUnlock(); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); + msg1 = chMBPostAheadTimeout(&mb1, 'X', 1); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); + chSysLock(); + msg1 = chMBPostAheadI(&mb1, 'X'); + chSysUnlock(); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); + } + + /* [9.3.3] Resetting the mailbox. The mailbox is then returned in + active state.*/ + test_set_step(3); + { + chMBReset(&mb1); + chMBResumeX(&mb1); + } + + /* [9.3.4] Testing chMBFetchTimeout() and chMBFetchI() timeout.*/ + test_set_step(4); + { + msg1 = chMBFetchTimeout(&mb1, &msg2, 1); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); + chSysLock(); + msg1 = chMBFetchI(&mb1, &msg2); + chSysUnlock(); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); + } +} + +static const testcase_t rt_test_009_003 = { + "Mailbox timeouts", + rt_test_009_003_setup, + rt_test_009_003_teardown, + rt_test_009_003_execute +}; + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Mailboxes. + */ +const testcase_t * const rt_test_sequence_009[] = { + &rt_test_009_001, + &rt_test_009_002, + &rt_test_009_003, + NULL +}; + +#endif /* CH_CFG_USE_MAILBOXES */ diff --git a/test/rt/source/test/rt_test_sequence_009.h b/test/rt/source/test/rt_test_sequence_009.h new file mode 100644 index 000000000..ffe13dfa1 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_009.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_009.h + * @brief Test Sequence 009 header. + */ + +#ifndef RT_TEST_SEQUENCE_009_H +#define RT_TEST_SEQUENCE_009_H + +extern const testcase_t * const rt_test_sequence_009[]; + +#endif /* RT_TEST_SEQUENCE_009_H */ diff --git a/test/rt/source/test/rt_test_sequence_010.c b/test/rt/source/test/rt_test_sequence_010.c new file mode 100644 index 000000000..80a81430c --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_010.c @@ -0,0 +1,297 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_010.c + * @brief Test Sequence 010 code. + * + * @page rt_test_sequence_010 [10] Memory Pools + * + * File: @ref rt_test_sequence_010.c + * + *

Description

+ * This sequence tests the ChibiOS/RT functionalities related to memory + * pools. + * + *

Conditions

+ * This sequence is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MEMPOOLS + * . + * + *

Test Cases

+ * - @subpage rt_test_010_001 + * - @subpage rt_test_010_002 + * - @subpage rt_test_010_003 + * . + */ + +#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +#define MEMORY_POOL_SIZE 4 + +static uint32_t objects[MEMORY_POOL_SIZE]; +static MEMORYPOOL_DECL(mp1, sizeof (uint32_t), PORT_NATURAL_ALIGN, NULL); + +#if CH_CFG_USE_SEMAPHORES +static GUARDEDMEMORYPOOL_DECL(gmp1, sizeof (uint32_t), PORT_NATURAL_ALIGN); +#endif + +static void *null_provider(size_t size, unsigned align) { + + (void)size; + (void)align; + + return NULL; +} + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page rt_test_010_001 [10.1] Loading and emptying a memory pool + * + *

Description

+ * The memory pool functionality is tested by loading and emptying it, + * all conditions are tested. + * + *

Test Steps

+ * - [10.1.1] Adding the objects to the pool using chPoolLoadArray(). + * - [10.1.2] Emptying the pool using chPoolAlloc(). + * - [10.1.3] Now must be empty. + * - [10.1.4] Adding the objects to the pool using chPoolFree(). + * - [10.1.5] Emptying the pool using chPoolAlloc() again. + * - [10.1.6] Now must be empty again. + * - [10.1.7] Covering the case where a provider is unable to return + * more memory. + * . + */ + +static void rt_test_010_001_setup(void) { + chPoolObjectInit(&mp1, sizeof (uint32_t), NULL); +} + +static void rt_test_010_001_execute(void) { + unsigned i; + + /* [10.1.1] Adding the objects to the pool using chPoolLoadArray().*/ + test_set_step(1); + { + chPoolLoadArray(&mp1, objects, MEMORY_POOL_SIZE); + } + + /* [10.1.2] Emptying the pool using chPoolAlloc().*/ + test_set_step(2); + { + for (i = 0; i < MEMORY_POOL_SIZE; i++) + test_assert(chPoolAlloc(&mp1) != NULL, "list empty"); + } + + /* [10.1.3] Now must be empty.*/ + test_set_step(3); + { + test_assert(chPoolAlloc(&mp1) == NULL, "list not empty"); + } + + /* [10.1.4] Adding the objects to the pool using chPoolFree().*/ + test_set_step(4); + { + for (i = 0; i < MEMORY_POOL_SIZE; i++) + chPoolFree(&mp1, &objects[i]); + } + + /* [10.1.5] Emptying the pool using chPoolAlloc() again.*/ + test_set_step(5); + { + for (i = 0; i < MEMORY_POOL_SIZE; i++) + test_assert(chPoolAlloc(&mp1) != NULL, "list empty"); + } + + /* [10.1.6] Now must be empty again.*/ + test_set_step(6); + { + test_assert(chPoolAlloc(&mp1) == NULL, "list not empty"); + } + + /* [10.1.7] Covering the case where a provider is unable to return + more memory.*/ + test_set_step(7); + { + chPoolObjectInit(&mp1, sizeof (uint32_t), null_provider); + test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory"); + } +} + +static const testcase_t rt_test_010_001 = { + "Loading and emptying a memory pool", + rt_test_010_001_setup, + NULL, + rt_test_010_001_execute +}; + +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) +/** + * @page rt_test_010_002 [10.2] Loading and emptying a guarded memory pool without waiting + * + *

Description

+ * The memory pool functionality is tested by loading and emptying it, + * all conditions are tested. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_SEMAPHORES + * . + * + *

Test Steps

+ * - [10.2.1] Adding the objects to the pool using + * chGuardedPoolLoadArray(). + * - [10.2.2] Emptying the pool using chGuardedPoolAllocTimeout(). + * - [10.2.3] Now must be empty. + * - [10.2.4] Adding the objects to the pool using chGuardedPoolFree(). + * - [10.2.5] Emptying the pool using chGuardedPoolAllocTimeout() + * again. + * - [10.2.6] Now must be empty again. + * . + */ + +static void rt_test_010_002_setup(void) { + chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); +} + +static void rt_test_010_002_execute(void) { + unsigned i; + + /* [10.2.1] Adding the objects to the pool using + chGuardedPoolLoadArray().*/ + test_set_step(1); + { + chGuardedPoolLoadArray(&gmp1, objects, MEMORY_POOL_SIZE); + } + + /* [10.2.2] Emptying the pool using chGuardedPoolAllocTimeout().*/ + test_set_step(2); + { + for (i = 0; i < MEMORY_POOL_SIZE; i++) + test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty"); + } + + /* [10.2.3] Now must be empty.*/ + test_set_step(3); + { + test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty"); + } + + /* [10.2.4] Adding the objects to the pool using + chGuardedPoolFree().*/ + test_set_step(4); + { + for (i = 0; i < MEMORY_POOL_SIZE; i++) + chGuardedPoolFree(&gmp1, &objects[i]); + } + + /* [10.2.5] Emptying the pool using chGuardedPoolAllocTimeout() + again.*/ + test_set_step(5); + { + for (i = 0; i < MEMORY_POOL_SIZE; i++) + test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty"); + } + + /* [10.2.6] Now must be empty again.*/ + test_set_step(6); + { + test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty"); + } +} + +static const testcase_t rt_test_010_002 = { + "Loading and emptying a guarded memory pool without waiting", + rt_test_010_002_setup, + NULL, + rt_test_010_002_execute +}; +#endif /* CH_CFG_USE_SEMAPHORES */ + +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) +/** + * @page rt_test_010_003 [10.3] Guarded Memory Pools timeout + * + *

Description

+ * The timeout features for the Guarded Memory Pools is tested. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_SEMAPHORES + * . + * + *

Test Steps

+ * - [10.3.1] Trying to allocate with 100mS timeout, must fail because + * the pool is empty. + * . + */ + +static void rt_test_010_003_setup(void) { + chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); +} + +static void rt_test_010_003_execute(void) { + + /* [10.3.1] Trying to allocate with 100mS timeout, must fail because + the pool is empty.*/ + test_set_step(1); + { + test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_MS2I(100)) == NULL, "list not empty"); + } +} + +static const testcase_t rt_test_010_003 = { + "Guarded Memory Pools timeout", + rt_test_010_003_setup, + NULL, + rt_test_010_003_execute +}; +#endif /* CH_CFG_USE_SEMAPHORES */ + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Memory Pools. + */ +const testcase_t * const rt_test_sequence_010[] = { + &rt_test_010_001, +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) + &rt_test_010_002, +#endif +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) + &rt_test_010_003, +#endif + NULL +}; + +#endif /* CH_CFG_USE_MEMPOOLS */ diff --git a/test/rt/source/test/rt_test_sequence_010.h b/test/rt/source/test/rt_test_sequence_010.h new file mode 100644 index 000000000..ed3fb97c6 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_010.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_010.h + * @brief Test Sequence 010 header. + */ + +#ifndef RT_TEST_SEQUENCE_010_H +#define RT_TEST_SEQUENCE_010_H + +extern const testcase_t * const rt_test_sequence_010[]; + +#endif /* RT_TEST_SEQUENCE_010_H */ diff --git a/test/rt/source/test/rt_test_sequence_011.c b/test/rt/source/test/rt_test_sequence_011.c new file mode 100644 index 000000000..7c4ec8a63 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_011.c @@ -0,0 +1,272 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_011.c + * @brief Test Sequence 011 code. + * + * @page rt_test_sequence_011 [11] Memory Heaps + * + * File: @ref rt_test_sequence_011.c + * + *

Description

+ * This sequence tests the ChibiOS/RT functionalities related to memory + * heaps. + * + *

Conditions

+ * This sequence is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_HEAP + * . + * + *

Test Cases

+ * - @subpage rt_test_011_001 + * - @subpage rt_test_011_002 + * . + */ + +#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +#define ALLOC_SIZE 16 +#define HEAP_SIZE (ALLOC_SIZE * 8) + +memory_heap_t test_heap; + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page rt_test_011_001 [11.1] Allocation and fragmentation + * + *

Description

+ * Series of allocations/deallocations are performed in carefully + * designed sequences in order to stimulate all the possible code paths + * inside the allocator. The test expects to find the heap back to the + * initial status after each sequence. + * + *

Test Steps

+ * - [11.1.1] Testing initial conditions, the heap must not be + * fragmented and one free block present. + * - [11.1.2] Trying to allocate an block bigger than available space, + * an error is expected. + * - [11.1.3] Single block allocation using chHeapAlloc() then the + * block is freed using chHeapFree(), must not fail. + * - [11.1.4] Using chHeapStatus() to assess the heap state. There must + * be at least one free block of sufficient size. + * - [11.1.5] Allocating then freeing in the same order. + * - [11.1.6] Allocating then freeing in reverse order. + * - [11.1.7] Small fragments handling. Checking the behavior when + * allocating blocks with size not multiple of alignment unit. + * - [11.1.8] Skipping a fragment, the first fragment in the list is + * too small so the allocator must pick the second one. + * - [11.1.9] Allocating the whole available space. + * - [11.1.10] Testing final conditions. The heap geometry must be the + * same than the one registered at beginning. + * . + */ + +static void rt_test_011_001_setup(void) { + chHeapObjectInit(&test_heap, test_buffer, sizeof(test_buffer)); +} + +static void rt_test_011_001_execute(void) { + void *p1, *p2, *p3; + size_t n, sz; + + /* [11.1.1] Testing initial conditions, the heap must not be + fragmented and one free block present.*/ + test_set_step(1); + { + test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented"); + } + + /* [11.1.2] Trying to allocate an block bigger than available space, + an error is expected.*/ + test_set_step(2); + { + p1 = chHeapAlloc(&test_heap, sizeof test_buffer * 2); + test_assert(p1 == NULL, "allocation not failed"); + } + + /* [11.1.3] Single block allocation using chHeapAlloc() then the + block is freed using chHeapFree(), must not fail.*/ + test_set_step(3); + { + p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); + test_assert(p1 != NULL, "allocation failed"); + chHeapFree(p1); + } + + /* [11.1.4] Using chHeapStatus() to assess the heap state. There must + be at least one free block of sufficient size.*/ + test_set_step(4); + { + size_t total_size, largest_size; + + n = chHeapStatus(&test_heap, &total_size, &largest_size); + test_assert(n == 1, "missing free block"); + test_assert(total_size >= ALLOC_SIZE, "unexpected heap state"); + test_assert(total_size == largest_size, "unexpected heap state"); + } + + /* [11.1.5] Allocating then freeing in the same order.*/ + test_set_step(5); + { + p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); + p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); + p3 = chHeapAlloc(&test_heap, ALLOC_SIZE); + chHeapFree(p1); /* Does not merge.*/ + chHeapFree(p2); /* Merges backward.*/ + chHeapFree(p3); /* Merges both sides.*/ + test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented"); + } + + /* [11.1.6] Allocating then freeing in reverse order.*/ + test_set_step(6); + { + p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); + p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); + p3 = chHeapAlloc(&test_heap, ALLOC_SIZE); + chHeapFree(p3); /* Merges forward.*/ + chHeapFree(p2); /* Merges forward.*/ + chHeapFree(p1); /* Merges forward.*/ + test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented"); + } + + /* [11.1.7] Small fragments handling. Checking the behavior when + allocating blocks with size not multiple of alignment unit.*/ + test_set_step(7); + { + p1 = chHeapAlloc(&test_heap, ALLOC_SIZE + 1); + p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); + chHeapFree(p1); + test_assert(chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state"); + p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); + /* Note, the first situation happens when the alignment size is smaller + than the header size, the second in the other cases.*/ + test_assert((chHeapStatus(&test_heap, &n, NULL) == 1) || + (chHeapStatus(&test_heap, &n, NULL) == 2), "heap fragmented"); + chHeapFree(p2); + chHeapFree(p1); + test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented"); + } + + /* [11.1.8] Skipping a fragment, the first fragment in the list is + too small so the allocator must pick the second one.*/ + test_set_step(8); + { + p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); + p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); + chHeapFree(p1); + test_assert( chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state"); + p1 = chHeapAlloc(&test_heap, ALLOC_SIZE * 2); /* Skips first fragment.*/ + chHeapFree(p1); + chHeapFree(p2); + test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented"); + } + + /* [11.1.9] Allocating the whole available space.*/ + test_set_step(9); + { + (void)chHeapStatus(&test_heap, &n, NULL); + p1 = chHeapAlloc(&test_heap, n); + test_assert(p1 != NULL, "allocation failed"); + test_assert(chHeapStatus(&test_heap, NULL, NULL) == 0, "not empty"); + chHeapFree(p1); + } + + /* [11.1.10] Testing final conditions. The heap geometry must be the + same than the one registered at beginning.*/ + test_set_step(10); + { + test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented"); + test_assert(n == sz, "size changed"); + } +} + +static const testcase_t rt_test_011_001 = { + "Allocation and fragmentation", + rt_test_011_001_setup, + NULL, + rt_test_011_001_execute +}; + +/** + * @page rt_test_011_002 [11.2] Default Heap + * + *

Description

+ * The default heap is pre-allocated in the system. We test base + * functionality. + * + *

Test Steps

+ * - [11.2.1] Single block allocation using chHeapAlloc() then the + * block is freed using chHeapFree(), must not fail. + * - [11.2.2] Testing allocation failure. + * . + */ + +static void rt_test_011_002_execute(void) { + void *p1; + size_t total_size, largest_size; + + /* [11.2.1] Single block allocation using chHeapAlloc() then the + block is freed using chHeapFree(), must not fail.*/ + test_set_step(1); + { + (void)chHeapStatus(NULL, &total_size, &largest_size); + p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); + test_assert(p1 != NULL, "allocation failed"); + chHeapFree(p1); + } + + /* [11.2.2] Testing allocation failure.*/ + test_set_step(2); + { + p1 = chHeapAlloc(NULL, (size_t)-256); + test_assert(p1 == NULL, "allocation not failed"); + } +} + +static const testcase_t rt_test_011_002 = { + "Default Heap", + NULL, + NULL, + rt_test_011_002_execute +}; + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Memory Heaps. + */ +const testcase_t * const rt_test_sequence_011[] = { + &rt_test_011_001, + &rt_test_011_002, + NULL +}; + +#endif /* CH_CFG_USE_HEAP */ diff --git a/test/rt/source/test/rt_test_sequence_011.h b/test/rt/source/test/rt_test_sequence_011.h new file mode 100644 index 000000000..2fc129c72 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_011.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_011.h + * @brief Test Sequence 011 header. + */ + +#ifndef RT_TEST_SEQUENCE_011_H +#define RT_TEST_SEQUENCE_011_H + +extern const testcase_t * const rt_test_sequence_011[]; + +#endif /* RT_TEST_SEQUENCE_011_H */ diff --git a/test/rt/source/test/rt_test_sequence_012.c b/test/rt/source/test/rt_test_sequence_012.c new file mode 100644 index 000000000..fd426002b --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_012.c @@ -0,0 +1,284 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_012.c + * @brief Test Sequence 012 code. + * + * @page rt_test_sequence_012 [12] Dynamic threads + * + * File: @ref rt_test_sequence_012.c + * + *

Description

+ * This module implements the test sequence for the dynamic thread + * creation APIs. + * + *

Conditions

+ * This sequence is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_DYNAMIC + * . + * + *

Test Cases

+ * - @subpage rt_test_012_001 + * - @subpage rt_test_012_002 + * . + */ + +#if (CH_CFG_USE_DYNAMIC) || defined(__DOXYGEN__) + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +#if CH_CFG_USE_HEAP +static memory_heap_t heap1; +#endif +#if CH_CFG_USE_MEMPOOLS +static memory_pool_t mp1; +#endif + +static THD_FUNCTION(dyn_thread1, p) { + + test_emit_token(*(char *)p); +} + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) +/** + * @page rt_test_012_001 [12.1] Threads creation from Memory Heap + * + *

Description

+ * Two threads are started by allocating the memory from the Memory + * Heap then a third thread is started with a huge stack + * requirement.
The test expects the first two threads to + * successfully start and the third one to fail. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_HEAP + * . + * + *

Test Steps

+ * - [12.1.1] Getting base priority for threads. + * - [12.1.2] Getting heap info before the test. + * - [12.1.3] Creating thread 1, it is expected to succeed. + * - [12.1.4] Creating thread 2, it is expected to succeed. + * - [12.1.5] Creating thread 3, it is expected to fail. + * - [12.1.6] Letting threads execute then checking the start order and + * freeing memory. + * - [12.1.7] Getting heap info again for verification. + * . + */ + +static void rt_test_012_001_setup(void) { + chHeapObjectInit(&heap1, test_buffer, sizeof test_buffer); +} + +static void rt_test_012_001_execute(void) { + size_t n1, total1, largest1; + size_t n2, total2, largest2; + tprio_t prio; + + /* [12.1.1] Getting base priority for threads.*/ + test_set_step(1); + { + prio = chThdGetPriorityX(); + } + + /* [12.1.2] Getting heap info before the test.*/ + test_set_step(2); + { + n1 = chHeapStatus(&heap1, &total1, &largest1); + test_assert(n1 == 1, "heap fragmented"); + } + + /* [12.1.3] Creating thread 1, it is expected to succeed.*/ + test_set_step(3); + { + threads[0] = chThdCreateFromHeap(&heap1, + THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), + "dyn1", + prio-1, dyn_thread1, "A"); + test_assert(threads[0] != NULL, "thread creation failed"); + } + + /* [12.1.4] Creating thread 2, it is expected to succeed.*/ + test_set_step(4); + { + threads[1] = chThdCreateFromHeap(&heap1, + THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), + "dyn2", + prio-2, dyn_thread1, "B"); + test_assert(threads[1] != NULL, "thread creation failed"); + } + + /* [12.1.5] Creating thread 3, it is expected to fail.*/ + test_set_step(5); + { + threads[2] = chThdCreateFromHeap(&heap1, + THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE * 1024), + "dyn3", + prio-3, dyn_thread1, "C"); + test_assert(threads[2] == NULL, "thread creation not failed"); + } + + /* [12.1.6] Letting threads execute then checking the start order and + freeing memory.*/ + test_set_step(6); + { + test_wait_threads(); + test_assert_sequence("AB", "invalid sequence"); + } + + /* [12.1.7] Getting heap info again for verification.*/ + test_set_step(7); + { + n2 = chHeapStatus(&heap1, &total2, &largest2); + test_assert(n1 == n2, "fragmentation changed"); + test_assert(total1 == total2, "total free space changed"); + test_assert(largest1 == largest2, "largest fragment size changed"); + } +} + +static const testcase_t rt_test_012_001 = { + "Threads creation from Memory Heap", + rt_test_012_001_setup, + NULL, + rt_test_012_001_execute +}; +#endif /* CH_CFG_USE_HEAP */ + +#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) +/** + * @page rt_test_012_002 [12.2] Threads creation from Memory Pool + * + *

Description

+ * Five thread creation are attempted from a pool containing only four + * elements.
The test expects the first four threads to + * successfully start and the last one to fail. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MEMPOOLS + * . + * + *

Test Steps

+ * - [12.2.1] Adding four working areas to the pool. + * - [12.2.2] Getting base priority for threads. + * - [12.2.3] Creating the five threads. + * - [12.2.4] Testing that only the fifth thread creation failed. + * - [12.2.5] Letting them run, free the memory then checking the + * execution sequence. + * - [12.2.6] Testing that the pool contains four elements again. + * . + */ + +static void rt_test_012_002_setup(void) { + chPoolObjectInit(&mp1, THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), NULL); +} + +static void rt_test_012_002_execute(void) { + unsigned i; + tprio_t prio; + + /* [12.2.1] Adding four working areas to the pool.*/ + test_set_step(1); + { + for (i = 0; i < 4; i++) + chPoolFree(&mp1, wa[i]); + } + + /* [12.2.2] Getting base priority for threads.*/ + test_set_step(2); + { + prio = chThdGetPriorityX(); + } + + /* [12.2.3] Creating the five threads.*/ + test_set_step(3); + { + threads[0] = chThdCreateFromMemoryPool(&mp1, "dyn1", prio-1, dyn_thread1, "A"); + threads[1] = chThdCreateFromMemoryPool(&mp1, "dyn2", prio-2, dyn_thread1, "B"); + threads[2] = chThdCreateFromMemoryPool(&mp1, "dyn3", prio-3, dyn_thread1, "C"); + threads[3] = chThdCreateFromMemoryPool(&mp1, "dyn4", prio-4, dyn_thread1, "D"); + threads[4] = chThdCreateFromMemoryPool(&mp1, "dyn5", prio-5, dyn_thread1, "E"); + } + + /* [12.2.4] Testing that only the fifth thread creation failed.*/ + test_set_step(4); + { + test_assert((threads[0] != NULL) && + (threads[1] != NULL) && + (threads[2] != NULL) && + (threads[3] != NULL), + "thread creation failed"); + test_assert(threads[4] == NULL, + "thread creation not failed"); + } + + /* [12.2.5] Letting them run, free the memory then checking the + execution sequence.*/ + test_set_step(5); + { + test_wait_threads(); + test_assert_sequence("ABCD", "invalid sequence"); + } + + /* [12.2.6] Testing that the pool contains four elements again.*/ + test_set_step(6); + { + for (i = 0; i < 4; i++) + test_assert(chPoolAlloc(&mp1) != NULL, "pool list empty"); + test_assert(chPoolAlloc(&mp1) == NULL, "pool list not empty"); + } +} + +static const testcase_t rt_test_012_002 = { + "Threads creation from Memory Pool", + rt_test_012_002_setup, + NULL, + rt_test_012_002_execute +}; +#endif /* CH_CFG_USE_MEMPOOLS */ + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Dynamic threads. + */ +const testcase_t * const rt_test_sequence_012[] = { +#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) + &rt_test_012_001, +#endif +#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) + &rt_test_012_002, +#endif + NULL +}; + +#endif /* CH_CFG_USE_DYNAMIC */ diff --git a/test/rt/source/test/rt_test_sequence_012.h b/test/rt/source/test/rt_test_sequence_012.h new file mode 100644 index 000000000..204e4e833 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_012.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_012.h + * @brief Test Sequence 012 header. + */ + +#ifndef RT_TEST_SEQUENCE_012_H +#define RT_TEST_SEQUENCE_012_H + +extern const testcase_t * const rt_test_sequence_012[]; + +#endif /* RT_TEST_SEQUENCE_012_H */ diff --git a/test/rt/source/test/rt_test_sequence_013.c b/test/rt/source/test/rt_test_sequence_013.c new file mode 100644 index 000000000..5b413a338 --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_013.c @@ -0,0 +1,1031 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" +#include "ch_test.h" +#include "rt_test_root.h" + +/** + * @file rt_test_sequence_013.c + * @brief Test Sequence 013 code. + * + * @page rt_test_sequence_013 [13] Benchmarks + * + * File: @ref rt_test_sequence_013.c + * + *

Description

+ * This module implements a series of system benchmarks. The benchmarks + * are useful as a stress test and as a reference when comparing + * ChibiOS/RT with similar systems.
Objective of the test sequence + * is to provide a performance index for the most critical system + * subsystems. The performance numbers allow to discover performance + * regressions between successive ChibiOS/RT releases. + * + *

Test Cases

+ * - @subpage rt_test_013_001 + * - @subpage rt_test_013_002 + * - @subpage rt_test_013_003 + * - @subpage rt_test_013_004 + * - @subpage rt_test_013_005 + * - @subpage rt_test_013_006 + * - @subpage rt_test_013_007 + * - @subpage rt_test_013_008 + * - @subpage rt_test_013_009 + * - @subpage rt_test_013_010 + * - @subpage rt_test_013_011 + * - @subpage rt_test_013_012 + * . + */ + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + +#if CH_CFG_USE_SEMAPHORES || defined(__DOXYGEN__) +static semaphore_t sem1; +#endif +#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__) +static mutex_t mtx1; +#endif + +static void tmo(void *param) {(void)param;} + +#if CH_CFG_USE_MESSAGES +static THD_FUNCTION(bmk_thread1, p) { + thread_t *tp; + msg_t msg; + + (void)p; + do { + tp = chMsgWait(); + msg = chMsgGet(tp); + chMsgRelease(tp, msg); + } while (msg); +} + +NOINLINE static unsigned int msg_loop_test(thread_t *tp) { + systime_t start, end; + + uint32_t n = 0; + start = test_wait_tick(); + end = start + TIME_MS2I(1000); + do { + (void)chMsgSend(tp, 1); + n++; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while (chVTIsSystemTimeWithinX(start, end)); + (void)chMsgSend(tp, 0); + return n; +} +#endif + +static THD_FUNCTION(bmk_thread3, p) { + + chThdExit((msg_t)p); +} + +static THD_FUNCTION(bmk_thread4, p) { + msg_t msg; + thread_t *self = chThdGetSelfX(); + + (void)p; + chSysLock(); + do { + chSchGoSleepS(CH_STATE_SUSPENDED); + msg = self->u.rdymsg; + } while (msg == MSG_OK); + chSysUnlock(); +} + +#if CH_CFG_USE_SEMAPHORES +static THD_FUNCTION(bmk_thread7, p) { + + (void)p; + while (!chThdShouldTerminateX()) + chSemWait(&sem1); +} +#endif + +static THD_FUNCTION(bmk_thread8, p) { + + do { + chThdYield(); + chThdYield(); + chThdYield(); + chThdYield(); + (*(uint32_t *)p) += 4; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while(!chThdShouldTerminateX()); +} + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) +/** + * @page rt_test_013_001 [13.1] Messages performance #1 + * + *

Description

+ * A message server thread is created with a lower priority than the + * client thread, the messages throughput per second is measured and + * the result printed on the output log. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MESSAGES + * . + * + *

Test Steps

+ * - [13.1.1] The messenger thread is started at a lower priority than + * the current thread. + * - [13.1.2] The number of messages exchanged is counted in a one + * second time window. + * - [13.1.3] Score is printed. + * . + */ + +static void rt_test_013_001_execute(void) { + uint32_t n; + + /* [13.1.1] The messenger thread is started at a lower priority than + the current thread.*/ + test_set_step(1); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-1, bmk_thread1, NULL); + } + + /* [13.1.2] The number of messages exchanged is counted in a one + second time window.*/ + test_set_step(2); + { + n = msg_loop_test(threads[0]); + test_wait_threads(); + } + + /* [13.1.3] Score is printed.*/ + test_set_step(3); + { + test_print("--- Score : "); + test_printn(n); + test_print(" msgs/S, "); + test_printn(n << 1); + test_println(" ctxswc/S"); + } +} + +static const testcase_t rt_test_013_001 = { + "Messages performance #1", + NULL, + NULL, + rt_test_013_001_execute +}; +#endif /* CH_CFG_USE_MESSAGES */ + +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) +/** + * @page rt_test_013_002 [13.2] Messages performance #2 + * + *

Description

+ * A message server thread is created with an higher priority than the + * client thread, the messages throughput per second is measured and + * the result printed on the output log. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MESSAGES + * . + * + *

Test Steps

+ * - [13.2.1] The messenger thread is started at an higher priority + * than the current thread. + * - [13.2.2] The number of messages exchanged is counted in a one + * second time window. + * - [13.2.3] Score is printed. + * . + */ + +static void rt_test_013_002_execute(void) { + uint32_t n; + + /* [13.2.1] The messenger thread is started at an higher priority + than the current thread.*/ + test_set_step(1); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, bmk_thread1, NULL); + } + + /* [13.2.2] The number of messages exchanged is counted in a one + second time window.*/ + test_set_step(2); + { + n = msg_loop_test(threads[0]); + test_wait_threads(); + } + + /* [13.2.3] Score is printed.*/ + test_set_step(3); + { + test_print("--- Score : "); + test_printn(n); + test_print(" msgs/S, "); + test_printn(n << 1); + test_println(" ctxswc/S"); + } +} + +static const testcase_t rt_test_013_002 = { + "Messages performance #2", + NULL, + NULL, + rt_test_013_002_execute +}; +#endif /* CH_CFG_USE_MESSAGES */ + +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) +/** + * @page rt_test_013_003 [13.3] Messages performance #3 + * + *

Description

+ * A message server thread is created with an higher priority than the + * client thread, four lower priority threads crowd the ready list, the + * messages throughput per second is measured while the ready list and + * the result printed on the output log. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MESSAGES + * . + * + *

Test Steps

+ * - [13.3.1] The messenger thread is started at an higher priority + * than the current thread. + * - [13.3.2] Four threads are started at a lower priority than the + * current thread. + * - [13.3.3] The number of messages exchanged is counted in a one + * second time window. + * - [13.3.4] Score is printed. + * . + */ + +static void rt_test_013_003_execute(void) { + uint32_t n; + + /* [13.3.1] The messenger thread is started at an higher priority + than the current thread.*/ + test_set_step(1); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, bmk_thread1, NULL); + } + + /* [13.3.2] Four threads are started at a lower priority than the + current thread.*/ + test_set_step(2); + { + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-2, bmk_thread3, NULL); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, bmk_thread3, NULL); + threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-4, bmk_thread3, NULL); + threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-5, bmk_thread3, NULL); + } + + /* [13.3.3] The number of messages exchanged is counted in a one + second time window.*/ + test_set_step(3); + { + n = msg_loop_test(threads[0]); + test_wait_threads(); + } + + /* [13.3.4] Score is printed.*/ + test_set_step(4); + { + test_print("--- Score : "); + test_printn(n); + test_print(" msgs/S, "); + test_printn(n << 1); + test_println(" ctxswc/S"); + } +} + +static const testcase_t rt_test_013_003 = { + "Messages performance #3", + NULL, + NULL, + rt_test_013_003_execute +}; +#endif /* CH_CFG_USE_MESSAGES */ + +/** + * @page rt_test_013_004 [13.4] Context Switch performance + * + *

Description

+ * A thread is created that just performs a @p chSchGoSleepS() into a + * loop, the thread is awakened as fast is possible by the tester + * thread.
The Context Switch performance is calculated by + * measuring the number of iterations after a second of continuous + * operations. + * + *

Test Steps

+ * - [13.4.1] Starting the target thread at an higher priority level. + * - [13.4.2] Waking up the thread as fast as possible in a one second + * time window. + * - [13.4.3] Stopping the target thread. + * - [13.4.4] Score is printed. + * . + */ + +static void rt_test_013_004_execute(void) { + thread_t *tp; + uint32_t n; + + /* [13.4.1] Starting the target thread at an higher priority level.*/ + test_set_step(1); + { + tp = threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, + bmk_thread4, NULL); + } + + /* [13.4.2] Waking up the thread as fast as possible in a one second + time window.*/ + test_set_step(2); + { + systime_t start, end; + + n = 0; + start = test_wait_tick(); + end = start + TIME_MS2I(1000); + do { + chSysLock(); + chSchWakeupS(tp, MSG_OK); + chSchWakeupS(tp, MSG_OK); + chSchWakeupS(tp, MSG_OK); + chSchWakeupS(tp, MSG_OK); + chSysUnlock(); + n += 4; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while (chVTIsSystemTimeWithinX(start, end)); + } + + /* [13.4.3] Stopping the target thread.*/ + test_set_step(3); + { + chSysLock(); + chSchWakeupS(tp, MSG_TIMEOUT); + chSysUnlock(); + test_wait_threads(); + } + + /* [13.4.4] Score is printed.*/ + test_set_step(4); + { + test_print("--- Score : "); + test_printn(n * 2); + test_println(" ctxswc/S"); + } +} + +static const testcase_t rt_test_013_004 = { + "Context Switch performance", + NULL, + NULL, + rt_test_013_004_execute +}; + +/** + * @page rt_test_013_005 [13.5] Threads performance, full cycle + * + *

Description

+ * Threads are continuously created and terminated into a loop. A full + * chThdCreateStatic() / @p chThdExit() / @p chThdWait() cycle is + * performed in each iteration.
The performance is calculated by + * measuring the number of iterations after a second of continuous + * operations. + * + *

Test Steps

+ * - [13.5.1] A thread is created at a lower priority level and its + * termination detected using @p chThdWait(). The operation is + * repeated continuously in a one-second time window. + * - [13.5.2] Score is printed. + * . + */ + +static void rt_test_013_005_execute(void) { + uint32_t n; + tprio_t prio = chThdGetPriorityX() - 1; + systime_t start, end; + + /* [13.5.1] A thread is created at a lower priority level and its + termination detected using @p chThdWait(). The operation is + repeated continuously in a one-second time window.*/ + test_set_step(1); + { + n = 0; + start = test_wait_tick(); + end = start + TIME_MS2I(1000); + do { + chThdWait(chThdCreateStatic(wa[0], WA_SIZE, prio, bmk_thread3, NULL)); + n++; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while (chVTIsSystemTimeWithinX(start, end)); + } + + /* [13.5.2] Score is printed.*/ + test_set_step(2); + { + test_print("--- Score : "); + test_printn(n); + test_println(" threads/S"); + } +} + +static const testcase_t rt_test_013_005 = { + "Threads performance, full cycle", + NULL, + NULL, + rt_test_013_005_execute +}; + +/** + * @page rt_test_013_006 [13.6] Threads performance, create/exit only + * + *

Description

+ * Threads are continuously created and terminated into a loop. A + * partial @p chThdCreateStatic() / @p chThdExit() cycle is performed + * in each iteration, the @p chThdWait() is not necessary because the + * thread is created at an higher priority so there is no need to wait + * for it to terminate.
The performance is calculated by measuring + * the number of iterations after a second of continuous operations. + * + *

Test Steps

+ * - [13.6.1] A thread is created at an higher priority level and let + * terminate immediately. The operation is repeated continuously in a + * one-second time window. + * - [13.6.2] Score is printed. + * . + */ + +static void rt_test_013_006_execute(void) { + uint32_t n; + tprio_t prio = chThdGetPriorityX() + 1; + systime_t start, end; + + /* [13.6.1] A thread is created at an higher priority level and let + terminate immediately. The operation is repeated continuously in a + one-second time window.*/ + test_set_step(1); + { + n = 0; + start = test_wait_tick(); + end = start + TIME_MS2I(1000); + do { +#if CH_CFG_USE_REGISTRY + chThdRelease(chThdCreateStatic(wa[0], WA_SIZE, prio, bmk_thread3, NULL)); +#else + chThdCreateStatic(wa[0], WA_SIZE, prio, bmk_thread3, NULL); +#endif + n++; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while (chVTIsSystemTimeWithinX(start, end)); + } + + /* [13.6.2] Score is printed.*/ + test_set_step(2); + { + test_print("--- Score : "); + test_printn(n); + test_println(" threads/S"); + } +} + +static const testcase_t rt_test_013_006 = { + "Threads performance, create/exit only", + NULL, + NULL, + rt_test_013_006_execute +}; + +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) +/** + * @page rt_test_013_007 [13.7] Mass reschedule performance + * + *

Description

+ * Five threads are created and atomically rescheduled by resetting the + * semaphore where they are waiting on. The operation is performed into + * a continuous loop.
The performance is calculated by measuring + * the number of iterations after a second of continuous operations. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_SEMAPHORES + * . + * + *

Test Steps

+ * - [13.7.1] Five threads are created at higher priority that + * immediately enqueue on a semaphore. + * - [13.7.2] The semaphore is reset waking up the five threads. The + * operation is repeated continuously in a one-second time window. + * - [13.7.3] The five threads are terminated. + * - [13.7.4] The score is printed. + * . + */ + +static void rt_test_013_007_setup(void) { + chSemObjectInit(&sem1, 0); +} + +static void rt_test_013_007_execute(void) { + uint32_t n; + + /* [13.7.1] Five threads are created at higher priority that + immediately enqueue on a semaphore.*/ + test_set_step(1); + { + threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+5, bmk_thread7, NULL); + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()+4, bmk_thread7, NULL); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()+3, bmk_thread7, NULL); + threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()+2, bmk_thread7, NULL); + threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()+1, bmk_thread7, NULL); + } + + /* [13.7.2] The semaphore is reset waking up the five threads. The + operation is repeated continuously in a one-second time window.*/ + test_set_step(2); + { + systime_t start, end; + + n = 0; + start = test_wait_tick(); + end = start + TIME_MS2I(1000); + do { + chSemReset(&sem1, 0); + n++; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while (chVTIsSystemTimeWithinX(start, end)); + } + + /* [13.7.3] The five threads are terminated.*/ + test_set_step(3); + { + test_terminate_threads(); + chSemReset(&sem1, 0); + test_wait_threads(); + } + + /* [13.7.4] The score is printed.*/ + test_set_step(4); + { + test_print("--- Score : "); + test_printn(n); + test_print(" reschedules/S, "); + test_printn(n * 6); + test_println(" ctxswc/S"); + } +} + +static const testcase_t rt_test_013_007 = { + "Mass reschedule performance", + rt_test_013_007_setup, + NULL, + rt_test_013_007_execute +}; +#endif /* CH_CFG_USE_SEMAPHORES */ + +/** + * @page rt_test_013_008 [13.8] Round-Robin voluntary reschedule + * + *

Description

+ * Five threads are created at equal priority, each thread just + * increases a variable and yields.
The performance is calculated + * by measuring the number of iterations after a second of continuous + * operations. + * + *

Test Steps

+ * - [13.8.1] The five threads are created at lower priority. The + * threds have equal priority and start calling @p chThdYield() + * continuously. + * - [13.8.2] Waiting one second then terminating the 5 threads. + * - [13.8.3] The score is printed. + * . + */ + +static void rt_test_013_008_execute(void) { + uint32_t n; + + /* [13.8.1] The five threads are created at lower priority. The + threds have equal priority and start calling @p chThdYield() + continuously.*/ + test_set_step(1); + { + n = 0; + test_wait_tick();threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-1, bmk_thread8, (void *)&n); + + threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-1, bmk_thread8, (void *)&n); + threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-1, bmk_thread8, (void *)&n); + threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-1, bmk_thread8, (void *)&n); + threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, bmk_thread8, (void *)&n); + } + + /* [13.8.2] Waiting one second then terminating the 5 threads.*/ + test_set_step(2); + { + chThdSleepSeconds(1); + test_terminate_threads(); + test_wait_threads(); + } + + /* [13.8.3] The score is printed.*/ + test_set_step(3); + { + test_print("--- Score : "); + test_printn(n); + test_println(" ctxswc/S"); + } +} + +static const testcase_t rt_test_013_008 = { + "Round-Robin voluntary reschedule", + NULL, + NULL, + rt_test_013_008_execute +}; + +/** + * @page rt_test_013_009 [13.9] Virtual Timers set/reset performance + * + *

Description

+ * A virtual timer is set and immediately reset into a continuous + * loop.
The performance is calculated by measuring the number of + * iterations after a second of continuous operations. + * + *

Test Steps

+ * - [13.9.1] Two timers are set then reset without waiting for their + * counter to elapse. The operation is repeated continuously in a + * one-second time window. + * - [13.9.2] The score is printed. + * . + */ + +static void rt_test_013_009_execute(void) { + static virtual_timer_t vt1, vt2; + uint32_t n; + + /* [13.9.1] Two timers are set then reset without waiting for their + counter to elapse. The operation is repeated continuously in a + one-second time window.*/ + test_set_step(1); + { + systime_t start, end; + + n = 0; + start = test_wait_tick(); + end = start + TIME_MS2I(1000); + do { + chSysLock(); + chVTDoSetI(&vt1, 1, tmo, NULL); + chVTDoSetI(&vt2, 10000, tmo, NULL); + chVTDoResetI(&vt1); + chVTDoResetI(&vt2); + chSysUnlock(); + n++; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while (chVTIsSystemTimeWithinX(start, end)); + } + + /* [13.9.2] The score is printed.*/ + test_set_step(2); + { + test_print("--- Score : "); + test_printn(n * 2); + test_println(" timers/S"); + } +} + +static const testcase_t rt_test_013_009 = { + "Virtual Timers set/reset performance", + NULL, + NULL, + rt_test_013_009_execute +}; + +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) +/** + * @page rt_test_013_010 [13.10] Semaphores wait/signal performance + * + *

Description

+ * A counting semaphore is taken/released into a continuous loop, no + * Context Switch happens because the counter is always non + * negative.
The performance is calculated by measuring the number + * of iterations after a second of continuous operations. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_SEMAPHORES + * . + * + *

Test Steps

+ * - [13.10.1] A semaphore is teken and released. The operation is + * repeated continuously in a one-second time window. + * - [13.10.2] The score is printed. + * . + */ + +static void rt_test_013_010_setup(void) { + chSemObjectInit(&sem1, 1); +} + +static void rt_test_013_010_execute(void) { + uint32_t n; + + /* [13.10.1] A semaphore is teken and released. The operation is + repeated continuously in a one-second time window.*/ + test_set_step(1); + { + systime_t start, end; + + n = 0; + start = test_wait_tick(); + end = start + TIME_MS2I(1000); + do { + chSemWait(&sem1); + chSemSignal(&sem1); + chSemWait(&sem1); + chSemSignal(&sem1); + chSemWait(&sem1); + chSemSignal(&sem1); + chSemWait(&sem1); + chSemSignal(&sem1); + n++; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while (chVTIsSystemTimeWithinX(start, end)); + } + + /* [13.10.2] The score is printed.*/ + test_set_step(2); + { + test_print("--- Score : "); + test_printn(n * 4); + test_println(" wait+signal/S"); + } +} + +static const testcase_t rt_test_013_010 = { + "Semaphores wait/signal performance", + rt_test_013_010_setup, + NULL, + rt_test_013_010_execute +}; +#endif /* CH_CFG_USE_SEMAPHORES */ + +#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) +/** + * @page rt_test_013_011 [13.11] Mutexes lock/unlock performance + * + *

Description

+ * A mutex is locked/unlocked into a continuous loop, no Context Switch + * happens because there are no other threads asking for the mutex.
+ * The performance is calculated by measuring the number of iterations + * after a second of continuous operations. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MUTEXES + * . + * + *

Test Steps

+ * - [13.11.1] A mutex is locked and unlocked. The operation is + * repeated continuously in a one-second time window. + * - [13.11.2] The score is printed. + * . + */ + +static void rt_test_013_011_setup(void) { + chMtxObjectInit(&mtx1); +} + +static void rt_test_013_011_execute(void) { + uint32_t n; + + /* [13.11.1] A mutex is locked and unlocked. The operation is + repeated continuously in a one-second time window.*/ + test_set_step(1); + { + systime_t start, end; + + n = 0; + start = test_wait_tick(); + end = start + TIME_MS2I(1000); + do { + chMtxLock(&mtx1); + chMtxUnlock(&mtx1); + chMtxLock(&mtx1); + chMtxUnlock(&mtx1); + chMtxLock(&mtx1); + chMtxUnlock(&mtx1); + chMtxLock(&mtx1); + chMtxUnlock(&mtx1); + n++; +#if defined(SIMULATOR) + _sim_check_for_interrupts(); +#endif + } while (chVTIsSystemTimeWithinX(start, end)); + } + + /* [13.11.2] The score is printed.*/ + test_set_step(2); + { + test_print("--- Score : "); + test_printn(n * 4); + test_println(" lock+unlock/S"); + } +} + +static const testcase_t rt_test_013_011 = { + "Mutexes lock/unlock performance", + rt_test_013_011_setup, + NULL, + rt_test_013_011_execute +}; +#endif /* CH_CFG_USE_MUTEXES */ + +/** + * @page rt_test_013_012 [13.12] RAM Footprint + * + *

Description

+ * The memory size of the various kernel objects is printed. + * + *

Test Steps

+ * - [13.12.1] The size of the system area is printed. + * - [13.12.2] The size of a thread structure is printed. + * - [13.12.3] The size of a virtual timer structure is printed. + * - [13.12.4] The size of a semaphore structure is printed. + * - [13.12.5] The size of a mutex is printed. + * - [13.12.6] The size of a condition variable is printed. + * - [13.12.7] The size of an event source is printed. + * - [13.12.8] The size of an event listener is printed. + * - [13.12.9] The size of a mailbox is printed. + * . + */ + +static void rt_test_013_012_execute(void) { + + /* [13.12.1] The size of the system area is printed.*/ + test_set_step(1); + { + test_print("--- System: "); + test_printn(sizeof(ch_system_t)); + test_println(" bytes"); + } + + /* [13.12.2] The size of a thread structure is printed.*/ + test_set_step(2); + { + test_print("--- Thread: "); + test_printn(sizeof(thread_t)); + test_println(" bytes"); + } + + /* [13.12.3] The size of a virtual timer structure is printed.*/ + test_set_step(3); + { + test_print("--- Timer : "); + test_printn(sizeof(virtual_timer_t)); + test_println(" bytes"); + } + + /* [13.12.4] The size of a semaphore structure is printed.*/ + test_set_step(4); + { +#if CH_CFG_USE_SEMAPHORES || defined(__DOXYGEN__) + test_print("--- Semaph: "); + test_printn(sizeof(semaphore_t)); + test_println(" bytes"); +#endif + } + + /* [13.12.5] The size of a mutex is printed.*/ + test_set_step(5); + { +#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__) + test_print("--- Mutex : "); + test_printn(sizeof(mutex_t)); + test_println(" bytes"); +#endif + } + + /* [13.12.6] The size of a condition variable is printed.*/ + test_set_step(6); + { +#if CH_CFG_USE_CONDVARS || defined(__DOXYGEN__) + test_print("--- CondV.: "); + test_printn(sizeof(condition_variable_t)); + test_println(" bytes"); +#endif + } + + /* [13.12.7] The size of an event source is printed.*/ + test_set_step(7); + { +#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__) + test_print("--- EventS: "); + test_printn(sizeof(event_source_t)); + test_println(" bytes"); +#endif + } + + /* [13.12.8] The size of an event listener is printed.*/ + test_set_step(8); + { +#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__) + test_print("--- EventL: "); + test_printn(sizeof(event_listener_t)); + test_println(" bytes"); +#endif + } + + /* [13.12.9] The size of a mailbox is printed.*/ + test_set_step(9); + { +#if CH_CFG_USE_MAILBOXES || defined(__DOXYGEN__) + test_print("--- MailB.: "); + test_printn(sizeof(mailbox_t)); + test_println(" bytes"); +#endif + } +} + +static const testcase_t rt_test_013_012 = { + "RAM Footprint", + NULL, + NULL, + rt_test_013_012_execute +}; + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Benchmarks. + */ +const testcase_t * const rt_test_sequence_013[] = { +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) + &rt_test_013_001, +#endif +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) + &rt_test_013_002, +#endif +#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) + &rt_test_013_003, +#endif + &rt_test_013_004, + &rt_test_013_005, + &rt_test_013_006, +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) + &rt_test_013_007, +#endif + &rt_test_013_008, + &rt_test_013_009, +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) + &rt_test_013_010, +#endif +#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) + &rt_test_013_011, +#endif + &rt_test_013_012, + NULL +}; diff --git a/test/rt/source/test/rt_test_sequence_013.h b/test/rt/source/test/rt_test_sequence_013.h new file mode 100644 index 000000000..7171c09ad --- /dev/null +++ b/test/rt/source/test/rt_test_sequence_013.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file rt_test_sequence_013.h + * @brief Test Sequence 013 header. + */ + +#ifndef RT_TEST_SEQUENCE_013_H +#define RT_TEST_SEQUENCE_013_H + +extern const testcase_t * const rt_test_sequence_013[]; + +#endif /* RT_TEST_SEQUENCE_013_H */ diff --git a/test/rt/source/test/test_root.c b/test/rt/source/test/test_root.c deleted file mode 100644 index 9e37e78be..000000000 --- a/test/rt/source/test/test_root.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @mainpage Test Suite Specification - * Test suite for ChibiOS/RT. The purpose of this suite is to perform - * unit tests on the RT modules and to converge to 100% code coverage - * through successive improvements. - * - *

Test Sequences

- * - @subpage test_sequence_001 - * - @subpage test_sequence_002 - * - @subpage test_sequence_003 - * - @subpage test_sequence_004 - * - @subpage test_sequence_005 - * - @subpage test_sequence_006 - * - @subpage test_sequence_007 - * - @subpage test_sequence_008 - * - @subpage test_sequence_009 - * - @subpage test_sequence_010 - * - @subpage test_sequence_011 - * - @subpage test_sequence_012 - * - @subpage test_sequence_013 - * . - */ - -/** - * @file test_root.c - * @brief Test Suite root structures code. - */ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -#if !defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/** - * @brief Array of all the test sequences. - */ -const testcase_t * const *test_suite[] = { - test_sequence_001, - test_sequence_002, - test_sequence_003, - test_sequence_004, -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) - test_sequence_005, -#endif -#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) - test_sequence_006, -#endif -#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) - test_sequence_007, -#endif -#if (CH_CFG_USE_EVENTS) || defined(__DOXYGEN__) - test_sequence_008, -#endif -#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__) - test_sequence_009, -#endif -#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) - test_sequence_010, -#endif -#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) - test_sequence_011, -#endif -#if (CH_CFG_USE_DYNAMIC) || defined(__DOXYGEN__) - test_sequence_012, -#endif - test_sequence_013, - NULL -}; - -/*===========================================================================*/ -/* Shared code. */ -/*===========================================================================*/ - -void test_print_port_info(void) { - -#ifdef PORT_COMPILER_NAME - test_print("*** Compiler: "); - test_println(PORT_COMPILER_NAME); -#endif - test_print("*** Architecture: "); - test_println(PORT_ARCHITECTURE_NAME); -#ifdef PORT_CORE_VARIANT_NAME - test_print("*** Core Variant: "); - test_println(PORT_CORE_VARIANT_NAME); -#endif -#ifdef PORT_INFO - test_print("*** Port Info: "); - test_println(PORT_INFO); -#endif -} - -/* - * Global test buffer holding 5 working areas. - */ -ALIGNED_VAR(PORT_WORKING_AREA_ALIGN) uint8_t test_buffer[WA_SIZE * 5]; - -/* - * Pointers to the spawned threads. - */ -thread_t *threads[MAX_THREADS]; - -/* - * Pointers to the working areas. - */ -void * ROMCONST wa[5] = {test_buffer + (WA_SIZE * 0), - test_buffer + (WA_SIZE * 1), - test_buffer + (WA_SIZE * 2), - test_buffer + (WA_SIZE * 3), - test_buffer + (WA_SIZE * 4)}; - -/* - * Sets a termination request in all the test-spawned threads. - */ -void test_terminate_threads(void) { - unsigned i; - - for (i = 0; i < MAX_THREADS; i++) - if (threads[i]) - chThdTerminate(threads[i]); -} - -/* - * Waits for the completion of all the test-spawned threads. - */ -void test_wait_threads(void) { - unsigned i; - - for (i = 0; i < MAX_THREADS; i++) - if (threads[i] != NULL) { - chThdWait(threads[i]); - threads[i] = NULL; - } -} - -/* - * Delays execution until next system time tick. - */ -systime_t test_wait_tick(void) { - - chThdSleep(1); - return chVTGetSystemTime(); -} - -#endif /* !defined(__DOXYGEN__) */ diff --git a/test/rt/source/test/test_root.h b/test/rt/source/test/test_root.h deleted file mode 100644 index fd0f32772..000000000 --- a/test/rt/source/test/test_root.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_root.h - * @brief Test Suite root structures header. - */ - -#ifndef TEST_ROOT_H -#define TEST_ROOT_H - -#include "test_sequence_001.h" -#include "test_sequence_002.h" -#include "test_sequence_003.h" -#include "test_sequence_004.h" -#include "test_sequence_005.h" -#include "test_sequence_006.h" -#include "test_sequence_007.h" -#include "test_sequence_008.h" -#include "test_sequence_009.h" -#include "test_sequence_010.h" -#include "test_sequence_011.h" -#include "test_sequence_012.h" -#include "test_sequence_013.h" - -#if !defined(__DOXYGEN__) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -extern const testcase_t * const *test_suite[]; - -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Shared definitions. */ -/*===========================================================================*/ - -#define TEST_SUITE_NAME "ChibiOS/RT Test Suite" - -/* - * Allowed delay in timeout checks. - */ -#define ALLOWED_DELAY MS2ST(2) - -/* - * Maximum number of test threads. - */ -#define MAX_THREADS 5 - -/* - * Stack size of test threads. - */ -#if defined(CH_ARCHITECTURE_AVR) || defined(CH_ARCHITECTURE_MSP430) -#define THREADS_STACK_SIZE 48 -#elif defined(CH_ARCHITECTURE_STM8) -#define THREADS_STACK_SIZE 64 -#elif defined(CH_ARCHITECTURE_SIMIA32) -#define THREADS_STACK_SIZE 512 -#else -#define THREADS_STACK_SIZE 128 -#endif - -/* - * Working Area size of test threads. - */ -#define WA_SIZE MEM_ALIGN_NEXT(THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), \ - PORT_WORKING_AREA_ALIGN) - -#define TEST_REPORT_HOOK_HEADER test_print_port_info(); - -extern uint8_t test_buffer[WA_SIZE * 5]; -extern thread_t *threads[MAX_THREADS]; -extern void * ROMCONST wa[5]; - -void test_print_port_info(void); -void test_terminate_threads(void); -void test_wait_threads(void); -systime_t test_wait_tick(void); - -#endif /* !defined(__DOXYGEN__) */ - -#endif /* TEST_ROOT_H */ diff --git a/test/rt/source/test/test_sequence_001.c b/test/rt/source/test/test_sequence_001.c deleted file mode 100644 index ce1396823..000000000 --- a/test/rt/source/test/test_sequence_001.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_001.c - * @brief Test Sequence 001 code. - * - * @page test_sequence_001 [1] Information - * - * File: @ref test_sequence_001.c - * - *

Description

- * This sequence reports configuration and version information about - * the RT kernel. - * - *

Test Cases

- * - @subpage test_001_001 - * - @subpage test_001_002 - * . - */ - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -#include "ch.h" - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -/** - * @page test_001_001 [1.1] Kernel Info - * - *

Description

- * The version numbers are reported. - * - *

Test Steps

- * - [1.1.1] Prints the version string. - * . - */ - -static void test_001_001_execute(void) { - - /* [1.1.1] Prints the version string.*/ - test_set_step(1); - { - test_println("--- Product: ChibiOS/RT"); - test_print("--- Stable Flag: "); - test_printn(CH_KERNEL_STABLE); - test_println(""); - test_print("--- Version String: "); - test_println(CH_KERNEL_VERSION); - test_print("--- Major Number: "); - test_printn(CH_KERNEL_MAJOR); - test_println(""); - test_print("--- Minor Number: "); - test_printn(CH_KERNEL_MINOR); - test_println(""); - test_print("--- Patch Number: "); - test_printn(CH_KERNEL_PATCH); - test_println(""); - } -} - -static const testcase_t test_001_001 = { - "Kernel Info", - NULL, - NULL, - test_001_001_execute -}; - -/** - * @page test_001_002 [1.2] Kernel Settings - * - *

Description

- * The static kernel settings are reported. - * - *

Test Steps

- * - [1.2.1] Prints the configuration options settings. - * . - */ - -static void test_001_002_execute(void) { - - /* [1.2.1] Prints the configuration options settings.*/ - test_set_step(1); - { - test_print("--- CH_CFG_ST_RESOLUTION: "); - test_printn(CH_CFG_ST_RESOLUTION); - test_println(""); - test_print("--- CH_CFG_ST_FREQUENCY: "); - test_printn(CH_CFG_ST_FREQUENCY); - test_println(""); - test_print("--- CH_CFG_ST_TIMEDELTA: "); - test_printn(CH_CFG_ST_TIMEDELTA); - test_println(""); - test_print("--- CH_CFG_TIME_QUANTUM: "); - test_printn(CH_CFG_TIME_QUANTUM); - test_println(""); - test_print("--- CH_CFG_MEMCORE_SIZE: "); - test_printn(CH_CFG_MEMCORE_SIZE); - test_println(""); - test_print("--- CH_CFG_NO_IDLE_THREAD: "); - test_printn(CH_CFG_NO_IDLE_THREAD); - test_println(""); - test_print("--- CH_CFG_OPTIMIZE_SPEED: "); - test_printn(CH_CFG_OPTIMIZE_SPEED); - test_println(""); - test_print("--- CH_CFG_USE_TM: "); - test_printn(CH_CFG_USE_TM); - test_println(""); - test_print("--- CH_CFG_USE_REGISTRY: "); - test_printn(CH_CFG_USE_REGISTRY); - test_println(""); - test_print("--- CH_CFG_USE_WAITEXIT: "); - test_printn(CH_CFG_USE_WAITEXIT); - test_println(""); - test_print("--- CH_CFG_USE_SEMAPHORES: "); - test_printn(CH_CFG_USE_SEMAPHORES); - test_println(""); - test_print("--- CH_CFG_USE_SEMAPHORES_PRI: "); - test_printn(CH_CFG_USE_SEMAPHORES_PRIORITY); - test_println(""); - test_print("--- CH_CFG_USE_MUTEXES: "); - test_printn(CH_CFG_USE_MUTEXES); - test_println(""); - test_print("--- CH_CFG_USE_MUTEXES_RECURS: "); - test_printn(CH_CFG_USE_MUTEXES_RECURSIVE); - test_println(""); - test_print("--- CH_CFG_USE_CONDVARS: "); - test_printn(CH_CFG_USE_CONDVARS); - test_println(""); - test_print("--- CH_CFG_USE_CONDVARS_TIMEO: "); - test_printn(CH_CFG_USE_CONDVARS_TIMEOUT); - test_println(""); - test_print("--- CH_CFG_USE_EVENTS: "); - test_printn(CH_CFG_USE_EVENTS); - test_println(""); - test_print("--- CH_CFG_USE_EVENTS_TIMEOUT: "); - test_printn(CH_CFG_USE_EVENTS_TIMEOUT); - test_println(""); - test_print("--- CH_CFG_USE_MESSAGES: "); - test_printn(CH_CFG_USE_MESSAGES); - test_println(""); - test_print("--- CH_CFG_USE_MESSAGES_PRI: "); - test_printn(CH_CFG_USE_MESSAGES_PRIORITY); - test_println(""); - test_print("--- CH_CFG_USE_MAILBOXES: "); - test_printn(CH_CFG_USE_MAILBOXES); - test_println(""); - test_print("--- CH_CFG_USE_MEMCORE: "); - test_printn(CH_CFG_USE_MEMCORE); - test_println(""); - test_print("--- CH_CFG_USE_HEAP: "); - test_printn(CH_CFG_USE_HEAP); - test_println(""); - test_print("--- CH_CFG_USE_MEMPOOLS: "); - test_printn(CH_CFG_USE_MEMPOOLS); - test_println(""); - test_print("--- CH_CFG_USE_DYNAMIC: "); - test_printn(CH_CFG_USE_DYNAMIC); - test_println(""); - test_print("--- CH_DBG_STATISTICS: "); - test_printn(CH_DBG_STATISTICS); - test_println(""); - test_print("--- CH_DBG_SYSTEM_STATE_CHECK: "); - test_printn(CH_DBG_SYSTEM_STATE_CHECK); - test_println(""); - test_print("--- CH_DBG_ENABLE_CHECKS: "); - test_printn(CH_DBG_ENABLE_CHECKS); - test_println(""); - test_print("--- CH_DBG_ENABLE_ASSERTS: "); - test_printn(CH_DBG_ENABLE_ASSERTS); - test_println(""); - test_print("--- CH_DBG_TRACE_MASK: "); - test_printn(CH_DBG_TRACE_MASK); - test_println(""); - test_print("--- CH_DBG_TRACE_BUFFER_SIZE: "); - test_printn(CH_DBG_TRACE_BUFFER_SIZE); - test_println(""); - test_print("--- CH_DBG_ENABLE_STACK_CHECK: "); - test_printn(CH_DBG_ENABLE_STACK_CHECK); - test_println(""); - test_print("--- CH_DBG_FILL_THREADS: "); - test_printn(CH_DBG_FILL_THREADS); - test_println(""); - test_print("--- CH_DBG_THREADS_PROFILING: "); - test_printn(CH_DBG_THREADS_PROFILING); - test_println(""); - } -} - -static const testcase_t test_001_002 = { - "Kernel Settings", - NULL, - NULL, - test_001_002_execute -}; - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Information. - */ -const testcase_t * const test_sequence_001[] = { - &test_001_001, - &test_001_002, - NULL -}; diff --git a/test/rt/source/test/test_sequence_001.h b/test/rt/source/test/test_sequence_001.h deleted file mode 100644 index 9684d47f6..000000000 --- a/test/rt/source/test/test_sequence_001.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_001.h - * @brief Test Sequence 001 header. - */ - -#ifndef TEST_SEQUENCE_001_H -#define TEST_SEQUENCE_001_H - -extern const testcase_t * const test_sequence_001[]; - -#endif /* TEST_SEQUENCE_001_H */ diff --git a/test/rt/source/test/test_sequence_002.c b/test/rt/source/test/test_sequence_002.c deleted file mode 100644 index 7f3afc82f..000000000 --- a/test/rt/source/test/test_sequence_002.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_002.c - * @brief Test Sequence 002 code. - * - * @page test_sequence_002 [2] System layer and port interface - * - * File: @ref test_sequence_002.c - * - *

Description

- * The functionality of the system layer and port interface is tested. - * Basic RT functionality is taken for granted or this test suite could - * not even be executed. Errors in implementation are detected by - * executing this sequence with the state checker enabled - * (CH_DBG_STATE_CHECKER=TRUE). - * - *

Test Cases

- * - @subpage test_002_001 - * - @subpage test_002_002 - * - @subpage test_002_003 - * - @subpage test_002_004 - * . - */ - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -/* Timer callback for testing system functions in ISR context.*/ -static void vtcb(void *p) { - syssts_t sts; - - (void)p; - - /* Testing normal case.*/ - chSysLockFromISR(); - chSysUnlockFromISR(); - - /* Reentrant case.*/ - chSysLockFromISR(); - sts = chSysGetStatusAndLockX(); - chSysRestoreStatusX(sts); - chSysUnlockFromISR(); -} - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -/** - * @page test_002_001 [2.1] System integrity functionality - * - *

Description

- * The system self-test functionality is invoked in order to make an - * initial system state assessment and for coverage. - * - *

Test Steps

- * - [2.1.1] Testing Ready List integrity. - * - [2.1.2] Testing Virtual Timers List integrity. - * - [2.1.3] Testing Registry List integrity. - * - [2.1.4] Testing Port-defined integrity. - * . - */ - -static void test_002_001_execute(void) { - bool result; - - /* [2.1.1] Testing Ready List integrity.*/ - test_set_step(1); - { - chSysLock(); - result = chSysIntegrityCheckI(CH_INTEGRITY_RLIST); - chSysUnlock(); - test_assert(result == false, "ready list check failed"); - } - - /* [2.1.2] Testing Virtual Timers List integrity.*/ - test_set_step(2); - { - chSysLock(); - result = chSysIntegrityCheckI(CH_INTEGRITY_VTLIST); - chSysUnlock(); - test_assert(result == false, "virtual timers list check failed"); - } - - /* [2.1.3] Testing Registry List integrity.*/ - test_set_step(3); - { - chSysLock(); - result = chSysIntegrityCheckI(CH_INTEGRITY_REGISTRY); - chSysUnlock(); - test_assert(result == false, "registry list check failed"); - } - - /* [2.1.4] Testing Port-defined integrity.*/ - test_set_step(4); - { - chSysLock(); - result = chSysIntegrityCheckI(CH_INTEGRITY_PORT); - chSysUnlock(); - test_assert(result == false, "port layer check failed"); - } -} - -static const testcase_t test_002_001 = { - "System integrity functionality", - NULL, - NULL, - test_002_001_execute -}; - -/** - * @page test_002_002 [2.2] Critical zones functionality - * - *

Description

- * The critical zones API is invoked for coverage. - * - *

Test Steps

- * - [2.2.1] Testing chSysGetStatusAndLockX() and - * chSysRestoreStatusX(), non reentrant case. - * - [2.2.2] Testing chSysGetStatusAndLockX() and - * chSysRestoreStatusX(), reentrant case. - * - [2.2.3] Testing chSysUnconditionalLock(). - * - [2.2.4] Testing chSysUnconditionalUnlock(). - * - [2.2.5] Testing from ISR context using a virtual timer. - * . - */ - -static void test_002_002_execute(void) { - syssts_t sts; - virtual_timer_t vt; - - /* [2.2.1] Testing chSysGetStatusAndLockX() and - chSysRestoreStatusX(), non reentrant case.*/ - test_set_step(1); - { - sts = chSysGetStatusAndLockX(); - chSysRestoreStatusX(sts); - } - - /* [2.2.2] Testing chSysGetStatusAndLockX() and - chSysRestoreStatusX(), reentrant case.*/ - test_set_step(2); - { - chSysLock(); - sts = chSysGetStatusAndLockX(); - chSysRestoreStatusX(sts); - chSysUnlock(); - } - - /* [2.2.3] Testing chSysUnconditionalLock().*/ - test_set_step(3); - { - chSysUnconditionalLock(); - chSysUnconditionalLock(); - chSysUnlock(); - } - - /* [2.2.4] Testing chSysUnconditionalUnlock().*/ - test_set_step(4); - { - chSysLock(); - chSysUnconditionalUnlock(); - chSysUnconditionalUnlock(); - } - - /* [2.2.5] Testing from ISR context using a virtual timer.*/ - test_set_step(5); - { - chVTObjectInit(&vt); - chVTSet(&vt, 1, vtcb, NULL); - chThdSleep(10); - - test_assert(chVTIsArmed(&vt) == false, "timer still armed"); - } -} - -static const testcase_t test_002_002 = { - "Critical zones functionality", - NULL, - NULL, - test_002_002_execute -}; - -/** - * @page test_002_003 [2.3] Interrupts handling functionality - * - *

Description

- * The interrupts handling API is invoked for coverage. - * - *

Test Steps

- * - [2.3.1] Testing chSysSuspend(), chSysDisable() and chSysEnable(). - * . - */ - -static void test_002_003_execute(void) { - - /* [2.3.1] Testing chSysSuspend(), chSysDisable() and - chSysEnable().*/ - test_set_step(1); - { - chSysSuspend(); - chSysDisable(); - chSysSuspend(); - chSysEnable(); - } -} - -static const testcase_t test_002_003 = { - "Interrupts handling functionality", - NULL, - NULL, - test_002_003_execute -}; - -/** - * @page test_002_004 [2.4] System Tick Counter functionality - * - *

Description

- * The functionality of the API @p chVTGetSystemTimeX() is tested. - * - *

Test Steps

- * - [2.4.1] A System Tick Counter increment is expected, the test - * simply hangs if it does not happen. - * . - */ - -static void test_002_004_execute(void) { - - /* [2.4.1] A System Tick Counter increment is expected, the test - simply hangs if it does not happen.*/ - test_set_step(1); - { - systime_t time = chVTGetSystemTimeX(); - while (time == chVTGetSystemTimeX()) { -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } - } -} - -static const testcase_t test_002_004 = { - "System Tick Counter functionality", - NULL, - NULL, - test_002_004_execute -}; - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief System layer and port interface. - */ -const testcase_t * const test_sequence_002[] = { - &test_002_001, - &test_002_002, - &test_002_003, - &test_002_004, - NULL -}; diff --git a/test/rt/source/test/test_sequence_002.h b/test/rt/source/test/test_sequence_002.h deleted file mode 100644 index 190f9ca46..000000000 --- a/test/rt/source/test/test_sequence_002.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_002.h - * @brief Test Sequence 002 header. - */ - -#ifndef TEST_SEQUENCE_002_H -#define TEST_SEQUENCE_002_H - -extern const testcase_t * const test_sequence_002[]; - -#endif /* TEST_SEQUENCE_002_H */ diff --git a/test/rt/source/test/test_sequence_003.c b/test/rt/source/test/test_sequence_003.c deleted file mode 100644 index b081f24a9..000000000 --- a/test/rt/source/test/test_sequence_003.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_003.c - * @brief Test Sequence 003 code. - * - * @page test_sequence_003 [3] Threads Functionality - * - * File: @ref test_sequence_003.c - * - *

Description

- * This sequence tests the ChibiOS/RT functionalities related to - * threading. - * - *

Test Cases

- * - @subpage test_003_001 - * - @subpage test_003_002 - * - @subpage test_003_003 - * - @subpage test_003_004 - * . - */ - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -static THD_FUNCTION(thread, p) { - - test_emit_token(*(char *)p); -} - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -/** - * @page test_003_001 [3.1] Thread Sleep functionality - * - *

Description

- * The functionality of @p chThdSleep() and derivatives is tested. - * - *

Test Steps

- * - [3.1.1] The current system time is read then a sleep is performed - * for 100 system ticks and on exit the system time is verified - * again. - * - [3.1.2] The current system time is read then a sleep is performed - * for 100000 microseconds and on exit the system time is verified - * again. - * - [3.1.3] The current system time is read then a sleep is performed - * for 100 milliseconds and on exit the system time is verified - * again. - * - [3.1.4] The current system time is read then a sleep is performed - * for 1 second and on exit the system time is verified again. - * - [3.1.5] Function chThdSleepUntil() is tested with a timeline of - * "now" + 100 ticks. - * . - */ - -static void test_003_001_execute(void) { - systime_t time; - - /* [3.1.1] The current system time is read then a sleep is performed - for 100 system ticks and on exit the system time is verified - again.*/ - test_set_step(1); - { - time = chVTGetSystemTimeX(); - chThdSleep(100); - test_assert_time_window(time + 100, - time + 100 + CH_CFG_ST_TIMEDELTA + 1, - "out of time window"); - } - - /* [3.1.2] The current system time is read then a sleep is performed - for 100000 microseconds and on exit the system time is verified - again.*/ - test_set_step(2); - { - time = chVTGetSystemTimeX(); - chThdSleepMicroseconds(100000); - test_assert_time_window(time + US2ST(100000), - time + US2ST(100000) + CH_CFG_ST_TIMEDELTA + 1, - "out of time window"); - } - - /* [3.1.3] The current system time is read then a sleep is performed - for 100 milliseconds and on exit the system time is verified - again.*/ - test_set_step(3); - { - time = chVTGetSystemTimeX(); - chThdSleepMilliseconds(100); - test_assert_time_window(time + MS2ST(100), - time + MS2ST(100) + CH_CFG_ST_TIMEDELTA + 1, - "out of time window"); - } - - /* [3.1.4] The current system time is read then a sleep is performed - for 1 second and on exit the system time is verified again.*/ - test_set_step(4); - { - time = chVTGetSystemTimeX(); - chThdSleepSeconds(1); - test_assert_time_window(time + S2ST(1), - time + S2ST(1) + CH_CFG_ST_TIMEDELTA + 1, - "out of time window"); - } - - /* [3.1.5] Function chThdSleepUntil() is tested with a timeline of - "now" + 100 ticks.*/ - test_set_step(5); - { - time = chVTGetSystemTimeX(); - chThdSleepUntil(time + 100); - test_assert_time_window(time + 100, - time + 100 + CH_CFG_ST_TIMEDELTA + 1, - "out of time window"); - } -} - -static const testcase_t test_003_001 = { - "Thread Sleep functionality", - NULL, - NULL, - test_003_001_execute -}; - -/** - * @page test_003_002 [3.2] Ready List functionality, threads priority order - * - *

Description

- * Five threads, are enqueued in the ready list and atomically - * executed. The test expects the threads to perform their operations - * in correct priority order regardless of the initial order. - * - *

Test Steps

- * - [3.2.1] Creating 5 threads with increasing priority, execution - * sequence is tested. - * - [3.2.2] Creating 5 threads with decreasing priority, execution - * sequence is tested. - * - [3.2.3] Creating 5 threads with pseudo-random priority, execution - * sequence is tested. - * . - */ - -static void test_003_002_execute(void) { - - /* [3.2.1] Creating 5 threads with increasing priority, execution - sequence is tested.*/ - test_set_step(1); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E"); - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D"); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C"); - threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B"); - threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A"); - test_wait_threads(); - test_assert_sequence("ABCDE", "invalid sequence"); - } - - /* [3.2.2] Creating 5 threads with decreasing priority, execution - sequence is tested.*/ - test_set_step(2); - { - threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A"); - threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B"); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C"); - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D"); - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E"); - test_wait_threads(); - test_assert_sequence("ABCDE", "invalid sequence"); - } - - /* [3.2.3] Creating 5 threads with pseudo-random priority, execution - sequence is tested.*/ - test_set_step(3); - { - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D"); - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E"); - threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A"); - threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B"); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C"); - test_wait_threads(); - test_assert_sequence("ABCDE", "invalid sequence"); - } -} - -static const testcase_t test_003_002 = { - "Ready List functionality, threads priority order", - NULL, - NULL, - test_003_002_execute -}; - -/** - * @page test_003_003 [3.3] Priority change test - * - *

Description

- * A series of priority changes are performed on the current thread in - * order to verify that the priority change happens as expected. - * - *

Test Steps

- * - [3.3.1] Thread priority is increased by one then a check is - * performed. - * - [3.3.2] Thread priority is returned to the previous value then a - * check is performed. - * . - */ - -static void test_003_003_execute(void) { - tprio_t prio, p1; - - /* [3.3.1] Thread priority is increased by one then a check is - performed.*/ - test_set_step(1); - { - prio = chThdGetPriorityX(); - p1 = chThdSetPriority(prio + 1); - test_assert(p1 == prio, "unexpected returned priority level"); - test_assert(chThdGetPriorityX() == prio + 1, "unexpected priority level"); - } - - /* [3.3.2] Thread priority is returned to the previous value then a - check is performed.*/ - test_set_step(2); - { - p1 = chThdSetPriority(p1); - test_assert(p1 == prio + 1, "unexpected returned priority level"); - test_assert(chThdGetPriorityX() == prio, "unexpected priority level"); - } -} - -static const testcase_t test_003_003 = { - "Priority change test", - NULL, - NULL, - test_003_003_execute -}; - -#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) -/** - * @page test_003_004 [3.4] Priority change test with Priority Inheritance - * - *

Description

- * A series of priority changes are performed on the current thread in - * order to verify that the priority change happens as expected. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MUTEXES - * . - * - *

Test Steps

- * - [3.4.1] Simulating a priority boost situation (prio > realprio). - * - [3.4.2] Raising thread priority above original priority but below - * the boosted level. - * - [3.4.3] Raising thread priority above the boosted level. - * - [3.4.4] Restoring original conditions. - * . - */ - -static void test_003_004_execute(void) { - tprio_t prio, p1; - - /* [3.4.1] Simulating a priority boost situation (prio > realprio).*/ - test_set_step(1); - { - prio = chThdGetPriorityX(); - chThdGetSelfX()->prio += 2; - test_assert(chThdGetPriorityX() == prio + 2, "unexpected priority level"); - } - - /* [3.4.2] Raising thread priority above original priority but below - the boosted level.*/ - test_set_step(2); - { - p1 = chThdSetPriority(prio + 1); - test_assert(p1 == prio, "unexpected returned priority level"); - test_assert(chThdGetSelfX()->prio == prio + 2, "unexpected priority level"); - test_assert(chThdGetSelfX()->realprio == prio + 1, "unexpected returned real priority level"); - } - - /* [3.4.3] Raising thread priority above the boosted level.*/ - test_set_step(3); - { - p1 = chThdSetPriority(prio + 3); - test_assert(p1 == prio + 1, "unexpected returned priority level"); - test_assert(chThdGetSelfX()->prio == prio + 3, "unexpected priority level"); - test_assert(chThdGetSelfX()->realprio == prio + 3, "unexpected real priority level"); - } - - /* [3.4.4] Restoring original conditions.*/ - test_set_step(4); - { - chSysLock(); - chThdGetSelfX()->prio = prio; - chThdGetSelfX()->realprio = prio; - chSysUnlock(); - } -} - -static const testcase_t test_003_004 = { - "Priority change test with Priority Inheritance", - NULL, - NULL, - test_003_004_execute -}; -#endif /* CH_CFG_USE_MUTEXES */ - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Threads Functionality. - */ -const testcase_t * const test_sequence_003[] = { - &test_003_001, - &test_003_002, - &test_003_003, -#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) - &test_003_004, -#endif - NULL -}; diff --git a/test/rt/source/test/test_sequence_003.h b/test/rt/source/test/test_sequence_003.h deleted file mode 100644 index 2de592a2f..000000000 --- a/test/rt/source/test/test_sequence_003.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_003.h - * @brief Test Sequence 003 header. - */ - -#ifndef TEST_SEQUENCE_003_H -#define TEST_SEQUENCE_003_H - -extern const testcase_t * const test_sequence_003[]; - -#endif /* TEST_SEQUENCE_003_H */ diff --git a/test/rt/source/test/test_sequence_004.c b/test/rt/source/test/test_sequence_004.c deleted file mode 100644 index 75b927a80..000000000 --- a/test/rt/source/test/test_sequence_004.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_004.c - * @brief Test Sequence 004 code. - * - * @page test_sequence_004 [4] Suspend/Resume - * - * File: @ref test_sequence_004.c - * - *

Description

- * This sequence tests the ChibiOS/RT functionalities related to - * threads suspend/resume. - * - *

Test Cases

- * - @subpage test_004_001 - * . - */ - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -static thread_reference_t tr1; - -static THD_FUNCTION(thread1, p) { - - chSysLock(); - chThdResumeI(&tr1, MSG_OK); - chSchRescheduleS(); - chSysUnlock(); - test_emit_token(*(char *)p); -} - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -/** - * @page test_004_001 [4.1] Suspend and Resume functionality - * - *

Description

- * The functionality of chThdSuspendTimeoutS() and chThdResumeI() is - * tested. - * - *

Test Steps

- * - [4.1.1] The function chThdSuspendTimeoutS() is invoked, the thread - * is remotely resumed with message @p MSG_OK. On return the message - * and the state of the reference are tested. - * - [4.1.2] The function chThdSuspendTimeoutS() is invoked, the thread - * is not resumed so a timeout must occur. On return the message and - * the state of the reference are tested. - * . - */ - -static void test_004_001_setup(void) { - tr1 = NULL; -} - -static void test_004_001_execute(void) { - systime_t time; - msg_t msg; - - /* [4.1.1] The function chThdSuspendTimeoutS() is invoked, the thread - is remotely resumed with message @p MSG_OK. On return the message - and the state of the reference are tested.*/ - test_set_step(1); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-1, thread1, "A"); - chSysLock(); - msg = chThdSuspendTimeoutS(&tr1, TIME_INFINITE); - chSysUnlock(); - test_assert(NULL == tr1, "not NULL"); - test_assert(MSG_OK == msg,"wrong returned message"); - test_wait_threads(); - } - - /* [4.1.2] The function chThdSuspendTimeoutS() is invoked, the thread - is not resumed so a timeout must occur. On return the message and - the state of the reference are tested.*/ - test_set_step(2); - { - chSysLock(); - time = chVTGetSystemTimeX(); - msg = chThdSuspendTimeoutS(&tr1, MS2ST(1000)); - chSysUnlock(); - test_assert_time_window(time + MS2ST(1000), - time + MS2ST(1000) + CH_CFG_ST_TIMEDELTA + 1, - "out of time window"); - test_assert(NULL == tr1, "not NULL"); - test_assert(MSG_TIMEOUT == msg, "wrong returned message"); - } -} - -static const testcase_t test_004_001 = { - "Suspend and Resume functionality", - test_004_001_setup, - NULL, - test_004_001_execute -}; - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Suspend/Resume. - */ -const testcase_t * const test_sequence_004[] = { - &test_004_001, - NULL -}; diff --git a/test/rt/source/test/test_sequence_004.h b/test/rt/source/test/test_sequence_004.h deleted file mode 100644 index 19d8c1bd7..000000000 --- a/test/rt/source/test/test_sequence_004.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_004.h - * @brief Test Sequence 004 header. - */ - -#ifndef TEST_SEQUENCE_004_H -#define TEST_SEQUENCE_004_H - -extern const testcase_t * const test_sequence_004[]; - -#endif /* TEST_SEQUENCE_004_H */ diff --git a/test/rt/source/test/test_sequence_005.c b/test/rt/source/test/test_sequence_005.c deleted file mode 100644 index 91579d0d4..000000000 --- a/test/rt/source/test/test_sequence_005.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_005.c - * @brief Test Sequence 005 code. - * - * @page test_sequence_005 [5] Counter and Binary Semaphores - * - * File: @ref test_sequence_005.c - * - *

Description

- * This sequence tests the ChibiOS/RT functionalities related to - * counter semaphores. - * - *

Conditions

- * This sequence is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_SEMAPHORES - * . - * - *

Test Cases

- * - @subpage test_005_001 - * - @subpage test_005_002 - * - @subpage test_005_003 - * - @subpage test_005_004 - * - @subpage test_005_005 - * - @subpage test_005_006 - * . - */ - -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -#include "ch.h" - -static semaphore_t sem1; - -static THD_FUNCTION(thread1, p) { - - chSemWait(&sem1); - test_emit_token(*(char *)p); -} - -static THD_FUNCTION(thread2, p) { - - (void)p; - chThdSleepMilliseconds(50); - chSysLock(); - chSemSignalI(&sem1); /* For coverage reasons */ - chSchRescheduleS(); - chSysUnlock(); -} - -static THD_FUNCTION(thread3, p) { - - (void)p; - chSemWait(&sem1); - chSemSignal(&sem1); -} - -static THD_FUNCTION(thread4, p) { - - chBSemSignal((binary_semaphore_t *)p); -} - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -/** - * @page test_005_001 [5.1] Semaphore primitives, no state change - * - *

Description

- * Wait, Signal and Reset primitives are tested. The testing thread - * does not trigger a state change. - * - *

Test Steps

- * - [5.1.1] The function chSemWait() is invoked, after return the - * counter and the returned message are tested. - * - [5.1.2] The function chSemSignal() is invoked, after return the - * counter is tested. - * - [5.1.3] The function chSemReset() is invoked, after return the - * counter is tested. - * . - */ - -static void test_005_001_setup(void) { - chSemObjectInit(&sem1, 1); -} - -static void test_005_001_teardown(void) { - chSemReset(&sem1, 0); -} - -static void test_005_001_execute(void) { - - /* [5.1.1] The function chSemWait() is invoked, after return the - counter and the returned message are tested.*/ - test_set_step(1); - { - msg_t msg; - - msg = chSemWait(&sem1); - test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value"); - test_assert(MSG_OK == msg, "wrong returned message"); - } - - /* [5.1.2] The function chSemSignal() is invoked, after return the - counter is tested.*/ - test_set_step(2); - { - chSemSignal(&sem1); - test_assert_lock(chSemGetCounterI(&sem1) == 1, "wrong counter value"); - } - - /* [5.1.3] The function chSemReset() is invoked, after return the - counter is tested.*/ - test_set_step(3); - { - chSemReset(&sem1, 2); - test_assert_lock(chSemGetCounterI(&sem1) == 2, "wrong counter value"); - } -} - -static const testcase_t test_005_001 = { - "Semaphore primitives, no state change", - test_005_001_setup, - test_005_001_teardown, - test_005_001_execute -}; - -/** - * @page test_005_002 [5.2] Semaphore enqueuing test - * - *

Description

- * Five threads with randomized priorities are enqueued to a semaphore - * then awakened one at time. The test expects that the threads reach - * their goal in FIFO order or priority order depending on the @p - * CH_CFG_USE_SEMAPHORES_PRIORITY configuration setting. - * - *

Test Steps

- * - [5.2.1] Five threads are created with mixed priority levels (not - * increasing nor decreasing). Threads enqueue on a semaphore - * initialized to zero. - * - [5.2.2] The semaphore is signaled 5 times. The thread activation - * sequence is tested. - * . - */ - -static void test_005_002_setup(void) { - chSemObjectInit(&sem1, 0); -} - -static void test_005_002_execute(void) { - - /* [5.2.1] Five threads are created with mixed priority levels (not - increasing nor decreasing). Threads enqueue on a semaphore - initialized to zero.*/ - test_set_step(1); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+5, thread1, "A"); - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()+1, thread1, "B"); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()+3, thread1, "C"); - threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()+4, thread1, "D"); - threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()+2, thread1, "E"); - } - - /* [5.2.2] The semaphore is signaled 5 times. The thread activation - sequence is tested.*/ - test_set_step(2); - { - chSemSignal(&sem1); - chSemSignal(&sem1); - chSemSignal(&sem1); - chSemSignal(&sem1); - chSemSignal(&sem1); - test_wait_threads(); -#if CH_CFG_USE_SEMAPHORES_PRIORITY - test_assert_sequence("ADCEB", "invalid sequence"); -#else - test_assert_sequence("ABCDE", "invalid sequence"); -#endif - } -} - -static const testcase_t test_005_002 = { - "Semaphore enqueuing test", - test_005_002_setup, - NULL, - test_005_002_execute -}; - -/** - * @page test_005_003 [5.3] Semaphore timeout test - * - *

Description

- * The three possible semaphore waiting modes (do not wait, wait with - * timeout, wait without timeout) are explored. The test expects that - * the semaphore wait function returns the correct value in each of the - * above scenario and that the semaphore structure status is correct - * after each operation. - * - *

Test Steps

- * - [5.3.1] Testing special case TIME_IMMEDIATE. - * - [5.3.2] Testing non-timeout condition. - * - [5.3.3] Testing timeout condition. - * . - */ - -static void test_005_003_setup(void) { - chSemObjectInit(&sem1, 0); -} - -static void test_005_003_execute(void) { - unsigned i; - systime_t target_time; - msg_t msg; - - /* [5.3.1] Testing special case TIME_IMMEDIATE.*/ - test_set_step(1); - { - msg = chSemWaitTimeout(&sem1, TIME_IMMEDIATE); - test_assert(msg == MSG_TIMEOUT, "wrong wake-up message"); - test_assert(queue_isempty(&sem1.queue), "queue not empty"); - test_assert(sem1.cnt == 0, "counter not zero"); - } - - /* [5.3.2] Testing non-timeout condition.*/ - test_set_step(2); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, - thread2, 0); - msg = chSemWaitTimeout(&sem1, MS2ST(500)); - test_wait_threads(); - test_assert(msg == MSG_OK, "wrong wake-up message"); - test_assert(queue_isempty(&sem1.queue), "queue not empty"); - test_assert(sem1.cnt == 0, "counter not zero"); - } - - /* [5.3.3] Testing timeout condition.*/ - test_set_step(3); - { - target_time = test_wait_tick() + MS2ST(5 * 50); - for (i = 0; i < 5; i++) { - test_emit_token('A' + i); - msg = chSemWaitTimeout(&sem1, MS2ST(50)); - test_assert(msg == MSG_TIMEOUT, "wrong wake-up message"); - test_assert(queue_isempty(&sem1.queue), "queue not empty"); - test_assert(sem1.cnt == 0, "counter not zero"); - } - test_assert_sequence("ABCDE", "invalid sequence"); - test_assert_time_window(target_time, target_time + ALLOWED_DELAY, - "out of time window"); - } -} - -static const testcase_t test_005_003 = { - "Semaphore timeout test", - test_005_003_setup, - NULL, - test_005_003_execute -}; - -/** - * @page test_005_004 [5.4] Testing chSemAddCounterI() functionality - * - *

Description

- * The functon is tested by waking up a thread then the semaphore - * counter value is tested. - * - *

Test Steps

- * - [5.4.1] A thread is created, it goes to wait on the semaphore. - * - [5.4.2] The semaphore counter is increased by two, it is then - * tested to be one, the thread must have completed. - * . - */ - -static void test_005_004_setup(void) { - chSemObjectInit(&sem1, 0); -} - -static void test_005_004_execute(void) { - - /* [5.4.1] A thread is created, it goes to wait on the semaphore.*/ - test_set_step(1); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, thread1, "A"); - } - - /* [5.4.2] The semaphore counter is increased by two, it is then - tested to be one, the thread must have completed.*/ - test_set_step(2); - { - chSysLock(); - chSemAddCounterI(&sem1, 2); - chSchRescheduleS(); - chSysUnlock(); - test_wait_threads(); - test_assert_lock(chSemGetCounterI(&sem1) == 1, "invalid counter"); - test_assert_sequence("A", "invalid sequence"); - } -} - -static const testcase_t test_005_004 = { - "Testing chSemAddCounterI() functionality", - test_005_004_setup, - NULL, - test_005_004_execute -}; - -/** - * @page test_005_005 [5.5] Testing chSemWaitSignal() functionality - * - *

Description

- * This test case explicitly addresses the @p chSemWaitSignal() - * function. A thread is created that performs a wait and a signal - * operations. The tester thread is awakened from an atomic wait/signal - * operation. The test expects that the semaphore wait function returns - * the correct value in each of the above scenario and that the - * semaphore structure status is correct after each operation. - * - *

Test Steps

- * - [5.5.1] An higher priority thread is created that performs - * non-atomical wait and signal operations on a semaphore. - * - [5.5.2] The function chSemSignalWait() is invoked by specifying - * the same semaphore for the wait and signal phases. The counter - * value must be one on exit. - * - [5.5.3] The function chSemSignalWait() is invoked again by - * specifying the same semaphore for the wait and signal phases. The - * counter value must be one on exit. - * . - */ - -static void test_005_005_setup(void) { - chSemObjectInit(&sem1, 0); -} - -static void test_005_005_teardown(void) { - test_wait_threads(); -} - -static void test_005_005_execute(void) { - - /* [5.5.1] An higher priority thread is created that performs - non-atomical wait and signal operations on a semaphore.*/ - test_set_step(1); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, thread3, 0); - } - - /* [5.5.2] The function chSemSignalWait() is invoked by specifying - the same semaphore for the wait and signal phases. The counter - value must be one on exit.*/ - test_set_step(2); - { - chSemSignalWait(&sem1, &sem1); - test_assert(queue_isempty(&sem1.queue), "queue not empty"); - test_assert(sem1.cnt == 0, "counter not zero"); - } - - /* [5.5.3] The function chSemSignalWait() is invoked again by - specifying the same semaphore for the wait and signal phases. The - counter value must be one on exit.*/ - test_set_step(3); - { - chSemSignalWait(&sem1, &sem1); - test_assert(queue_isempty(&sem1.queue), "queue not empty"); - test_assert(sem1.cnt == 0, "counter not zero"); - } -} - -static const testcase_t test_005_005 = { - "Testing chSemWaitSignal() functionality", - test_005_005_setup, - test_005_005_teardown, - test_005_005_execute -}; - -/** - * @page test_005_006 [5.6] Testing Binary Semaphores special case - * - *

Description

- * This test case tests the binary semaphores functionality. The test - * both checks the binary semaphore status and the expected status of - * the underlying counting semaphore. - * - *

Test Steps

- * - [5.6.1] Creating a binary semaphore in "taken" state, the state is - * checked. - * - [5.6.2] Resetting the binary semaphore in "taken" state, the state - * must not change. - * - [5.6.3] Starting a signaler thread at a lower priority. - * - [5.6.4] Waiting for the binary semaphore to be signaled, the - * semaphore is expected to be taken. - * - [5.6.5] Signaling the binary semaphore, checking the binary - * semaphore state to be "not taken" and the underlying counter - * semaphore counter to be one. - * - [5.6.6] Signaling the binary semaphore again, the internal state - * must not change from "not taken". - * . - */ - -static void test_005_006_teardown(void) { - test_wait_threads(); -} - -static void test_005_006_execute(void) { - binary_semaphore_t bsem; - msg_t msg; - - /* [5.6.1] Creating a binary semaphore in "taken" state, the state is - checked.*/ - test_set_step(1); - { - chBSemObjectInit(&bsem, true); - test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken"); - } - - /* [5.6.2] Resetting the binary semaphore in "taken" state, the state - must not change.*/ - test_set_step(2); - { - chBSemReset(&bsem, true); - test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken"); - } - - /* [5.6.3] Starting a signaler thread at a lower priority.*/ - test_set_step(3); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, - chThdGetPriorityX()-1, thread4, &bsem); - } - - /* [5.6.4] Waiting for the binary semaphore to be signaled, the - semaphore is expected to be taken.*/ - test_set_step(4); - { - msg = chBSemWait(&bsem); - test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken"); - test_assert(msg == MSG_OK, "unexpected message"); - } - - /* [5.6.5] Signaling the binary semaphore, checking the binary - semaphore state to be "not taken" and the underlying counter - semaphore counter to be one.*/ - test_set_step(5); - { - chBSemSignal(&bsem); - test_assert_lock(chBSemGetStateI(&bsem) ==false, "still taken"); - test_assert_lock(chSemGetCounterI(&bsem.sem) == 1, "unexpected counter"); - } - - /* [5.6.6] Signaling the binary semaphore again, the internal state - must not change from "not taken".*/ - test_set_step(6); - { - chBSemSignal(&bsem); - test_assert_lock(chBSemGetStateI(&bsem) == false, "taken"); - test_assert_lock(chSemGetCounterI(&bsem.sem) == 1, "unexpected counter"); - } -} - -static const testcase_t test_005_006 = { - "Testing Binary Semaphores special case", - NULL, - test_005_006_teardown, - test_005_006_execute -}; - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Counter and Binary Semaphores. - */ -const testcase_t * const test_sequence_005[] = { - &test_005_001, - &test_005_002, - &test_005_003, - &test_005_004, - &test_005_005, - &test_005_006, - NULL -}; - -#endif /* CH_CFG_USE_SEMAPHORES */ diff --git a/test/rt/source/test/test_sequence_005.h b/test/rt/source/test/test_sequence_005.h deleted file mode 100644 index d2df83307..000000000 --- a/test/rt/source/test/test_sequence_005.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_005.h - * @brief Test Sequence 005 header. - */ - -#ifndef TEST_SEQUENCE_005_H -#define TEST_SEQUENCE_005_H - -extern const testcase_t * const test_sequence_005[]; - -#endif /* TEST_SEQUENCE_005_H */ diff --git a/test/rt/source/test/test_sequence_006.c b/test/rt/source/test/test_sequence_006.c deleted file mode 100644 index b15d61b38..000000000 --- a/test/rt/source/test/test_sequence_006.c +++ /dev/null @@ -1,1069 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_006.c - * @brief Test Sequence 006 code. - * - * @page test_sequence_006 [6] Mutexes, Condition Variables and Priority Inheritance - * - * File: @ref test_sequence_006.c - * - *

Description

- * This sequence tests the ChibiOS/RT functionalities related to - * mutexes, condition variables and priority inheritance algorithm. - * - *

Conditions

- * This sequence is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MUTEXES - * . - * - *

Test Cases

- * - @subpage test_006_001 - * - @subpage test_006_002 - * - @subpage test_006_003 - * - @subpage test_006_004 - * - @subpage test_006_005 - * - @subpage test_006_006 - * - @subpage test_006_007 - * - @subpage test_006_008 - * - @subpage test_006_009 - * . - */ - -#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -static MUTEX_DECL(m1); -static MUTEX_DECL(m2); -#if CH_CFG_USE_CONDVARS || defined(__DOXYGEN__) -static CONDVAR_DECL(c1); -#endif - -#if CH_DBG_THREADS_PROFILING || defined(__DOXYGEN__) -/** - * @brief CPU pulse. - * @note The current implementation is not totally reliable. - * - * @param[in] duration CPU pulse duration in milliseconds - */ -void test_cpu_pulse(unsigned duration) { - systime_t start, end, now; - - start = chThdGetTicksX(chThdGetSelfX()); - end = start + MS2ST(duration); - do { - now = chThdGetTicksX(chThdGetSelfX()); -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } - while (chVTIsTimeWithinX(now, start, end)); -} -#endif /* CH_DBG_THREADS_PROFILING */ - -static THD_FUNCTION(thread1, p) { - - chMtxLock(&m1); - test_emit_token(*(char *)p); - chMtxUnlock(&m1); -} - -#if CH_DBG_THREADS_PROFILING || defined(__DOXYGEN__) -/* Low priority thread */ -static THD_FUNCTION(thread2L, p) { - - (void)p; - chMtxLock(&m1); - test_cpu_pulse(40); - chMtxUnlock(&m1); - test_cpu_pulse(10); - test_emit_token('C'); -} - -/* Medium priority thread */ -static THD_FUNCTION(thread2M, p) { - - (void)p; - chThdSleepMilliseconds(20); - test_cpu_pulse(40); - test_emit_token('B'); -} - -/* High priority thread */ -static THD_FUNCTION(thread2H, p) { - - (void)p; - chThdSleepMilliseconds(40); - chMtxLock(&m1); - test_cpu_pulse(10); - chMtxUnlock(&m1); - test_emit_token('A'); -} - -/* Lowest priority thread */ -static THD_FUNCTION(thread3LL, p) { - - (void)p; - chMtxLock(&m1); - test_cpu_pulse(30); - chMtxUnlock(&m1); - test_emit_token('E'); -} - -/* Low priority thread */ -static THD_FUNCTION(thread3L, p) { - - (void)p; - chThdSleepMilliseconds(10); - chMtxLock(&m2); - test_cpu_pulse(20); - chMtxLock(&m1); - test_cpu_pulse(10); - chMtxUnlock(&m1); - test_cpu_pulse(10); - chMtxUnlock(&m2); - test_emit_token('D'); -} - -/* Medium priority thread */ -static THD_FUNCTION(thread3M, p) { - - (void)p; - chThdSleepMilliseconds(20); - chMtxLock(&m2); - test_cpu_pulse(10); - chMtxUnlock(&m2); - test_emit_token('C'); -} - -/* High priority thread */ -static THD_FUNCTION(thread3H, p) { - - (void)p; - chThdSleepMilliseconds(40); - test_cpu_pulse(20); - test_emit_token('B'); -} - -/* Highest priority thread */ -static THD_FUNCTION(thread3HH, p) { - - (void)p; - chThdSleepMilliseconds(50); - chMtxLock(&m2); - test_cpu_pulse(10); - chMtxUnlock(&m2); - test_emit_token('A'); -} -#endif /* CH_DBG_THREADS_PROFILING */ - -static THD_FUNCTION(thread4A, p) { - - (void)p; - chThdSleepMilliseconds(50); - chMtxLock(&m1); - chMtxUnlock(&m1); -} - -static THD_FUNCTION(thread4B, p) { - - (void)p; - chThdSleepMilliseconds(150); - chSysLock(); - chMtxLockS(&m2); /* For coverage of the chMtxLockS() function variant.*/ - chMtxUnlockS(&m2); /* For coverage of the chMtxUnlockS() function variant.*/ - chSchRescheduleS(); - chSysUnlock(); -} - -#if CH_CFG_USE_CONDVARS || defined(__DOXYGEN__) -static THD_FUNCTION(thread6, p) { - - chMtxLock(&m1); - chCondWait(&c1); - test_emit_token(*(char *)p); - chMtxUnlock(&m1); -} - -static THD_FUNCTION(thread8, p) { - - chMtxLock(&m2); - chMtxLock(&m1); -#if CH_CFG_USE_CONDVARS_TIMEOUT || defined(__DOXYGEN__) - chCondWaitTimeout(&c1, TIME_INFINITE); -#else - chCondWait(&c1); -#endif - test_emit_token(*(char *)p); - chMtxUnlock(&m1); - chMtxUnlock(&m2); -} - -static THD_FUNCTION(thread9, p) { - - chMtxLock(&m2); - test_emit_token(*(char *)p); - chMtxUnlock(&m2); -} -#endif /* CH_CFG_USE_CONDVARS */ - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -/** - * @page test_006_001 [6.1] Priority enqueuing test - * - *

Description

- * Five threads, with increasing priority, are enqueued on a locked - * mutex then the mutex is unlocked. The test expects the threads to - * perform their operations in increasing priority order regardless of - * the initial order. - * - *

Test Steps

- * - [6.1.1] Getting the initial priority. - * - [6.1.2] Locking the mutex. - * - [6.1.3] Five threads are created that try to lock and unlock the - * mutex then terminate. The threads are created in ascending - * priority order. - * - [6.1.4] Unlocking the mutex, the threads will wakeup in priority - * order because the mutext queue is an ordered one. - * . - */ - -static void test_006_001_setup(void) { - chMtxObjectInit(&m1); -} - -static void test_006_001_execute(void) { - tprio_t prio; - - /* [6.1.1] Getting the initial priority.*/ - test_set_step(1); - { - prio = chThdGetPriorityX(); - } - - /* [6.1.2] Locking the mutex.*/ - test_set_step(2); - { - chMtxLock(&m1); - } - - /* [6.1.3] Five threads are created that try to lock and unlock the - mutex then terminate. The threads are created in ascending - priority order.*/ - test_set_step(3); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread1, "E"); - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread1, "D"); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread1, "C"); - threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread1, "B"); - threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread1, "A"); - } - - /* [6.1.4] Unlocking the mutex, the threads will wakeup in priority - order because the mutext queue is an ordered one.*/ - test_set_step(4); - { - chMtxUnlock(&m1); - test_wait_threads(); - test_assert(prio == chThdGetPriorityX(), "wrong priority level"); - test_assert_sequence("ABCDE", "invalid sequence"); - } -} - -static const testcase_t test_006_001 = { - "Priority enqueuing test", - test_006_001_setup, - NULL, - test_006_001_execute -}; - -#if (CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) -/** - * @page test_006_002 [6.2] Priority inheritance, simple case - * - *

Description

- * Three threads are involved in the classic priority inversion - * scenario, a medium priority thread tries to starve an high priority - * thread by blocking a low priority thread into a mutex lock zone. The - * test expects the threads to reach their goal in increasing priority - * order by rearranging their priorities in order to avoid the priority - * inversion trap. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_DBG_THREADS_PROFILING - * . - * - *

Test Steps

- * - [6.2.1] Getting the system time for test duration measurement. - * - [6.2.2] The three contenders threads are created and let run - * atomically, the goals sequence is tested, the threads must - * complete in priority order. - * - [6.2.3] Testing that all threads completed within the specified - * time windows (100mS...100mS+ALLOWED_DELAY). - * . - */ - -static void test_006_002_setup(void) { - chMtxObjectInit(&m1); -} - -static void test_006_002_execute(void) { - systime_t time; - - /* [6.2.1] Getting the system time for test duration measurement.*/ - test_set_step(1); - { - time = test_wait_tick(); - } - - /* [6.2.2] The three contenders threads are created and let run - atomically, the goals sequence is tested, the threads must - complete in priority order.*/ - test_set_step(2); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-1, thread2H, 0); - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-2, thread2M, 0); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread2L, 0); - test_wait_threads(); - test_assert_sequence("ABC", "invalid sequence"); - } - - /* [6.2.3] Testing that all threads completed within the specified - time windows (100mS...100mS+ALLOWED_DELAY).*/ - test_set_step(3); - { - test_assert_time_window(time + MS2ST(100), time + MS2ST(100) + ALLOWED_DELAY, - "out of time window"); - } -} - -static const testcase_t test_006_002 = { - "Priority inheritance, simple case", - test_006_002_setup, - NULL, - test_006_002_execute -}; -#endif /* CH_DBG_THREADS_PROFILING */ - -#if (CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) -/** - * @page test_006_003 [6.3] Priority inheritance, complex case - * - *

Description

- * Five threads are involved in the complex priority inversion - * scenario, the priority inheritance algorithm is tested for depths - * greater than one. The test expects the threads to perform their - * operations in increasing priority order by rearranging their - * priorities in order to avoid the priority inversion trap. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_DBG_THREADS_PROFILING - * . - * - *

Test Steps

- * - [6.3.1] Getting the system time for test duration measurement. - * - [6.3.2] The five contenders threads are created and let run - * atomically, the goals sequence is tested, the threads must - * complete in priority order. - * - [6.3.3] Testing that all threads completed within the specified - * time windows (110mS...110mS+ALLOWED_DELAY). - * . - */ - -static void test_006_003_setup(void) { - chMtxObjectInit(&m1); /* Mutex B.*/ - chMtxObjectInit(&m2); /* Mutex A.*/ -} - -static void test_006_003_execute(void) { - systime_t time; - - /* [6.3.1] Getting the system time for test duration measurement.*/ - test_set_step(1); - { - time = test_wait_tick(); - } - - /* [6.3.2] The five contenders threads are created and let run - atomically, the goals sequence is tested, the threads must - complete in priority order.*/ - test_set_step(2); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread3LL, 0); - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread3L, 0); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread3M, 0); - threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread3H, 0); - threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread3HH, 0); - test_wait_threads(); - test_assert_sequence("ABCDE", "invalid sequence"); - } - - /* [6.3.3] Testing that all threads completed within the specified - time windows (110mS...110mS+ALLOWED_DELAY).*/ - test_set_step(3); - { - test_assert_time_window(time + MS2ST(110), time + MS2ST(110) + ALLOWED_DELAY, - "out of time window"); - } -} - -static const testcase_t test_006_003 = { - "Priority inheritance, complex case", - test_006_003_setup, - NULL, - test_006_003_execute -}; -#endif /* CH_DBG_THREADS_PROFILING */ - -/** - * @page test_006_004 [6.4] Priority return verification - * - *

Description

- * Two threads are spawned that try to lock the mutexes already locked - * by the tester thread with precise timing. The test expects that the - * priority changes caused by the priority inheritance algorithm happen - * at the right moment and with the right values.
Thread A performs - * wait(50), lock(m1), unlock(m1), exit. Thread B performs wait(150), - * lock(m2), unlock(m2), exit. - * - *

Test Steps

- * - [6.4.1] Getting current thread priority P(0) and assigning to the - * threads A and B priorities +1 and +2. - * - [6.4.2] Spawning threads A and B at priorities P(A) and P(B). - * - [6.4.3] Locking the mutex M1 before thread A has a chance to lock - * it. The priority must not change because A has not yet reached - * chMtxLock(M1). the mutex is not locked. - * - [6.4.4] Waiting 100mS, this makes thread A reach chMtxLock(M1) and - * get the mutex. This must boost the priority of the current thread - * at the same level of thread A. - * - [6.4.5] Locking the mutex M2 before thread B has a chance to lock - * it. The priority must not change because B has not yet reached - * chMtxLock(M2). the mutex is not locked. - * - [6.4.6] Waiting 100mS, this makes thread B reach chMtxLock(M2) and - * get the mutex. This must boost the priority of the current thread - * at the same level of thread B. - * - [6.4.7] Unlocking M2, the priority should fall back to P(A). - * - [6.4.8] Unlocking M1, the priority should fall back to P(0). - * . - */ - -static void test_006_004_setup(void) { - chMtxObjectInit(&m1); - chMtxObjectInit(&m2); -} - -static void test_006_004_teardown(void) { - test_wait_threads(); -} - -static void test_006_004_execute(void) { - tprio_t p, pa, pb; - - /* [6.4.1] Getting current thread priority P(0) and assigning to the - threads A and B priorities +1 and +2.*/ - test_set_step(1); - { - p = chThdGetPriorityX(); - pa = p + 1; - pb = p + 2; - } - - /* [6.4.2] Spawning threads A and B at priorities P(A) and P(B).*/ - test_set_step(2); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, pa, thread4A, "A"); - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, pb, thread4B, "B"); - } - - /* [6.4.3] Locking the mutex M1 before thread A has a chance to lock - it. The priority must not change because A has not yet reached - chMtxLock(M1). the mutex is not locked.*/ - test_set_step(3); - { - chMtxLock(&m1); - test_assert(chThdGetPriorityX() == p, "wrong priority level"); - } - - /* [6.4.4] Waiting 100mS, this makes thread A reach chMtxLock(M1) and - get the mutex. This must boost the priority of the current thread - at the same level of thread A.*/ - test_set_step(4); - { - chThdSleepMilliseconds(100); - test_assert(chThdGetPriorityX() == pa, "wrong priority level"); - } - - /* [6.4.5] Locking the mutex M2 before thread B has a chance to lock - it. The priority must not change because B has not yet reached - chMtxLock(M2). the mutex is not locked.*/ - test_set_step(5); - { - chMtxLock(&m2); - test_assert(chThdGetPriorityX() == pa, "wrong priority level"); - } - - /* [6.4.6] Waiting 100mS, this makes thread B reach chMtxLock(M2) and - get the mutex. This must boost the priority of the current thread - at the same level of thread B.*/ - test_set_step(6); - { - chThdSleepMilliseconds(100); - test_assert(chThdGetPriorityX() == pb, "wrong priority level"); - } - - /* [6.4.7] Unlocking M2, the priority should fall back to P(A).*/ - test_set_step(7); - { - chMtxUnlock(&m2); - test_assert(chThdGetPriorityX() == pa, "wrong priority level"); - } - - /* [6.4.8] Unlocking M1, the priority should fall back to P(0).*/ - test_set_step(8); - { - chMtxUnlock(&m1); - test_assert(chThdGetPriorityX() == p, "wrong priority level"); - } -} - -static const testcase_t test_006_004 = { - "Priority return verification", - test_006_004_setup, - test_006_004_teardown, - test_006_004_execute -}; - -#if (!CH_CFG_USE_MUTEXES_RECURSIVE) || defined(__DOXYGEN__) -/** - * @page test_006_005 [6.5] Repeated locks, non recursive scenario - * - *

Description

- * The behavior of multiple mutex locks from the same thread is tested - * when recursion is disabled. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - !CH_CFG_USE_MUTEXES_RECURSIVE - * . - * - *

Test Steps

- * - [6.5.1] Getting current thread priority for later checks. - * - [6.5.2] Locking the mutex first time, it must be possible because - * it is not owned. - * - [6.5.3] Locking the mutex second time, it must fail because it is - * already owned. - * - [6.5.4] Unlocking the mutex then it must not be owned anymore and - * the queue must be empty. - * - [6.5.5] Testing that priority has not changed after operations. - * - [6.5.6] Testing chMtxUnlockAll() behavior. - * - [6.5.7] Testing that priority has not changed after operations. - * . - */ - -static void test_006_005_setup(void) { - chMtxObjectInit(&m1); -} - -static void test_006_005_execute(void) { - bool b; - tprio_t prio; - - /* [6.5.1] Getting current thread priority for later checks.*/ - test_set_step(1); - { - prio = chThdGetPriorityX(); - } - - /* [6.5.2] Locking the mutex first time, it must be possible because - it is not owned.*/ - test_set_step(2); - { - b = chMtxTryLock(&m1); - test_assert(b, "already locked"); - } - - /* [6.5.3] Locking the mutex second time, it must fail because it is - already owned.*/ - test_set_step(3); - { - b = chMtxTryLock(&m1); - test_assert(!b, "not locked"); - } - - /* [6.5.4] Unlocking the mutex then it must not be owned anymore and - the queue must be empty.*/ - test_set_step(4); - { - chMtxUnlock(&m1); - test_assert(m1.owner == NULL, "still owned"); - test_assert(queue_isempty(&m1.queue), "queue not empty"); - } - - /* [6.5.5] Testing that priority has not changed after operations.*/ - test_set_step(5); - { - test_assert(chThdGetPriorityX() == prio, "wrong priority level"); - } - - /* [6.5.6] Testing chMtxUnlockAll() behavior.*/ - test_set_step(6); - { - b = chMtxTryLock(&m1); - test_assert(b, "already locked"); - b = chMtxTryLock(&m1); - test_assert(!b, "not locked"); - - chMtxUnlockAll(); - test_assert(m1.owner == NULL, "still owned"); - test_assert(queue_isempty(&m1.queue), "queue not empty"); - } - - /* [6.5.7] Testing that priority has not changed after operations.*/ - test_set_step(7); - { - test_assert(chThdGetPriorityX() == prio, "wrong priority level"); - } -} - -static const testcase_t test_006_005 = { - "Repeated locks, non recursive scenario", - test_006_005_setup, - NULL, - test_006_005_execute -}; -#endif /* !CH_CFG_USE_MUTEXES_RECURSIVE */ - -#if (CH_CFG_USE_MUTEXES_RECURSIVE) || defined(__DOXYGEN__) -/** - * @page test_006_006 [6.6] Repeated locks using, recursive scenario - * - *

Description

- * The behavior of multiple mutex locks from the same thread is tested - * when recursion is enabled. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MUTEXES_RECURSIVE - * . - * - *

Test Steps

- * - [6.6.1] Getting current thread priority for later checks. - * - [6.6.2] Locking the mutex first time, it must be possible because - * it is not owned. - * - [6.6.3] Locking the mutex second time, it must be possible because - * it is recursive. - * - [6.6.4] Unlocking the mutex then it must be still owned because - * recursivity. - * - [6.6.5] Unlocking the mutex then it must not be owned anymore and - * the queue must be empty. - * - [6.6.6] Testing that priority has not changed after operations. - * - [6.6.7] Testing consecutive chMtxTryLock()/chMtxTryLockS() calls - * and a final chMtxUnlockAllS(). - * - [6.6.8] Testing consecutive chMtxLock()/chMtxLockS() calls and a - * final chMtxUnlockAll(). - * - [6.6.9] Testing that priority has not changed after operations. - * . - */ - -static void test_006_006_setup(void) { - chMtxObjectInit(&m1); -} - -static void test_006_006_execute(void) { - bool b; - tprio_t prio; - - /* [6.6.1] Getting current thread priority for later checks.*/ - test_set_step(1); - { - prio = chThdGetPriorityX(); - } - - /* [6.6.2] Locking the mutex first time, it must be possible because - it is not owned.*/ - test_set_step(2); - { - b = chMtxTryLock(&m1); - test_assert(b, "already locked"); - } - - /* [6.6.3] Locking the mutex second time, it must be possible because - it is recursive.*/ - test_set_step(3); - { - b = chMtxTryLock(&m1); - test_assert(b, "already locked"); - } - - /* [6.6.4] Unlocking the mutex then it must be still owned because - recursivity.*/ - test_set_step(4); - { - chMtxUnlock(&m1); - test_assert(m1.owner != NULL, "not owned"); - } - - /* [6.6.5] Unlocking the mutex then it must not be owned anymore and - the queue must be empty.*/ - test_set_step(5); - { - chMtxUnlock(&m1); - test_assert(m1.owner == NULL, "still owned"); - test_assert(queue_isempty(&m1.queue), "queue not empty"); - } - - /* [6.6.6] Testing that priority has not changed after operations.*/ - test_set_step(6); - { - test_assert(chThdGetPriorityX() == prio, "wrong priority level"); - } - - /* [6.6.7] Testing consecutive chMtxTryLock()/chMtxTryLockS() calls - and a final chMtxUnlockAllS().*/ - test_set_step(7); - { - b = chMtxTryLock(&m1); - test_assert(b, "already locked"); - chSysLock(); - b = chMtxTryLockS(&m1); - chSysUnlock(); - test_assert(b, "already locked"); - test_assert(m1.cnt == 2, "invalid recursion counter"); - chSysLock(); - chMtxUnlockAllS(); - chSysUnlock(); - test_assert(m1.owner == NULL, "still owned"); - test_assert(queue_isempty(&m1.queue), "queue not empty"); - test_assert(m1.cnt == 0, "invalid recursion counter"); - } - - /* [6.6.8] Testing consecutive chMtxLock()/chMtxLockS() calls and a - final chMtxUnlockAll().*/ - test_set_step(8); - { - chMtxLock(&m1); - test_assert(m1.owner != NULL, "not owned"); - chSysLock(); - chMtxLockS(&m1); - chSysUnlock(); - test_assert(m1.owner != NULL, "not owned"); - test_assert(m1.cnt == 2, "invalid recursion counter"); - chMtxUnlockAll(); - test_assert(m1.owner == NULL, "still owned"); - test_assert(queue_isempty(&m1.queue), "queue not empty"); - test_assert(m1.cnt == 0, "invalid recursion counter"); - } - - /* [6.6.9] Testing that priority has not changed after operations.*/ - test_set_step(9); - { - test_assert(chThdGetPriorityX() == prio, "wrong priority level"); - } -} - -static const testcase_t test_006_006 = { - "Repeated locks using, recursive scenario", - test_006_006_setup, - NULL, - test_006_006_execute -}; -#endif /* CH_CFG_USE_MUTEXES_RECURSIVE */ - -#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) -/** - * @page test_006_007 [6.7] Condition Variable signal test - * - *

Description

- * Five threads take a mutex and then enter a conditional variable - * queue, the tester thread then proceeds to signal the conditional - * variable five times atomically.
The test expects the threads to - * reach their goal in increasing priority order regardless of the - * initial order. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_CONDVARS - * . - * - *

Test Steps

- * - [6.7.1] Starting the five threads with increasing priority, the - * threads will queue on the condition variable. - * - [6.7.2] Atomically signaling the condition variable five times - * then waiting for the threads to terminate in priority order, the - * order is tested. - * . - */ - -static void test_006_007_setup(void) { - chCondObjectInit(&c1); - chMtxObjectInit(&m1); -} - -static void test_006_007_execute(void) { - - /* [6.7.1] Starting the five threads with increasing priority, the - threads will queue on the condition variable.*/ - test_set_step(1); - { - tprio_t prio = chThdGetPriorityX(); - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread6, "E"); - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread6, "D"); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread6, "C"); - threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread6, "B"); - threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread6, "A"); - } - - /* [6.7.2] Atomically signaling the condition variable five times - then waiting for the threads to terminate in priority order, the - order is tested.*/ - test_set_step(2); - { - chSysLock(); - chCondSignalI(&c1); - chCondSignalI(&c1); - chCondSignalI(&c1); - chCondSignalI(&c1); - chCondSignalI(&c1); - chSchRescheduleS(); - chSysUnlock(); - test_wait_threads(); - test_assert_sequence("ABCDE", "invalid sequence"); - } -} - -static const testcase_t test_006_007 = { - "Condition Variable signal test", - test_006_007_setup, - NULL, - test_006_007_execute -}; -#endif /* CH_CFG_USE_CONDVARS */ - -#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) -/** - * @page test_006_008 [6.8] Condition Variable broadcast test - * - *

Description

- * Five threads take a mutex and then enter a conditional variable - * queue, the tester thread then proceeds to broadcast the conditional - * variable.
The test expects the threads to reach their goal in - * increasing priority order regardless of the initial order. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_CONDVARS - * . - * - *

Test Steps

- * - [6.8.1] Starting the five threads with increasing priority, the - * threads will queue on the condition variable. - * - [6.8.2] Broarcasting on the condition variable then waiting for - * the threads to terminate in priority order, the order is tested. - * . - */ - -static void test_006_008_setup(void) { - chCondObjectInit(&c1); - chMtxObjectInit(&m1); -} - -static void test_006_008_execute(void) { - - /* [6.8.1] Starting the five threads with increasing priority, the - threads will queue on the condition variable.*/ - test_set_step(1); - { - tprio_t prio = chThdGetPriorityX(); - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread6, "E"); - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread6, "D"); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread6, "C"); - threads[3] = chThdCreateStatic(wa[3], WA_SIZE, prio+4, thread6, "B"); - threads[4] = chThdCreateStatic(wa[4], WA_SIZE, prio+5, thread6, "A"); - } - - /* [6.8.2] Broarcasting on the condition variable then waiting for - the threads to terminate in priority order, the order is tested.*/ - test_set_step(2); - { - chCondBroadcast(&c1); - test_wait_threads(); - test_assert_sequence("ABCDE", "invalid sequence"); - } -} - -static const testcase_t test_006_008 = { - "Condition Variable broadcast test", - test_006_008_setup, - NULL, - test_006_008_execute -}; -#endif /* CH_CFG_USE_CONDVARS */ - -#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) -/** - * @page test_006_009 [6.9] Condition Variable priority boost test - * - *

Description

- * This test case verifies the priority boost of a thread waiting on a - * conditional variable queue. It tests this very specific situation in - * order to improve code coverage. The created threads perform the - * following operations: TA{lock(M2), lock(M1), wait(C1), unlock(M1), - * unlock(M2)}, TB{lock(M2), wait(C1), unlock(M2)}. TC{lock(M1), - * unlock(M1)}. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_CONDVARS - * . - * - *

Test Steps

- * - [6.9.1] Reading current base priority. - * - [6.9.2] Thread A is created at priority P(+1), it locks M2, locks - * M1 and goes to wait on C1. - * - [6.9.3] Thread C is created at priority P(+2), it enqueues on M1 - * and boosts TA priority at P(+2). - * - [6.9.4] Thread B is created at priority P(+3), it enqueues on M2 - * and boosts TA priority at P(+3). - * - [6.9.5] Signaling C1: TA wakes up, unlocks M1 and priority goes to - * P(+2). TB locks M1, unlocks M1 and completes. TA unlocks M2 and - * priority goes to P(+1). TC waits on C1. TA completes. - * - [6.9.6] Signaling C1: TC wakes up, unlocks M1 and completes. - * - [6.9.7] Checking the order of operations. - * . - */ - -static void test_006_009_setup(void) { - chCondObjectInit(&c1); - chMtxObjectInit(&m1); - chMtxObjectInit(&m2); -} - -static void test_006_009_execute(void) { - tprio_t prio; - - /* [6.9.1] Reading current base priority.*/ - test_set_step(1); - { - prio = chThdGetPriorityX(); - } - - /* [6.9.2] Thread A is created at priority P(+1), it locks M2, locks - M1 and goes to wait on C1.*/ - test_set_step(2); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, prio+1, thread8, "A"); - } - - /* [6.9.3] Thread C is created at priority P(+2), it enqueues on M1 - and boosts TA priority at P(+2).*/ - test_set_step(3); - { - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, prio+2, thread6, "C"); - } - - /* [6.9.4] Thread B is created at priority P(+3), it enqueues on M2 - and boosts TA priority at P(+3).*/ - test_set_step(4); - { - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, prio+3, thread9, "B"); - } - - /* [6.9.5] Signaling C1: TA wakes up, unlocks M1 and priority goes to - P(+2). TB locks M1, unlocks M1 and completes. TA unlocks M2 and - priority goes to P(+1). TC waits on C1. TA completes.*/ - test_set_step(5); - { - chCondSignal(&c1); - } - - /* [6.9.6] Signaling C1: TC wakes up, unlocks M1 and completes.*/ - test_set_step(6); - { - chCondSignal(&c1); - } - - /* [6.9.7] Checking the order of operations.*/ - test_set_step(7); - { - test_wait_threads(); - test_assert_sequence("ABC", "invalid sequence"); - } -} - -static const testcase_t test_006_009 = { - "Condition Variable priority boost test", - test_006_009_setup, - NULL, - test_006_009_execute -}; -#endif /* CH_CFG_USE_CONDVARS */ - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Mutexes, Condition Variables and Priority Inheritance. - */ -const testcase_t * const test_sequence_006[] = { - &test_006_001, -#if (CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) - &test_006_002, -#endif -#if (CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) - &test_006_003, -#endif - &test_006_004, -#if (!CH_CFG_USE_MUTEXES_RECURSIVE) || defined(__DOXYGEN__) - &test_006_005, -#endif -#if (CH_CFG_USE_MUTEXES_RECURSIVE) || defined(__DOXYGEN__) - &test_006_006, -#endif -#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) - &test_006_007, -#endif -#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) - &test_006_008, -#endif -#if (CH_CFG_USE_CONDVARS) || defined(__DOXYGEN__) - &test_006_009, -#endif - NULL -}; - -#endif /* CH_CFG_USE_MUTEXES */ diff --git a/test/rt/source/test/test_sequence_006.h b/test/rt/source/test/test_sequence_006.h deleted file mode 100644 index 959689dc1..000000000 --- a/test/rt/source/test/test_sequence_006.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_006.h - * @brief Test Sequence 006 header. - */ - -#ifndef TEST_SEQUENCE_006_H -#define TEST_SEQUENCE_006_H - -extern const testcase_t * const test_sequence_006[]; - -#endif /* TEST_SEQUENCE_006_H */ diff --git a/test/rt/source/test/test_sequence_007.c b/test/rt/source/test/test_sequence_007.c deleted file mode 100644 index e472cac4e..000000000 --- a/test/rt/source/test/test_sequence_007.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_007.c - * @brief Test Sequence 007 code. - * - * @page test_sequence_007 [7] Synchronous Messages - * - * File: @ref test_sequence_007.c - * - *

Description

- * This module implements the test sequence for the Synchronous - * Messages subsystem. - * - *

Conditions

- * This sequence is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MESSAGES - * . - * - *

Test Cases

- * - @subpage test_007_001 - * . - */ - -#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -static THD_FUNCTION(msg_thread1, p) { - - chMsgSend(p, 'A'); - chMsgSend(p, 'B'); - chMsgSend(p, 'C'); - chMsgSend(p, 'D'); -} - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -/** - * @page test_007_001 [7.1] Messages Server loop - * - *

Description

- * A messenger thread is spawned that sends four messages back to the - * tester thread.
The test expect to receive the messages in the - * correct sequence and to not find a fifth message waiting. - * - *

Test Steps

- * - [7.1.1] Starting the messenger thread. - * - [7.1.2] Waiting for four messages then testing the receive order. - * . - */ - -static void test_007_001_execute(void) { - thread_t *tp; - msg_t msg; - - /* [7.1.1] Starting the messenger thread.*/ - test_set_step(1); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() + 1, - msg_thread1, chThdGetSelfX()); - } - - /* [7.1.2] Waiting for four messages then testing the receive - order.*/ - test_set_step(2); - { - unsigned i; - - for (i = 0; i < 4; i++) { - tp = chMsgWait(); - msg = chMsgGet(tp); - chMsgRelease(tp, msg); - test_emit_token(msg); - } - test_wait_threads(); - test_assert_sequence("ABCD", "invalid sequence"); - } -} - -static const testcase_t test_007_001 = { - "Messages Server loop", - NULL, - NULL, - test_007_001_execute -}; - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Synchronous Messages. - */ -const testcase_t * const test_sequence_007[] = { - &test_007_001, - NULL -}; - -#endif /* CH_CFG_USE_MESSAGES */ diff --git a/test/rt/source/test/test_sequence_007.h b/test/rt/source/test/test_sequence_007.h deleted file mode 100644 index b0b926223..000000000 --- a/test/rt/source/test/test_sequence_007.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_007.h - * @brief Test Sequence 007 header. - */ - -#ifndef TEST_SEQUENCE_007_H -#define TEST_SEQUENCE_007_H - -extern const testcase_t * const test_sequence_007[]; - -#endif /* TEST_SEQUENCE_007_H */ diff --git a/test/rt/source/test/test_sequence_008.c b/test/rt/source/test/test_sequence_008.c deleted file mode 100644 index 6ae56aa7a..000000000 --- a/test/rt/source/test/test_sequence_008.c +++ /dev/null @@ -1,569 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_008.c - * @brief Test Sequence 008 code. - * - * @page test_sequence_008 [8] Event Sources and Event Flags - * - * File: @ref test_sequence_008.c - * - *

Description

- * This module implements the test sequence for the Events subsystem. - * - *

Conditions

- * This sequence is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_EVENTS - * . - * - *

Test Cases

- * - @subpage test_008_001 - * - @subpage test_008_002 - * - @subpage test_008_003 - * - @subpage test_008_004 - * - @subpage test_008_005 - * - @subpage test_008_006 - * - @subpage test_008_007 - * . - */ - -#if (CH_CFG_USE_EVENTS) || defined(__DOXYGEN__) - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -static EVENTSOURCE_DECL(es1); -static EVENTSOURCE_DECL(es2); - -static void h1(eventid_t id) {(void)id;test_emit_token('A');} -static void h2(eventid_t id) {(void)id;test_emit_token('B');} -static void h3(eventid_t id) {(void)id;test_emit_token('C');} -static ROMCONST evhandler_t evhndl[] = {h1, h2, h3}; - -static THD_FUNCTION(evt_thread3, p) { - - chThdSleepMilliseconds(50); - chEvtSignal((thread_t *)p, 1); -} - -static THD_FUNCTION(evt_thread7, p) { - - (void)p; - chEvtBroadcast(&es1); - chThdSleepMilliseconds(50); - chEvtBroadcast(&es2); -} - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -/** - * @page test_008_001 [8.1] Events registration - * - *

Description

- * Two event listeners are registered on an event source and then - * unregistered in the same order.
The test expects that the even - * source has listeners after the registrations and after the first - * unregistration, then, after the second unegistration, the test - * expects no more listeners. - * - *

Test Steps

- * - [8.1.1] An Event Source is initialized. - * - [8.1.2] Two Event Listeners are registered on the Event Source, - * the Event Source is tested to have listeners. - * - [8.1.3] An Event Listener is unregistered, the Event Source must - * still have listeners. - * - [8.1.4] An Event Listener is unregistered, the Event Source must - * not have listeners. - * . - */ - -static void test_008_001_execute(void) { - event_listener_t el1, el2; - - /* [8.1.1] An Event Source is initialized.*/ - test_set_step(1); - { - chEvtObjectInit(&es1); - } - - /* [8.1.2] Two Event Listeners are registered on the Event Source, - the Event Source is tested to have listeners.*/ - test_set_step(2); - { - chEvtRegisterMask(&es1, &el1, 1); - chEvtRegisterMask(&es1, &el2, 2); - test_assert_lock(chEvtIsListeningI(&es1), "no listener"); - } - - /* [8.1.3] An Event Listener is unregistered, the Event Source must - still have listeners.*/ - test_set_step(3); - { - chEvtUnregister(&es1, &el1); - test_assert_lock(chEvtIsListeningI(&es1), "no listener"); - } - - /* [8.1.4] An Event Listener is unregistered, the Event Source must - not have listeners.*/ - test_set_step(4); - { - chEvtUnregister(&es1, &el2); - test_assert_lock(!chEvtIsListeningI(&es1), "stuck listener"); - } -} - -static const testcase_t test_008_001 = { - "Events registration", - NULL, - NULL, - test_008_001_execute -}; - -/** - * @page test_008_002 [8.2] Event Flags dispatching - * - *

Description

- * The test dispatches three event flags and verifies that the - * associated event handlers are invoked in LSb-first order. - * - *

Test Steps

- * - [8.2.1] Three evenf flag bits are raised then chEvtDispatch() is - * invoked, the sequence of handlers calls is tested. - * . - */ - -static void test_008_002_setup(void) { - chEvtGetAndClearEvents(ALL_EVENTS); -} - -static void test_008_002_execute(void) { - - /* [8.2.1] Three evenf flag bits are raised then chEvtDispatch() is - invoked, the sequence of handlers calls is tested.*/ - test_set_step(1); - { - chEvtDispatch(evhndl, 7); - test_assert_sequence("ABC", "invalid sequence"); - } -} - -static const testcase_t test_008_002 = { - "Event Flags dispatching", - test_008_002_setup, - NULL, - test_008_002_execute -}; - -/** - * @page test_008_003 [8.3] Events Flags wait using chEvtWaitOne() - * - *

Description

- * Functionality of chEvtWaitOne() is tested under various scenarios. - * - *

Test Steps

- * - [8.3.1] Setting three event flags. - * - [8.3.2] Calling chEvtWaitOne() three times, each time a single - * flag must be returned in order of priority. - * - [8.3.3] Getting current time and starting a signaler thread, the - * thread will set an event flag after 50mS. - * - [8.3.4] Calling chEvtWaitOne() then verifying that the event has - * been received after 50mS and that the event flags mask has been - * emptied. - * . - */ - -static void test_008_003_setup(void) { - chEvtGetAndClearEvents(ALL_EVENTS); -} - -static void test_008_003_execute(void) { - eventmask_t m; - systime_t target_time; - - /* [8.3.1] Setting three event flags.*/ - test_set_step(1); - { - chEvtAddEvents(7); - } - - /* [8.3.2] Calling chEvtWaitOne() three times, each time a single - flag must be returned in order of priority.*/ - test_set_step(2); - { - m = chEvtWaitOne(ALL_EVENTS); - test_assert(m == 1, "single event error"); - m = chEvtWaitOne(ALL_EVENTS); - test_assert(m == 2, "single event error"); - m = chEvtWaitOne(ALL_EVENTS); - test_assert(m == 4, "single event error"); - m = chEvtGetAndClearEvents(ALL_EVENTS); - test_assert(m == 0, "stuck event"); - } - - /* [8.3.3] Getting current time and starting a signaler thread, the - thread will set an event flag after 50mS.*/ - test_set_step(3); - { - target_time = test_wait_tick() + MS2ST(50); - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, - evt_thread3, chThdGetSelfX()); - } - - /* [8.3.4] Calling chEvtWaitOne() then verifying that the event has - been received after 50mS and that the event flags mask has been - emptied.*/ - test_set_step(4); - { - m = chEvtWaitOne(ALL_EVENTS); - test_assert_time_window(target_time, target_time + ALLOWED_DELAY, - "out of time window"); - test_assert(m == 1, "event flag error"); - m = chEvtGetAndClearEvents(ALL_EVENTS); - test_assert(m == 0, "stuck event"); - test_wait_threads(); - } -} - -static const testcase_t test_008_003 = { - "Events Flags wait using chEvtWaitOne()", - test_008_003_setup, - NULL, - test_008_003_execute -}; - -/** - * @page test_008_004 [8.4] Events Flags wait using chEvtWaitAny() - * - *

Description

- * Functionality of chEvtWaitAny() is tested under various scenarios. - * - *

Test Steps

- * - [8.4.1] Setting two, non contiguous, event flags. - * - [8.4.2] Calling chEvtWaitAny() one time, the two flags must be - * returned. - * - [8.4.3] Getting current time and starting a signaler thread, the - * thread will set an event flag after 50mS. - * - [8.4.4] Calling chEvtWaitAny() then verifying that the event has - * been received after 50mS and that the event flags mask has been - * emptied. - * . - */ - -static void test_008_004_setup(void) { - chEvtGetAndClearEvents(ALL_EVENTS); -} - -static void test_008_004_execute(void) { - eventmask_t m; - systime_t target_time; - - /* [8.4.1] Setting two, non contiguous, event flags.*/ - test_set_step(1); - { - chEvtAddEvents(5); - } - - /* [8.4.2] Calling chEvtWaitAny() one time, the two flags must be - returned.*/ - test_set_step(2); - { - m = chEvtWaitAny(ALL_EVENTS); - test_assert(m == 5, "unexpected pending bit"); - m = chEvtGetAndClearEvents(ALL_EVENTS); - test_assert(m == 0, "stuck event"); - } - - /* [8.4.3] Getting current time and starting a signaler thread, the - thread will set an event flag after 50mS.*/ - test_set_step(3); - { - target_time = test_wait_tick() + MS2ST(50); - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, - evt_thread3, chThdGetSelfX()); - } - - /* [8.4.4] Calling chEvtWaitAny() then verifying that the event has - been received after 50mS and that the event flags mask has been - emptied.*/ - test_set_step(4); - { - m = chEvtWaitAny(ALL_EVENTS); - test_assert_time_window(target_time, target_time + ALLOWED_DELAY, - "out of time window"); - test_assert(m == 1, "event flag error"); - m = chEvtGetAndClearEvents(ALL_EVENTS); - test_assert(m == 0, "stuck event"); - test_wait_threads(); - } -} - -static const testcase_t test_008_004 = { - "Events Flags wait using chEvtWaitAny()", - test_008_004_setup, - NULL, - test_008_004_execute -}; - -/** - * @page test_008_005 [8.5] Events Flags wait using chEvtWaitAll() - * - *

Description

- * Functionality of chEvtWaitAll() is tested under various scenarios. - * - *

Test Steps

- * - [8.5.1] Setting two, non contiguous, event flags. - * - [8.5.2] Calling chEvtWaitAll() one time, the two flags must be - * returned. - * - [8.5.3] Setting one event flag. - * - [8.5.4] Getting current time and starting a signaler thread, the - * thread will set another event flag after 50mS. - * - [8.5.5] Calling chEvtWaitAll() then verifying that both event - * flags have been received after 50mS and that the event flags mask - * has been emptied. - * . - */ - -static void test_008_005_setup(void) { - chEvtGetAndClearEvents(ALL_EVENTS); -} - -static void test_008_005_execute(void) { - eventmask_t m; - systime_t target_time; - - /* [8.5.1] Setting two, non contiguous, event flags.*/ - test_set_step(1); - { - chEvtAddEvents(5); - } - - /* [8.5.2] Calling chEvtWaitAll() one time, the two flags must be - returned.*/ - test_set_step(2); - { - m = chEvtWaitAll(5); - test_assert(m == 5, "unexpected pending bit"); - m = chEvtGetAndClearEvents(ALL_EVENTS); - test_assert(m == 0, "stuck event"); - } - - /* [8.5.3] Setting one event flag.*/ - test_set_step(3); - { - chEvtAddEvents(4); - } - - /* [8.5.4] Getting current time and starting a signaler thread, the - thread will set another event flag after 50mS.*/ - test_set_step(4); - { - target_time = test_wait_tick() + MS2ST(50); - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, - evt_thread3, chThdGetSelfX()); - } - - /* [8.5.5] Calling chEvtWaitAll() then verifying that both event - flags have been received after 50mS and that the event flags mask - has been emptied.*/ - test_set_step(5); - { - m = chEvtWaitAll(5); - test_assert_time_window(target_time, target_time + ALLOWED_DELAY, - "out of time window"); - test_assert(m == 5, "event flags error"); - m = chEvtGetAndClearEvents(ALL_EVENTS); - test_assert(m == 0, "stuck event"); - test_wait_threads(); - } -} - -static const testcase_t test_008_005 = { - "Events Flags wait using chEvtWaitAll()", - test_008_005_setup, - NULL, - test_008_005_execute -}; - -#if (CH_CFG_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__) -/** - * @page test_008_006 [8.6] Events Flags wait timeouts - * - *

Description

- * Timeout functionality is tested for chEvtWaitOneTimeout(), - * chEvtWaitAnyTimeout() and chEvtWaitAllTimeout(). - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_EVENTS_TIMEOUT - * . - * - *

Test Steps

- * - [8.6.1] The functions are invoked first with TIME_IMMEDIATE - * timeout, the timeout condition is tested. - * - [8.6.2] The functions are invoked first with a 50mS timeout, the - * timeout condition is tested. - * . - */ - -static void test_008_006_setup(void) { - chEvtGetAndClearEvents(ALL_EVENTS); -} - -static void test_008_006_execute(void) { - eventmask_t m; - - /* [8.6.1] The functions are invoked first with TIME_IMMEDIATE - timeout, the timeout condition is tested.*/ - test_set_step(1); - { - m = chEvtWaitOneTimeout(ALL_EVENTS, TIME_IMMEDIATE); - test_assert(m == 0, "spurious event"); - m = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_IMMEDIATE); - test_assert(m == 0, "spurious event"); - m = chEvtWaitAllTimeout(ALL_EVENTS, TIME_IMMEDIATE); - test_assert(m == 0, "spurious event"); - } - - /* [8.6.2] The functions are invoked first with a 50mS timeout, the - timeout condition is tested.*/ - test_set_step(2); - { - m = chEvtWaitOneTimeout(ALL_EVENTS, MS2ST(50)); - test_assert(m == 0, "spurious event"); - m = chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(50)); - test_assert(m == 0, "spurious event"); - m = chEvtWaitAllTimeout(ALL_EVENTS, MS2ST(50)); - test_assert(m == 0, "spurious event"); - } -} - -static const testcase_t test_008_006 = { - "Events Flags wait timeouts", - test_008_006_setup, - NULL, - test_008_006_execute -}; -#endif /* CH_CFG_USE_EVENTS_TIMEOUT */ - -/** - * @page test_008_007 [8.7] Broadcasting using chEvtBroadcast() - * - *

Description

- * Functionality of chEvtBroadcast() is tested. - * - *

Test Steps

- * - [8.7.1] Registering on two event sources associating them with - * flags 1 and 4. - * - [8.7.2] Getting current time and starting a broadcaster thread, - * the thread broadcast the first Event Source immediately and the - * other after 50mS. - * - [8.7.3] Calling chEvtWaitAll() then verifying that both event - * flags have been received after 50mS and that the event flags mask - * has been emptied. - * - [8.7.4] Unregistering from the Event Sources. - * . - */ - -static void test_008_007_setup(void) { - chEvtGetAndClearEvents(ALL_EVENTS); - chEvtObjectInit(&es1); - chEvtObjectInit(&es2); -} - -static void test_008_007_execute(void) { - eventmask_t m; - event_listener_t el1, el2; - systime_t target_time; - - /* [8.7.1] Registering on two event sources associating them with - flags 1 and 4.*/ - test_set_step(1); - { - chEvtRegisterMask(&es1, &el1, 1); - chEvtRegisterMask(&es2, &el2, 4); - } - - /* [8.7.2] Getting current time and starting a broadcaster thread, - the thread broadcast the first Event Source immediately and the - other after 50mS.*/ - test_set_step(2); - { - target_time = test_wait_tick() + MS2ST(50); - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1, - evt_thread7, "A"); - } - - /* [8.7.3] Calling chEvtWaitAll() then verifying that both event - flags have been received after 50mS and that the event flags mask - has been emptied.*/ - test_set_step(3); - { - m = chEvtWaitAll(5); - test_assert_time_window(target_time, target_time + ALLOWED_DELAY, - "out of time window"); - m = chEvtGetAndClearEvents(ALL_EVENTS); - test_assert(m == 0, "stuck event"); - test_wait_threads(); - } - - /* [8.7.4] Unregistering from the Event Sources.*/ - test_set_step(4); - { - chEvtUnregister(&es1, &el1); - chEvtUnregister(&es2, &el2); - test_assert(!chEvtIsListeningI(&es1), "stuck listener"); - test_assert(!chEvtIsListeningI(&es2), "stuck listener"); - } -} - -static const testcase_t test_008_007 = { - "Broadcasting using chEvtBroadcast()", - test_008_007_setup, - NULL, - test_008_007_execute -}; - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Event Sources and Event Flags. - */ -const testcase_t * const test_sequence_008[] = { - &test_008_001, - &test_008_002, - &test_008_003, - &test_008_004, - &test_008_005, -#if (CH_CFG_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__) - &test_008_006, -#endif - &test_008_007, - NULL -}; - -#endif /* CH_CFG_USE_EVENTS */ diff --git a/test/rt/source/test/test_sequence_008.h b/test/rt/source/test/test_sequence_008.h deleted file mode 100644 index 5824b2cc1..000000000 --- a/test/rt/source/test/test_sequence_008.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_008.h - * @brief Test Sequence 008 header. - */ - -#ifndef TEST_SEQUENCE_008_H -#define TEST_SEQUENCE_008_H - -extern const testcase_t * const test_sequence_008[]; - -#endif /* TEST_SEQUENCE_008_H */ diff --git a/test/rt/source/test/test_sequence_009.c b/test/rt/source/test/test_sequence_009.c deleted file mode 100644 index 92ec11b77..000000000 --- a/test/rt/source/test/test_sequence_009.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_009.c - * @brief Test Sequence 009 code. - * - * @page test_sequence_009 [9] Mailboxes - * - * File: @ref test_sequence_009.c - * - *

Description

- * This sequence tests the ChibiOS/RT functionalities related to - * mailboxes. - * - *

Conditions

- * This sequence is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MAILBOXES - * . - * - *

Test Cases

- * - @subpage test_009_001 - * - @subpage test_009_002 - * - @subpage test_009_003 - * . - */ - -#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__) - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -#define MB_SIZE 4 - -static msg_t mb_buffer[MB_SIZE]; -static MAILBOX_DECL(mb1, mb_buffer, MB_SIZE); - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -/** - * @page test_009_001 [9.1] Mailbox normal API, non-blocking tests - * - *

Description

- * The mailbox normal API is tested without triggering blocking - * conditions. - * - *

Test Steps

- * - [9.1.1] Testing the mailbox size. - * - [9.1.2] Resetting the mailbox, conditions are checked, no errors - * expected. - * - [9.1.3] Testing the behavior of API when the mailbox is in reset - * state then return in active state. - * - [9.1.4] Filling the mailbox using chMBPostTimeout() and - * chMBPostAheadTimeout() once, no errors expected. - * - [9.1.5] Testing intermediate conditions. Data pointers must be - * aligned, semaphore counters are checked. - * - [9.1.6] Emptying the mailbox using chMBFetchTimeout(), no errors - * expected. - * - [9.1.7] Posting and then fetching one more message, no errors - * expected. - * - [9.1.8] Testing final conditions. Data pointers must be aligned to - * buffer start, semaphore counters are checked. - * . - */ - -static void test_009_001_setup(void) { - chMBObjectInit(&mb1, mb_buffer, MB_SIZE); -} - -static void test_009_001_teardown(void) { - chMBReset(&mb1); -} - -static void test_009_001_execute(void) { - msg_t msg1, msg2; - unsigned i; - - /* [9.1.1] Testing the mailbox size.*/ - test_set_step(1); - { - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size"); - } - - /* [9.1.2] Resetting the mailbox, conditions are checked, no errors - expected.*/ - test_set_step(2); - { - chMBReset(&mb1); - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); - test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); - test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); - } - - /* [9.1.3] Testing the behavior of API when the mailbox is in reset - state then return in active state.*/ - test_set_step(3); - { - msg1 = chMBPostTimeout(&mb1, (msg_t)0, TIME_INFINITE); - test_assert(msg1 == MSG_RESET, "not in reset state"); - msg1 = chMBPostAheadTimeout(&mb1, (msg_t)0, TIME_INFINITE); - test_assert(msg1 == MSG_RESET, "not in reset state"); - msg1 = chMBFetchTimeout(&mb1, &msg2, TIME_INFINITE); - test_assert(msg1 == MSG_RESET, "not in reset state"); - chMBResumeX(&mb1); - } - - /* [9.1.4] Filling the mailbox using chMBPostTimeout() and - chMBPostAheadTimeout() once, no errors expected.*/ - test_set_step(4); - { - for (i = 0; i < MB_SIZE - 1; i++) { - msg1 = chMBPostTimeout(&mb1, 'B' + i, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - msg1 = chMBPostAheadTimeout(&mb1, 'A', TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - - /* [9.1.5] Testing intermediate conditions. Data pointers must be - aligned, semaphore counters are checked.*/ - test_set_step(5); - { - test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full"); - test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned"); - } - - /* [9.1.6] Emptying the mailbox using chMBFetchTimeout(), no errors - expected.*/ - test_set_step(6); - { - for (i = 0; i < MB_SIZE; i++) { - msg1 = chMBFetchTimeout(&mb1, &msg2, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - test_emit_token(msg2); - } - test_assert_sequence("ABCD", "wrong get sequence"); - } - - /* [9.1.7] Posting and then fetching one more message, no errors - expected.*/ - test_set_step(7); - { - msg1 = chMBPostTimeout(&mb1, 'B' + i, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - msg1 = chMBFetchTimeout(&mb1, &msg2, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - - /* [9.1.8] Testing final conditions. Data pointers must be aligned to - buffer start, semaphore counters are checked.*/ - test_set_step(8); - { - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); - test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); - test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); - } -} - -static const testcase_t test_009_001 = { - "Mailbox normal API, non-blocking tests", - test_009_001_setup, - test_009_001_teardown, - test_009_001_execute -}; - -/** - * @page test_009_002 [9.2] Mailbox I-Class API, non-blocking tests - * - *

Description

- * The mailbox I-Class API is tested without triggering blocking - * conditions. - * - *

Test Steps

- * - [9.2.1] Testing the mailbox size. - * - [9.2.2] Resetting the mailbox, conditions are checked, no errors - * expected. The mailbox is then returned in active state. - * - [9.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI() - * once, no errors expected. - * - [9.2.4] Testing intermediate conditions. Data pointers must be - * aligned, semaphore counters are checked. - * - [9.2.5] Emptying the mailbox using chMBFetchI(), no errors - * expected. - * - [9.2.6] Posting and then fetching one more message, no errors - * expected. - * - [9.2.7] Testing final conditions. Data pointers must be aligned to - * buffer start, semaphore counters are checked. - * . - */ - -static void test_009_002_setup(void) { - chMBObjectInit(&mb1, mb_buffer, MB_SIZE); -} - -static void test_009_002_teardown(void) { - chMBReset(&mb1); -} - -static void test_009_002_execute(void) { - msg_t msg1, msg2; - unsigned i; - - /* [9.2.1] Testing the mailbox size.*/ - test_set_step(1); - { - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size"); - } - - /* [9.2.2] Resetting the mailbox, conditions are checked, no errors - expected. The mailbox is then returned in active state.*/ - test_set_step(2); - { - chSysLock(); - chMBResetI(&mb1); - chSysUnlock(); - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); - test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); - test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); - chMBResumeX(&mb1); - } - - /* [9.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI() - once, no errors expected.*/ - test_set_step(3); - { - for (i = 0; i < MB_SIZE - 1; i++) { - chSysLock(); - msg1 = chMBPostI(&mb1, 'B' + i); - chSysUnlock(); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - chSysLock(); - msg1 = chMBPostAheadI(&mb1, 'A'); - chSysUnlock(); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - - /* [9.2.4] Testing intermediate conditions. Data pointers must be - aligned, semaphore counters are checked.*/ - test_set_step(4); - { - test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full"); - test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned"); - } - - /* [9.2.5] Emptying the mailbox using chMBFetchI(), no errors - expected.*/ - test_set_step(5); - { - for (i = 0; i < MB_SIZE; i++) { - chSysLock(); - msg1 = chMBFetchI(&mb1, &msg2); - chSysUnlock(); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - test_emit_token(msg2); - } - test_assert_sequence("ABCD", "wrong get sequence"); - } - - /* [9.2.6] Posting and then fetching one more message, no errors - expected.*/ - test_set_step(6); - { - msg1 = chMBPostTimeout(&mb1, 'B' + i, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - msg1 = chMBFetchTimeout(&mb1, &msg2, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - - /* [9.2.7] Testing final conditions. Data pointers must be aligned to - buffer start, semaphore counters are checked.*/ - test_set_step(7); - { - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); - test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); - test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); - } -} - -static const testcase_t test_009_002 = { - "Mailbox I-Class API, non-blocking tests", - test_009_002_setup, - test_009_002_teardown, - test_009_002_execute -}; - -/** - * @page test_009_003 [9.3] Mailbox timeouts - * - *

Description

- * The mailbox API is tested for timeouts. - * - *

Test Steps

- * - [9.3.1] Filling the mailbox. - * - [9.3.2] Testing chMBPostTimeout(), chMBPostI(), - * chMBPostAheadTimeout() and chMBPostAheadI() timeout. - * - [9.3.3] Resetting the mailbox. The mailbox is then returned in - * active state. - * - [9.3.4] Testing chMBFetchTimeout() and chMBFetchI() timeout. - * . - */ - -static void test_009_003_setup(void) { - chMBObjectInit(&mb1, mb_buffer, MB_SIZE); -} - -static void test_009_003_teardown(void) { - chMBReset(&mb1); -} - -static void test_009_003_execute(void) { - msg_t msg1, msg2; - unsigned i; - - /* [9.3.1] Filling the mailbox.*/ - test_set_step(1); - { - for (i = 0; i < MB_SIZE; i++) { - msg1 = chMBPostTimeout(&mb1, 'B' + i, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - } - - /* [9.3.2] Testing chMBPostTimeout(), chMBPostI(), - chMBPostAheadTimeout() and chMBPostAheadI() timeout.*/ - test_set_step(2); - { - msg1 = chMBPostTimeout(&mb1, 'X', 1); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - chSysLock(); - msg1 = chMBPostI(&mb1, 'X'); - chSysUnlock(); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - msg1 = chMBPostAheadTimeout(&mb1, 'X', 1); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - chSysLock(); - msg1 = chMBPostAheadI(&mb1, 'X'); - chSysUnlock(); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - } - - /* [9.3.3] Resetting the mailbox. The mailbox is then returned in - active state.*/ - test_set_step(3); - { - chMBReset(&mb1); - chMBResumeX(&mb1); - } - - /* [9.3.4] Testing chMBFetchTimeout() and chMBFetchI() timeout.*/ - test_set_step(4); - { - msg1 = chMBFetchTimeout(&mb1, &msg2, 1); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - chSysLock(); - msg1 = chMBFetchI(&mb1, &msg2); - chSysUnlock(); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - } -} - -static const testcase_t test_009_003 = { - "Mailbox timeouts", - test_009_003_setup, - test_009_003_teardown, - test_009_003_execute -}; - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Mailboxes. - */ -const testcase_t * const test_sequence_009[] = { - &test_009_001, - &test_009_002, - &test_009_003, - NULL -}; - -#endif /* CH_CFG_USE_MAILBOXES */ diff --git a/test/rt/source/test/test_sequence_009.h b/test/rt/source/test/test_sequence_009.h deleted file mode 100644 index 81eaa7aaa..000000000 --- a/test/rt/source/test/test_sequence_009.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_009.h - * @brief Test Sequence 009 header. - */ - -#ifndef TEST_SEQUENCE_009_H -#define TEST_SEQUENCE_009_H - -extern const testcase_t * const test_sequence_009[]; - -#endif /* TEST_SEQUENCE_009_H */ diff --git a/test/rt/source/test/test_sequence_010.c b/test/rt/source/test/test_sequence_010.c deleted file mode 100644 index ebdf7acac..000000000 --- a/test/rt/source/test/test_sequence_010.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_010.c - * @brief Test Sequence 010 code. - * - * @page test_sequence_010 [10] Memory Pools - * - * File: @ref test_sequence_010.c - * - *

Description

- * This sequence tests the ChibiOS/RT functionalities related to memory - * pools. - * - *

Conditions

- * This sequence is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MEMPOOLS - * . - * - *

Test Cases

- * - @subpage test_010_001 - * - @subpage test_010_002 - * - @subpage test_010_003 - * . - */ - -#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -#define MEMORY_POOL_SIZE 4 - -static uint32_t objects[MEMORY_POOL_SIZE]; -static MEMORYPOOL_DECL(mp1, sizeof (uint32_t), PORT_NATURAL_ALIGN, NULL); - -#if CH_CFG_USE_SEMAPHORES -static GUARDEDMEMORYPOOL_DECL(gmp1, sizeof (uint32_t), PORT_NATURAL_ALIGN); -#endif - -static void *null_provider(size_t size, unsigned align) { - - (void)size; - (void)align; - - return NULL; -} - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -/** - * @page test_010_001 [10.1] Loading and emptying a memory pool - * - *

Description

- * The memory pool functionality is tested by loading and emptying it, - * all conditions are tested. - * - *

Test Steps

- * - [10.1.1] Adding the objects to the pool using chPoolLoadArray(). - * - [10.1.2] Emptying the pool using chPoolAlloc(). - * - [10.1.3] Now must be empty. - * - [10.1.4] Adding the objects to the pool using chPoolFree(). - * - [10.1.5] Emptying the pool using chPoolAlloc() again. - * - [10.1.6] Now must be empty again. - * - [10.1.7] Covering the case where a provider is unable to return - * more memory. - * . - */ - -static void test_010_001_setup(void) { - chPoolObjectInit(&mp1, sizeof (uint32_t), NULL); -} - -static void test_010_001_execute(void) { - unsigned i; - - /* [10.1.1] Adding the objects to the pool using chPoolLoadArray().*/ - test_set_step(1); - { - chPoolLoadArray(&mp1, objects, MEMORY_POOL_SIZE); - } - - /* [10.1.2] Emptying the pool using chPoolAlloc().*/ - test_set_step(2); - { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - test_assert(chPoolAlloc(&mp1) != NULL, "list empty"); - } - - /* [10.1.3] Now must be empty.*/ - test_set_step(3); - { - test_assert(chPoolAlloc(&mp1) == NULL, "list not empty"); - } - - /* [10.1.4] Adding the objects to the pool using chPoolFree().*/ - test_set_step(4); - { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - chPoolFree(&mp1, &objects[i]); - } - - /* [10.1.5] Emptying the pool using chPoolAlloc() again.*/ - test_set_step(5); - { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - test_assert(chPoolAlloc(&mp1) != NULL, "list empty"); - } - - /* [10.1.6] Now must be empty again.*/ - test_set_step(6); - { - test_assert(chPoolAlloc(&mp1) == NULL, "list not empty"); - } - - /* [10.1.7] Covering the case where a provider is unable to return - more memory.*/ - test_set_step(7); - { - chPoolObjectInit(&mp1, sizeof (uint32_t), null_provider); - test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory"); - } -} - -static const testcase_t test_010_001 = { - "Loading and emptying a memory pool", - test_010_001_setup, - NULL, - test_010_001_execute -}; - -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) -/** - * @page test_010_002 [10.2] Loading and emptying a guarded memory pool without waiting - * - *

Description

- * The memory pool functionality is tested by loading and emptying it, - * all conditions are tested. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_SEMAPHORES - * . - * - *

Test Steps

- * - [10.2.1] Adding the objects to the pool using - * chGuardedPoolLoadArray(). - * - [10.2.2] Emptying the pool using chGuardedPoolAllocTimeout(). - * - [10.2.3] Now must be empty. - * - [10.2.4] Adding the objects to the pool using chGuardedPoolFree(). - * - [10.2.5] Emptying the pool using chGuardedPoolAllocTimeout() - * again. - * - [10.2.6] Now must be empty again. - * . - */ - -static void test_010_002_setup(void) { - chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); -} - -static void test_010_002_execute(void) { - unsigned i; - - /* [10.2.1] Adding the objects to the pool using - chGuardedPoolLoadArray().*/ - test_set_step(1); - { - chGuardedPoolLoadArray(&gmp1, objects, MEMORY_POOL_SIZE); - } - - /* [10.2.2] Emptying the pool using chGuardedPoolAllocTimeout().*/ - test_set_step(2); - { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty"); - } - - /* [10.2.3] Now must be empty.*/ - test_set_step(3); - { - test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty"); - } - - /* [10.2.4] Adding the objects to the pool using - chGuardedPoolFree().*/ - test_set_step(4); - { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - chGuardedPoolFree(&gmp1, &objects[i]); - } - - /* [10.2.5] Emptying the pool using chGuardedPoolAllocTimeout() - again.*/ - test_set_step(5); - { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty"); - } - - /* [10.2.6] Now must be empty again.*/ - test_set_step(6); - { - test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty"); - } -} - -static const testcase_t test_010_002 = { - "Loading and emptying a guarded memory pool without waiting", - test_010_002_setup, - NULL, - test_010_002_execute -}; -#endif /* CH_CFG_USE_SEMAPHORES */ - -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) -/** - * @page test_010_003 [10.3] Guarded Memory Pools timeout - * - *

Description

- * The timeout features for the Guarded Memory Pools is tested. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_SEMAPHORES - * . - * - *

Test Steps

- * - [10.3.1] Trying to allocate with 100mS timeout, must fail because - * the pool is empty. - * . - */ - -static void test_010_003_setup(void) { - chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); -} - -static void test_010_003_execute(void) { - - /* [10.3.1] Trying to allocate with 100mS timeout, must fail because - the pool is empty.*/ - test_set_step(1); - { - test_assert(chGuardedPoolAllocTimeout(&gmp1, MS2ST(100)) == NULL, "list not empty"); - } -} - -static const testcase_t test_010_003 = { - "Guarded Memory Pools timeout", - test_010_003_setup, - NULL, - test_010_003_execute -}; -#endif /* CH_CFG_USE_SEMAPHORES */ - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Memory Pools. - */ -const testcase_t * const test_sequence_010[] = { - &test_010_001, -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) - &test_010_002, -#endif -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) - &test_010_003, -#endif - NULL -}; - -#endif /* CH_CFG_USE_MEMPOOLS */ diff --git a/test/rt/source/test/test_sequence_010.h b/test/rt/source/test/test_sequence_010.h deleted file mode 100644 index bd94c5032..000000000 --- a/test/rt/source/test/test_sequence_010.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_010.h - * @brief Test Sequence 010 header. - */ - -#ifndef TEST_SEQUENCE_010_H -#define TEST_SEQUENCE_010_H - -extern const testcase_t * const test_sequence_010[]; - -#endif /* TEST_SEQUENCE_010_H */ diff --git a/test/rt/source/test/test_sequence_011.c b/test/rt/source/test/test_sequence_011.c deleted file mode 100644 index 398e4da3f..000000000 --- a/test/rt/source/test/test_sequence_011.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_011.c - * @brief Test Sequence 011 code. - * - * @page test_sequence_011 [11] Memory Heaps - * - * File: @ref test_sequence_011.c - * - *

Description

- * This sequence tests the ChibiOS/RT functionalities related to memory - * heaps. - * - *

Conditions

- * This sequence is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_HEAP - * . - * - *

Test Cases

- * - @subpage test_011_001 - * - @subpage test_011_002 - * . - */ - -#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -#define ALLOC_SIZE 16 -#define HEAP_SIZE (ALLOC_SIZE * 8) - -memory_heap_t test_heap; - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -/** - * @page test_011_001 [11.1] Allocation and fragmentation - * - *

Description

- * Series of allocations/deallocations are performed in carefully - * designed sequences in order to stimulate all the possible code paths - * inside the allocator. The test expects to find the heap back to the - * initial status after each sequence. - * - *

Test Steps

- * - [11.1.1] Testing initial conditions, the heap must not be - * fragmented and one free block present. - * - [11.1.2] Trying to allocate an block bigger than available space, - * an error is expected. - * - [11.1.3] Single block allocation using chHeapAlloc() then the - * block is freed using chHeapFree(), must not fail. - * - [11.1.4] Using chHeapStatus() to assess the heap state. There must - * be at least one free block of sufficient size. - * - [11.1.5] Allocating then freeing in the same order. - * - [11.1.6] Allocating then freeing in reverse order. - * - [11.1.7] Small fragments handling. Checking the behavior when - * allocating blocks with size not multiple of alignment unit. - * - [11.1.8] Skipping a fragment, the first fragment in the list is - * too small so the allocator must pick the second one. - * - [11.1.9] Allocating the whole available space. - * - [11.1.10] Testing final conditions. The heap geometry must be the - * same than the one registered at beginning. - * . - */ - -static void test_011_001_setup(void) { - chHeapObjectInit(&test_heap, test_buffer, sizeof(test_buffer)); -} - -static void test_011_001_execute(void) { - void *p1, *p2, *p3; - size_t n, sz; - - /* [11.1.1] Testing initial conditions, the heap must not be - fragmented and one free block present.*/ - test_set_step(1); - { - test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented"); - } - - /* [11.1.2] Trying to allocate an block bigger than available space, - an error is expected.*/ - test_set_step(2); - { - p1 = chHeapAlloc(&test_heap, sizeof test_buffer * 2); - test_assert(p1 == NULL, "allocation not failed"); - } - - /* [11.1.3] Single block allocation using chHeapAlloc() then the - block is freed using chHeapFree(), must not fail.*/ - test_set_step(3); - { - p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); - test_assert(p1 != NULL, "allocation failed"); - chHeapFree(p1); - } - - /* [11.1.4] Using chHeapStatus() to assess the heap state. There must - be at least one free block of sufficient size.*/ - test_set_step(4); - { - size_t total_size, largest_size; - - n = chHeapStatus(&test_heap, &total_size, &largest_size); - test_assert(n == 1, "missing free block"); - test_assert(total_size >= ALLOC_SIZE, "unexpected heap state"); - test_assert(total_size == largest_size, "unexpected heap state"); - } - - /* [11.1.5] Allocating then freeing in the same order.*/ - test_set_step(5); - { - p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); - p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); - p3 = chHeapAlloc(&test_heap, ALLOC_SIZE); - chHeapFree(p1); /* Does not merge.*/ - chHeapFree(p2); /* Merges backward.*/ - chHeapFree(p3); /* Merges both sides.*/ - test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented"); - } - - /* [11.1.6] Allocating then freeing in reverse order.*/ - test_set_step(6); - { - p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); - p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); - p3 = chHeapAlloc(&test_heap, ALLOC_SIZE); - chHeapFree(p3); /* Merges forward.*/ - chHeapFree(p2); /* Merges forward.*/ - chHeapFree(p1); /* Merges forward.*/ - test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented"); - } - - /* [11.1.7] Small fragments handling. Checking the behavior when - allocating blocks with size not multiple of alignment unit.*/ - test_set_step(7); - { - p1 = chHeapAlloc(&test_heap, ALLOC_SIZE + 1); - p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); - chHeapFree(p1); - test_assert(chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state"); - p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); - /* Note, the first situation happens when the alignment size is smaller - than the header size, the second in the other cases.*/ - test_assert((chHeapStatus(&test_heap, &n, NULL) == 1) || - (chHeapStatus(&test_heap, &n, NULL) == 2), "heap fragmented"); - chHeapFree(p2); - chHeapFree(p1); - test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented"); - } - - /* [11.1.8] Skipping a fragment, the first fragment in the list is - too small so the allocator must pick the second one.*/ - test_set_step(8); - { - p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); - p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); - chHeapFree(p1); - test_assert( chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state"); - p1 = chHeapAlloc(&test_heap, ALLOC_SIZE * 2); /* Skips first fragment.*/ - chHeapFree(p1); - chHeapFree(p2); - test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented"); - } - - /* [11.1.9] Allocating the whole available space.*/ - test_set_step(9); - { - (void)chHeapStatus(&test_heap, &n, NULL); - p1 = chHeapAlloc(&test_heap, n); - test_assert(p1 != NULL, "allocation failed"); - test_assert(chHeapStatus(&test_heap, NULL, NULL) == 0, "not empty"); - chHeapFree(p1); - } - - /* [11.1.10] Testing final conditions. The heap geometry must be the - same than the one registered at beginning.*/ - test_set_step(10); - { - test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented"); - test_assert(n == sz, "size changed"); - } -} - -static const testcase_t test_011_001 = { - "Allocation and fragmentation", - test_011_001_setup, - NULL, - test_011_001_execute -}; - -/** - * @page test_011_002 [11.2] Default Heap - * - *

Description

- * The default heap is pre-allocated in the system. We test base - * functionality. - * - *

Test Steps

- * - [11.2.1] Single block allocation using chHeapAlloc() then the - * block is freed using chHeapFree(), must not fail. - * - [11.2.2] Testing allocation failure. - * . - */ - -static void test_011_002_execute(void) { - void *p1; - size_t total_size, largest_size; - - /* [11.2.1] Single block allocation using chHeapAlloc() then the - block is freed using chHeapFree(), must not fail.*/ - test_set_step(1); - { - (void)chHeapStatus(NULL, &total_size, &largest_size); - p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); - test_assert(p1 != NULL, "allocation failed"); - chHeapFree(p1); - } - - /* [11.2.2] Testing allocation failure.*/ - test_set_step(2); - { - p1 = chHeapAlloc(NULL, (size_t)-256); - test_assert(p1 == NULL, "allocation not failed"); - } -} - -static const testcase_t test_011_002 = { - "Default Heap", - NULL, - NULL, - test_011_002_execute -}; - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Memory Heaps. - */ -const testcase_t * const test_sequence_011[] = { - &test_011_001, - &test_011_002, - NULL -}; - -#endif /* CH_CFG_USE_HEAP */ diff --git a/test/rt/source/test/test_sequence_011.h b/test/rt/source/test/test_sequence_011.h deleted file mode 100644 index 7f2faedb5..000000000 --- a/test/rt/source/test/test_sequence_011.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_011.h - * @brief Test Sequence 011 header. - */ - -#ifndef TEST_SEQUENCE_011_H -#define TEST_SEQUENCE_011_H - -extern const testcase_t * const test_sequence_011[]; - -#endif /* TEST_SEQUENCE_011_H */ diff --git a/test/rt/source/test/test_sequence_012.c b/test/rt/source/test/test_sequence_012.c deleted file mode 100644 index 35ea29585..000000000 --- a/test/rt/source/test/test_sequence_012.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_012.c - * @brief Test Sequence 012 code. - * - * @page test_sequence_012 [12] Dynamic threads - * - * File: @ref test_sequence_012.c - * - *

Description

- * This module implements the test sequence for the dynamic thread - * creation APIs. - * - *

Conditions

- * This sequence is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_DYNAMIC - * . - * - *

Test Cases

- * - @subpage test_012_001 - * - @subpage test_012_002 - * . - */ - -#if (CH_CFG_USE_DYNAMIC) || defined(__DOXYGEN__) - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -#if CH_CFG_USE_HEAP -static memory_heap_t heap1; -#endif -#if CH_CFG_USE_MEMPOOLS -static memory_pool_t mp1; -#endif - -static THD_FUNCTION(dyn_thread1, p) { - - test_emit_token(*(char *)p); -} - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) -/** - * @page test_012_001 [12.1] Threads creation from Memory Heap - * - *

Description

- * Two threads are started by allocating the memory from the Memory - * Heap then a third thread is started with a huge stack - * requirement.
The test expects the first two threads to - * successfully start and the third one to fail. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_HEAP - * . - * - *

Test Steps

- * - [12.1.1] Getting base priority for threads. - * - [12.1.2] Getting heap info before the test. - * - [12.1.3] Creating thread 1, it is expected to succeed. - * - [12.1.4] Creating thread 2, it is expected to succeed. - * - [12.1.5] Creating thread 3, it is expected to fail. - * - [12.1.6] Letting threads execute then checking the start order and - * freeing memory. - * - [12.1.7] Getting heap info again for verification. - * . - */ - -static void test_012_001_setup(void) { - chHeapObjectInit(&heap1, test_buffer, sizeof test_buffer); -} - -static void test_012_001_execute(void) { - size_t n1, total1, largest1; - size_t n2, total2, largest2; - tprio_t prio; - - /* [12.1.1] Getting base priority for threads.*/ - test_set_step(1); - { - prio = chThdGetPriorityX(); - } - - /* [12.1.2] Getting heap info before the test.*/ - test_set_step(2); - { - n1 = chHeapStatus(&heap1, &total1, &largest1); - test_assert(n1 == 1, "heap fragmented"); - } - - /* [12.1.3] Creating thread 1, it is expected to succeed.*/ - test_set_step(3); - { - threads[0] = chThdCreateFromHeap(&heap1, - THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), - "dyn1", - prio-1, dyn_thread1, "A"); - test_assert(threads[0] != NULL, "thread creation failed"); - } - - /* [12.1.4] Creating thread 2, it is expected to succeed.*/ - test_set_step(4); - { - threads[1] = chThdCreateFromHeap(&heap1, - THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), - "dyn2", - prio-2, dyn_thread1, "B"); - test_assert(threads[1] != NULL, "thread creation failed"); - } - - /* [12.1.5] Creating thread 3, it is expected to fail.*/ - test_set_step(5); - { - threads[2] = chThdCreateFromHeap(&heap1, - THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE * 1024), - "dyn3", - prio-3, dyn_thread1, "C"); - test_assert(threads[2] == NULL, "thread creation not failed"); - } - - /* [12.1.6] Letting threads execute then checking the start order and - freeing memory.*/ - test_set_step(6); - { - test_wait_threads(); - test_assert_sequence("AB", "invalid sequence"); - } - - /* [12.1.7] Getting heap info again for verification.*/ - test_set_step(7); - { - n2 = chHeapStatus(&heap1, &total2, &largest2); - test_assert(n1 == n2, "fragmentation changed"); - test_assert(total1 == total2, "total free space changed"); - test_assert(largest1 == largest2, "largest fragment size changed"); - } -} - -static const testcase_t test_012_001 = { - "Threads creation from Memory Heap", - test_012_001_setup, - NULL, - test_012_001_execute -}; -#endif /* CH_CFG_USE_HEAP */ - -#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) -/** - * @page test_012_002 [12.2] Threads creation from Memory Pool - * - *

Description

- * Five thread creation are attempted from a pool containing only four - * elements.
The test expects the first four threads to - * successfully start and the last one to fail. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MEMPOOLS - * . - * - *

Test Steps

- * - [12.2.1] Adding four working areas to the pool. - * - [12.2.2] Getting base priority for threads. - * - [12.2.3] Creating the five threads. - * - [12.2.4] Testing that only the fifth thread creation failed. - * - [12.2.5] Letting them run, free the memory then checking the - * execution sequence. - * - [12.2.6] Testing that the pool contains four elements again. - * . - */ - -static void test_012_002_setup(void) { - chPoolObjectInit(&mp1, THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), NULL); -} - -static void test_012_002_execute(void) { - unsigned i; - tprio_t prio; - - /* [12.2.1] Adding four working areas to the pool.*/ - test_set_step(1); - { - for (i = 0; i < 4; i++) - chPoolFree(&mp1, wa[i]); - } - - /* [12.2.2] Getting base priority for threads.*/ - test_set_step(2); - { - prio = chThdGetPriorityX(); - } - - /* [12.2.3] Creating the five threads.*/ - test_set_step(3); - { - threads[0] = chThdCreateFromMemoryPool(&mp1, "dyn1", prio-1, dyn_thread1, "A"); - threads[1] = chThdCreateFromMemoryPool(&mp1, "dyn2", prio-2, dyn_thread1, "B"); - threads[2] = chThdCreateFromMemoryPool(&mp1, "dyn3", prio-3, dyn_thread1, "C"); - threads[3] = chThdCreateFromMemoryPool(&mp1, "dyn4", prio-4, dyn_thread1, "D"); - threads[4] = chThdCreateFromMemoryPool(&mp1, "dyn5", prio-5, dyn_thread1, "E"); - } - - /* [12.2.4] Testing that only the fifth thread creation failed.*/ - test_set_step(4); - { - test_assert((threads[0] != NULL) && - (threads[1] != NULL) && - (threads[2] != NULL) && - (threads[3] != NULL), - "thread creation failed"); - test_assert(threads[4] == NULL, - "thread creation not failed"); - } - - /* [12.2.5] Letting them run, free the memory then checking the - execution sequence.*/ - test_set_step(5); - { - test_wait_threads(); - test_assert_sequence("ABCD", "invalid sequence"); - } - - /* [12.2.6] Testing that the pool contains four elements again.*/ - test_set_step(6); - { - for (i = 0; i < 4; i++) - test_assert(chPoolAlloc(&mp1) != NULL, "pool list empty"); - test_assert(chPoolAlloc(&mp1) == NULL, "pool list not empty"); - } -} - -static const testcase_t test_012_002 = { - "Threads creation from Memory Pool", - test_012_002_setup, - NULL, - test_012_002_execute -}; -#endif /* CH_CFG_USE_MEMPOOLS */ - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Dynamic threads. - */ -const testcase_t * const test_sequence_012[] = { -#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) - &test_012_001, -#endif -#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) - &test_012_002, -#endif - NULL -}; - -#endif /* CH_CFG_USE_DYNAMIC */ diff --git a/test/rt/source/test/test_sequence_012.h b/test/rt/source/test/test_sequence_012.h deleted file mode 100644 index 893a5cadc..000000000 --- a/test/rt/source/test/test_sequence_012.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_012.h - * @brief Test Sequence 012 header. - */ - -#ifndef TEST_SEQUENCE_012_H -#define TEST_SEQUENCE_012_H - -extern const testcase_t * const test_sequence_012[]; - -#endif /* TEST_SEQUENCE_012_H */ diff --git a/test/rt/source/test/test_sequence_013.c b/test/rt/source/test/test_sequence_013.c deleted file mode 100644 index 22fb3beb9..000000000 --- a/test/rt/source/test/test_sequence_013.c +++ /dev/null @@ -1,1031 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#include "hal.h" -#include "ch_test.h" -#include "test_root.h" - -/** - * @file test_sequence_013.c - * @brief Test Sequence 013 code. - * - * @page test_sequence_013 [13] Benchmarks - * - * File: @ref test_sequence_013.c - * - *

Description

- * This module implements a series of system benchmarks. The benchmarks - * are useful as a stress test and as a reference when comparing - * ChibiOS/RT with similar systems.
Objective of the test sequence - * is to provide a performance index for the most critical system - * subsystems. The performance numbers allow to discover performance - * regressions between successive ChibiOS/RT releases. - * - *

Test Cases

- * - @subpage test_013_001 - * - @subpage test_013_002 - * - @subpage test_013_003 - * - @subpage test_013_004 - * - @subpage test_013_005 - * - @subpage test_013_006 - * - @subpage test_013_007 - * - @subpage test_013_008 - * - @subpage test_013_009 - * - @subpage test_013_010 - * - @subpage test_013_011 - * - @subpage test_013_012 - * . - */ - -/**************************************************************************** - * Shared code. - ****************************************************************************/ - -#if CH_CFG_USE_SEMAPHORES || defined(__DOXYGEN__) -static semaphore_t sem1; -#endif -#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__) -static mutex_t mtx1; -#endif - -static void tmo(void *param) {(void)param;} - -#if CH_CFG_USE_MESSAGES -static THD_FUNCTION(bmk_thread1, p) { - thread_t *tp; - msg_t msg; - - (void)p; - do { - tp = chMsgWait(); - msg = chMsgGet(tp); - chMsgRelease(tp, msg); - } while (msg); -} - -NOINLINE static unsigned int msg_loop_test(thread_t *tp) { - systime_t start, end; - - uint32_t n = 0; - start = test_wait_tick(); - end = start + MS2ST(1000); - do { - (void)chMsgSend(tp, 1); - n++; -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } while (chVTIsSystemTimeWithinX(start, end)); - (void)chMsgSend(tp, 0); - return n; -} -#endif - -static THD_FUNCTION(bmk_thread3, p) { - - chThdExit((msg_t)p); -} - -static THD_FUNCTION(bmk_thread4, p) { - msg_t msg; - thread_t *self = chThdGetSelfX(); - - (void)p; - chSysLock(); - do { - chSchGoSleepS(CH_STATE_SUSPENDED); - msg = self->u.rdymsg; - } while (msg == MSG_OK); - chSysUnlock(); -} - -#if CH_CFG_USE_SEMAPHORES -static THD_FUNCTION(bmk_thread7, p) { - - (void)p; - while (!chThdShouldTerminateX()) - chSemWait(&sem1); -} -#endif - -static THD_FUNCTION(bmk_thread8, p) { - - do { - chThdYield(); - chThdYield(); - chThdYield(); - chThdYield(); - (*(uint32_t *)p) += 4; -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } while(!chThdShouldTerminateX()); -} - -/**************************************************************************** - * Test cases. - ****************************************************************************/ - -#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) -/** - * @page test_013_001 [13.1] Messages performance #1 - * - *

Description

- * A message server thread is created with a lower priority than the - * client thread, the messages throughput per second is measured and - * the result printed on the output log. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MESSAGES - * . - * - *

Test Steps

- * - [13.1.1] The messenger thread is started at a lower priority than - * the current thread. - * - [13.1.2] The number of messages exchanged is counted in a one - * second time window. - * - [13.1.3] Score is printed. - * . - */ - -static void test_013_001_execute(void) { - uint32_t n; - - /* [13.1.1] The messenger thread is started at a lower priority than - the current thread.*/ - test_set_step(1); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-1, bmk_thread1, NULL); - } - - /* [13.1.2] The number of messages exchanged is counted in a one - second time window.*/ - test_set_step(2); - { - n = msg_loop_test(threads[0]); - test_wait_threads(); - } - - /* [13.1.3] Score is printed.*/ - test_set_step(3); - { - test_print("--- Score : "); - test_printn(n); - test_print(" msgs/S, "); - test_printn(n << 1); - test_println(" ctxswc/S"); - } -} - -static const testcase_t test_013_001 = { - "Messages performance #1", - NULL, - NULL, - test_013_001_execute -}; -#endif /* CH_CFG_USE_MESSAGES */ - -#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) -/** - * @page test_013_002 [13.2] Messages performance #2 - * - *

Description

- * A message server thread is created with an higher priority than the - * client thread, the messages throughput per second is measured and - * the result printed on the output log. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MESSAGES - * . - * - *

Test Steps

- * - [13.2.1] The messenger thread is started at an higher priority - * than the current thread. - * - [13.2.2] The number of messages exchanged is counted in a one - * second time window. - * - [13.2.3] Score is printed. - * . - */ - -static void test_013_002_execute(void) { - uint32_t n; - - /* [13.2.1] The messenger thread is started at an higher priority - than the current thread.*/ - test_set_step(1); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, bmk_thread1, NULL); - } - - /* [13.2.2] The number of messages exchanged is counted in a one - second time window.*/ - test_set_step(2); - { - n = msg_loop_test(threads[0]); - test_wait_threads(); - } - - /* [13.2.3] Score is printed.*/ - test_set_step(3); - { - test_print("--- Score : "); - test_printn(n); - test_print(" msgs/S, "); - test_printn(n << 1); - test_println(" ctxswc/S"); - } -} - -static const testcase_t test_013_002 = { - "Messages performance #2", - NULL, - NULL, - test_013_002_execute -}; -#endif /* CH_CFG_USE_MESSAGES */ - -#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) -/** - * @page test_013_003 [13.3] Messages performance #3 - * - *

Description

- * A message server thread is created with an higher priority than the - * client thread, four lower priority threads crowd the ready list, the - * messages throughput per second is measured while the ready list and - * the result printed on the output log. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MESSAGES - * . - * - *

Test Steps

- * - [13.3.1] The messenger thread is started at an higher priority - * than the current thread. - * - [13.3.2] Four threads are started at a lower priority than the - * current thread. - * - [13.3.3] The number of messages exchanged is counted in a one - * second time window. - * - [13.3.4] Score is printed. - * . - */ - -static void test_013_003_execute(void) { - uint32_t n; - - /* [13.3.1] The messenger thread is started at an higher priority - than the current thread.*/ - test_set_step(1); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, bmk_thread1, NULL); - } - - /* [13.3.2] Four threads are started at a lower priority than the - current thread.*/ - test_set_step(2); - { - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-2, bmk_thread3, NULL); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, bmk_thread3, NULL); - threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-4, bmk_thread3, NULL); - threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-5, bmk_thread3, NULL); - } - - /* [13.3.3] The number of messages exchanged is counted in a one - second time window.*/ - test_set_step(3); - { - n = msg_loop_test(threads[0]); - test_wait_threads(); - } - - /* [13.3.4] Score is printed.*/ - test_set_step(4); - { - test_print("--- Score : "); - test_printn(n); - test_print(" msgs/S, "); - test_printn(n << 1); - test_println(" ctxswc/S"); - } -} - -static const testcase_t test_013_003 = { - "Messages performance #3", - NULL, - NULL, - test_013_003_execute -}; -#endif /* CH_CFG_USE_MESSAGES */ - -/** - * @page test_013_004 [13.4] Context Switch performance - * - *

Description

- * A thread is created that just performs a @p chSchGoSleepS() into a - * loop, the thread is awakened as fast is possible by the tester - * thread.
The Context Switch performance is calculated by - * measuring the number of iterations after a second of continuous - * operations. - * - *

Test Steps

- * - [13.4.1] Starting the target thread at an higher priority level. - * - [13.4.2] Waking up the thread as fast as possible in a one second - * time window. - * - [13.4.3] Stopping the target thread. - * - [13.4.4] Score is printed. - * . - */ - -static void test_013_004_execute(void) { - thread_t *tp; - uint32_t n; - - /* [13.4.1] Starting the target thread at an higher priority level.*/ - test_set_step(1); - { - tp = threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, - bmk_thread4, NULL); - } - - /* [13.4.2] Waking up the thread as fast as possible in a one second - time window.*/ - test_set_step(2); - { - systime_t start, end; - - n = 0; - start = test_wait_tick(); - end = start + MS2ST(1000); - do { - chSysLock(); - chSchWakeupS(tp, MSG_OK); - chSchWakeupS(tp, MSG_OK); - chSchWakeupS(tp, MSG_OK); - chSchWakeupS(tp, MSG_OK); - chSysUnlock(); - n += 4; -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } while (chVTIsSystemTimeWithinX(start, end)); - } - - /* [13.4.3] Stopping the target thread.*/ - test_set_step(3); - { - chSysLock(); - chSchWakeupS(tp, MSG_TIMEOUT); - chSysUnlock(); - test_wait_threads(); - } - - /* [13.4.4] Score is printed.*/ - test_set_step(4); - { - test_print("--- Score : "); - test_printn(n * 2); - test_println(" ctxswc/S"); - } -} - -static const testcase_t test_013_004 = { - "Context Switch performance", - NULL, - NULL, - test_013_004_execute -}; - -/** - * @page test_013_005 [13.5] Threads performance, full cycle - * - *

Description

- * Threads are continuously created and terminated into a loop. A full - * chThdCreateStatic() / @p chThdExit() / @p chThdWait() cycle is - * performed in each iteration.
The performance is calculated by - * measuring the number of iterations after a second of continuous - * operations. - * - *

Test Steps

- * - [13.5.1] A thread is created at a lower priority level and its - * termination detected using @p chThdWait(). The operation is - * repeated continuously in a one-second time window. - * - [13.5.2] Score is printed. - * . - */ - -static void test_013_005_execute(void) { - uint32_t n; - tprio_t prio = chThdGetPriorityX() - 1; - systime_t start, end; - - /* [13.5.1] A thread is created at a lower priority level and its - termination detected using @p chThdWait(). The operation is - repeated continuously in a one-second time window.*/ - test_set_step(1); - { - n = 0; - start = test_wait_tick(); - end = start + MS2ST(1000); - do { - chThdWait(chThdCreateStatic(wa[0], WA_SIZE, prio, bmk_thread3, NULL)); - n++; -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } while (chVTIsSystemTimeWithinX(start, end)); - } - - /* [13.5.2] Score is printed.*/ - test_set_step(2); - { - test_print("--- Score : "); - test_printn(n); - test_println(" threads/S"); - } -} - -static const testcase_t test_013_005 = { - "Threads performance, full cycle", - NULL, - NULL, - test_013_005_execute -}; - -/** - * @page test_013_006 [13.6] Threads performance, create/exit only - * - *

Description

- * Threads are continuously created and terminated into a loop. A - * partial @p chThdCreateStatic() / @p chThdExit() cycle is performed - * in each iteration, the @p chThdWait() is not necessary because the - * thread is created at an higher priority so there is no need to wait - * for it to terminate.
The performance is calculated by measuring - * the number of iterations after a second of continuous operations. - * - *

Test Steps

- * - [13.6.1] A thread is created at an higher priority level and let - * terminate immediately. The operation is repeated continuously in a - * one-second time window. - * - [13.6.2] Score is printed. - * . - */ - -static void test_013_006_execute(void) { - uint32_t n; - tprio_t prio = chThdGetPriorityX() + 1; - systime_t start, end; - - /* [13.6.1] A thread is created at an higher priority level and let - terminate immediately. The operation is repeated continuously in a - one-second time window.*/ - test_set_step(1); - { - n = 0; - start = test_wait_tick(); - end = start + MS2ST(1000); - do { -#if CH_CFG_USE_REGISTRY - chThdRelease(chThdCreateStatic(wa[0], WA_SIZE, prio, bmk_thread3, NULL)); -#else - chThdCreateStatic(wa[0], WA_SIZE, prio, bmk_thread3, NULL); -#endif - n++; -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } while (chVTIsSystemTimeWithinX(start, end)); - } - - /* [13.6.2] Score is printed.*/ - test_set_step(2); - { - test_print("--- Score : "); - test_printn(n); - test_println(" threads/S"); - } -} - -static const testcase_t test_013_006 = { - "Threads performance, create/exit only", - NULL, - NULL, - test_013_006_execute -}; - -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) -/** - * @page test_013_007 [13.7] Mass reschedule performance - * - *

Description

- * Five threads are created and atomically rescheduled by resetting the - * semaphore where they are waiting on. The operation is performed into - * a continuous loop.
The performance is calculated by measuring - * the number of iterations after a second of continuous operations. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_SEMAPHORES - * . - * - *

Test Steps

- * - [13.7.1] Five threads are created at higher priority that - * immediately enqueue on a semaphore. - * - [13.7.2] The semaphore is reset waking up the five threads. The - * operation is repeated continuously in a one-second time window. - * - [13.7.3] The five threads are terminated. - * - [13.7.4] The score is printed. - * . - */ - -static void test_013_007_setup(void) { - chSemObjectInit(&sem1, 0); -} - -static void test_013_007_execute(void) { - uint32_t n; - - /* [13.7.1] Five threads are created at higher priority that - immediately enqueue on a semaphore.*/ - test_set_step(1); - { - threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+5, bmk_thread7, NULL); - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()+4, bmk_thread7, NULL); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()+3, bmk_thread7, NULL); - threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()+2, bmk_thread7, NULL); - threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()+1, bmk_thread7, NULL); - } - - /* [13.7.2] The semaphore is reset waking up the five threads. The - operation is repeated continuously in a one-second time window.*/ - test_set_step(2); - { - systime_t start, end; - - n = 0; - start = test_wait_tick(); - end = start + MS2ST(1000); - do { - chSemReset(&sem1, 0); - n++; -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } while (chVTIsSystemTimeWithinX(start, end)); - } - - /* [13.7.3] The five threads are terminated.*/ - test_set_step(3); - { - test_terminate_threads(); - chSemReset(&sem1, 0); - test_wait_threads(); - } - - /* [13.7.4] The score is printed.*/ - test_set_step(4); - { - test_print("--- Score : "); - test_printn(n); - test_print(" reschedules/S, "); - test_printn(n * 6); - test_println(" ctxswc/S"); - } -} - -static const testcase_t test_013_007 = { - "Mass reschedule performance", - test_013_007_setup, - NULL, - test_013_007_execute -}; -#endif /* CH_CFG_USE_SEMAPHORES */ - -/** - * @page test_013_008 [13.8] Round-Robin voluntary reschedule - * - *

Description

- * Five threads are created at equal priority, each thread just - * increases a variable and yields.
The performance is calculated - * by measuring the number of iterations after a second of continuous - * operations. - * - *

Test Steps

- * - [13.8.1] The five threads are created at lower priority. The - * threds have equal priority and start calling @p chThdYield() - * continuously. - * - [13.8.2] Waiting one second then terminating the 5 threads. - * - [13.8.3] The score is printed. - * . - */ - -static void test_013_008_execute(void) { - uint32_t n; - - /* [13.8.1] The five threads are created at lower priority. The - threds have equal priority and start calling @p chThdYield() - continuously.*/ - test_set_step(1); - { - n = 0; - test_wait_tick();threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-1, bmk_thread8, (void *)&n); - - threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-1, bmk_thread8, (void *)&n); - threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-1, bmk_thread8, (void *)&n); - threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-1, bmk_thread8, (void *)&n); - threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, bmk_thread8, (void *)&n); - } - - /* [13.8.2] Waiting one second then terminating the 5 threads.*/ - test_set_step(2); - { - chThdSleepSeconds(1); - test_terminate_threads(); - test_wait_threads(); - } - - /* [13.8.3] The score is printed.*/ - test_set_step(3); - { - test_print("--- Score : "); - test_printn(n); - test_println(" ctxswc/S"); - } -} - -static const testcase_t test_013_008 = { - "Round-Robin voluntary reschedule", - NULL, - NULL, - test_013_008_execute -}; - -/** - * @page test_013_009 [13.9] Virtual Timers set/reset performance - * - *

Description

- * A virtual timer is set and immediately reset into a continuous - * loop.
The performance is calculated by measuring the number of - * iterations after a second of continuous operations. - * - *

Test Steps

- * - [13.9.1] Two timers are set then reset without waiting for their - * counter to elapse. The operation is repeated continuously in a - * one-second time window. - * - [13.9.2] The score is printed. - * . - */ - -static void test_013_009_execute(void) { - static virtual_timer_t vt1, vt2; - uint32_t n; - - /* [13.9.1] Two timers are set then reset without waiting for their - counter to elapse. The operation is repeated continuously in a - one-second time window.*/ - test_set_step(1); - { - systime_t start, end; - - n = 0; - start = test_wait_tick(); - end = start + MS2ST(1000); - do { - chSysLock(); - chVTDoSetI(&vt1, 1, tmo, NULL); - chVTDoSetI(&vt2, 10000, tmo, NULL); - chVTDoResetI(&vt1); - chVTDoResetI(&vt2); - chSysUnlock(); - n++; -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } while (chVTIsSystemTimeWithinX(start, end)); - } - - /* [13.9.2] The score is printed.*/ - test_set_step(2); - { - test_print("--- Score : "); - test_printn(n * 2); - test_println(" timers/S"); - } -} - -static const testcase_t test_013_009 = { - "Virtual Timers set/reset performance", - NULL, - NULL, - test_013_009_execute -}; - -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) -/** - * @page test_013_010 [13.10] Semaphores wait/signal performance - * - *

Description

- * A counting semaphore is taken/released into a continuous loop, no - * Context Switch happens because the counter is always non - * negative.
The performance is calculated by measuring the number - * of iterations after a second of continuous operations. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_SEMAPHORES - * . - * - *

Test Steps

- * - [13.10.1] A semaphore is teken and released. The operation is - * repeated continuously in a one-second time window. - * - [13.10.2] The score is printed. - * . - */ - -static void test_013_010_setup(void) { - chSemObjectInit(&sem1, 1); -} - -static void test_013_010_execute(void) { - uint32_t n; - - /* [13.10.1] A semaphore is teken and released. The operation is - repeated continuously in a one-second time window.*/ - test_set_step(1); - { - systime_t start, end; - - n = 0; - start = test_wait_tick(); - end = start + MS2ST(1000); - do { - chSemWait(&sem1); - chSemSignal(&sem1); - chSemWait(&sem1); - chSemSignal(&sem1); - chSemWait(&sem1); - chSemSignal(&sem1); - chSemWait(&sem1); - chSemSignal(&sem1); - n++; -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } while (chVTIsSystemTimeWithinX(start, end)); - } - - /* [13.10.2] The score is printed.*/ - test_set_step(2); - { - test_print("--- Score : "); - test_printn(n * 4); - test_println(" wait+signal/S"); - } -} - -static const testcase_t test_013_010 = { - "Semaphores wait/signal performance", - test_013_010_setup, - NULL, - test_013_010_execute -}; -#endif /* CH_CFG_USE_SEMAPHORES */ - -#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) -/** - * @page test_013_011 [13.11] Mutexes lock/unlock performance - * - *

Description

- * A mutex is locked/unlocked into a continuous loop, no Context Switch - * happens because there are no other threads asking for the mutex.
- * The performance is calculated by measuring the number of iterations - * after a second of continuous operations. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MUTEXES - * . - * - *

Test Steps

- * - [13.11.1] A mutex is locked and unlocked. The operation is - * repeated continuously in a one-second time window. - * - [13.11.2] The score is printed. - * . - */ - -static void test_013_011_setup(void) { - chMtxObjectInit(&mtx1); -} - -static void test_013_011_execute(void) { - uint32_t n; - - /* [13.11.1] A mutex is locked and unlocked. The operation is - repeated continuously in a one-second time window.*/ - test_set_step(1); - { - systime_t start, end; - - n = 0; - start = test_wait_tick(); - end = start + MS2ST(1000); - do { - chMtxLock(&mtx1); - chMtxUnlock(&mtx1); - chMtxLock(&mtx1); - chMtxUnlock(&mtx1); - chMtxLock(&mtx1); - chMtxUnlock(&mtx1); - chMtxLock(&mtx1); - chMtxUnlock(&mtx1); - n++; -#if defined(SIMULATOR) - _sim_check_for_interrupts(); -#endif - } while (chVTIsSystemTimeWithinX(start, end)); - } - - /* [13.11.2] The score is printed.*/ - test_set_step(2); - { - test_print("--- Score : "); - test_printn(n * 4); - test_println(" lock+unlock/S"); - } -} - -static const testcase_t test_013_011 = { - "Mutexes lock/unlock performance", - test_013_011_setup, - NULL, - test_013_011_execute -}; -#endif /* CH_CFG_USE_MUTEXES */ - -/** - * @page test_013_012 [13.12] RAM Footprint - * - *

Description

- * The memory size of the various kernel objects is printed. - * - *

Test Steps

- * - [13.12.1] The size of the system area is printed. - * - [13.12.2] The size of a thread structure is printed. - * - [13.12.3] The size of a virtual timer structure is printed. - * - [13.12.4] The size of a semaphore structure is printed. - * - [13.12.5] The size of a mutex is printed. - * - [13.12.6] The size of a condition variable is printed. - * - [13.12.7] The size of an event source is printed. - * - [13.12.8] The size of an event listener is printed. - * - [13.12.9] The size of a mailbox is printed. - * . - */ - -static void test_013_012_execute(void) { - - /* [13.12.1] The size of the system area is printed.*/ - test_set_step(1); - { - test_print("--- System: "); - test_printn(sizeof(ch_system_t)); - test_println(" bytes"); - } - - /* [13.12.2] The size of a thread structure is printed.*/ - test_set_step(2); - { - test_print("--- Thread: "); - test_printn(sizeof(thread_t)); - test_println(" bytes"); - } - - /* [13.12.3] The size of a virtual timer structure is printed.*/ - test_set_step(3); - { - test_print("--- Timer : "); - test_printn(sizeof(virtual_timer_t)); - test_println(" bytes"); - } - - /* [13.12.4] The size of a semaphore structure is printed.*/ - test_set_step(4); - { -#if CH_CFG_USE_SEMAPHORES || defined(__DOXYGEN__) - test_print("--- Semaph: "); - test_printn(sizeof(semaphore_t)); - test_println(" bytes"); -#endif - } - - /* [13.12.5] The size of a mutex is printed.*/ - test_set_step(5); - { -#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__) - test_print("--- Mutex : "); - test_printn(sizeof(mutex_t)); - test_println(" bytes"); -#endif - } - - /* [13.12.6] The size of a condition variable is printed.*/ - test_set_step(6); - { -#if CH_CFG_USE_CONDVARS || defined(__DOXYGEN__) - test_print("--- CondV.: "); - test_printn(sizeof(condition_variable_t)); - test_println(" bytes"); -#endif - } - - /* [13.12.7] The size of an event source is printed.*/ - test_set_step(7); - { -#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__) - test_print("--- EventS: "); - test_printn(sizeof(event_source_t)); - test_println(" bytes"); -#endif - } - - /* [13.12.8] The size of an event listener is printed.*/ - test_set_step(8); - { -#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__) - test_print("--- EventL: "); - test_printn(sizeof(event_listener_t)); - test_println(" bytes"); -#endif - } - - /* [13.12.9] The size of a mailbox is printed.*/ - test_set_step(9); - { -#if CH_CFG_USE_MAILBOXES || defined(__DOXYGEN__) - test_print("--- MailB.: "); - test_printn(sizeof(mailbox_t)); - test_println(" bytes"); -#endif - } -} - -static const testcase_t test_013_012 = { - "RAM Footprint", - NULL, - NULL, - test_013_012_execute -}; - -/**************************************************************************** - * Exported data. - ****************************************************************************/ - -/** - * @brief Benchmarks. - */ -const testcase_t * const test_sequence_013[] = { -#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) - &test_013_001, -#endif -#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) - &test_013_002, -#endif -#if (CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__) - &test_013_003, -#endif - &test_013_004, - &test_013_005, - &test_013_006, -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) - &test_013_007, -#endif - &test_013_008, - &test_013_009, -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) - &test_013_010, -#endif -#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__) - &test_013_011, -#endif - &test_013_012, - NULL -}; diff --git a/test/rt/source/test/test_sequence_013.h b/test/rt/source/test/test_sequence_013.h deleted file mode 100644 index 9bbcb7b0d..000000000 --- a/test/rt/source/test/test_sequence_013.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file test_sequence_013.h - * @brief Test Sequence 013 header. - */ - -#ifndef TEST_SEQUENCE_013_H -#define TEST_SEQUENCE_013_H - -extern const testcase_t * const test_sequence_013[]; - -#endif /* TEST_SEQUENCE_013_H */ diff --git a/test/rt/test.mk b/test/rt/test.mk index e9c74676a..d3eb41f63 100644 --- a/test/rt/test.mk +++ b/test/rt/test.mk @@ -1,19 +1,19 @@ # List of all the ChibiOS/RT test files. TESTSRC = ${CHIBIOS}/test/lib/ch_test.c \ - ${CHIBIOS}/test/rt/source/test/test_root.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_001.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_002.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_003.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_004.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_005.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_006.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_007.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_008.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_009.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_010.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_011.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_012.c \ - ${CHIBIOS}/test/rt/source/test/test_sequence_013.c + ${CHIBIOS}/test/rt/source/test/rt_test_root.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_001.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_002.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_003.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_004.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_005.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_006.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_007.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_008.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_009.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_010.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_011.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_012.c \ + ${CHIBIOS}/test/rt/source/test/rt_test_sequence_013.c # Required include directories TESTINC = ${CHIBIOS}/test/lib \ -- cgit v1.2.3