From 1c24089c1574f77fe8919354c9aa0ce86c71e8c7 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Mon, 5 Aug 2024 17:21:03 +0200 Subject: [PATCH 01/23] dont drive short test route forever --- test/physical/swtbahn-full/testsuite.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index c2912c1..971cbec 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -479,7 +479,7 @@ void testsuite_case_swtbahnFullMultipleTrains(const char *train1, const char *tr } bool route_custom_short(const char *train) { - if (!testsuite_trainReady(train, "seg7a")) { + if (!testsuite_trainReady(train, "seg7b")) { return false; } @@ -491,7 +491,8 @@ bool route_custom_short(const char *train) { testsuite_switch_point("point4", "normal"); testsuite_switch_point("point3", "normal"); - testsuite_driveTo("drive_forever", 50, train); + testsuite_driveToStop("seg7a", 50, train); + testsuite_driveToStop("seg7b", 50, train); return true; } From 5c32aa784ed8f652e01f1bd7a8ebc01dbae38740 Mon Sep 17 00:00:00 2001 From: Uniba-SWT Date: Wed, 7 Aug 2024 13:18:56 +0200 Subject: [PATCH 02/23] Added section in test readme remarking issue with feedback gathering for points. --- test/physical/Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/test/physical/Readme.md b/test/physical/Readme.md index 9797e06..0ec5d2d 100644 --- a/test/physical/Readme.md +++ b/test/physical/Readme.md @@ -80,6 +80,7 @@ point10 -> unknownState: 0 ``` +Currently, the feedback state of points is determined immediately after setting them to a new aspect. The state of a point at that time may not yet reflect the state change bound to occur due to the new aspect being set. Feedback gathering will have to be adjusted to wait for some time after setting the point aspect to get an accurate picture of the state of the point. ## Dependencies From b451c972772bdbe558df3a1cf34ead7bb10d2841 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Wed, 27 Nov 2024 09:56:33 +0100 Subject: [PATCH 03/23] fix possible read from unitialized var (not directly related to physical test) --- src/state/bidib_state_setter.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/state/bidib_state_setter.c b/src/state/bidib_state_setter.c index 2baf7fb..0dca9a5 100644 --- a/src/state/bidib_state_setter.c +++ b/src/state/bidib_state_setter.c @@ -111,7 +111,7 @@ void bidib_state_accessory_state(t_bidib_node_address node_address, uint8_t numb if (accessory_mapping != NULL && (accessory_state = bidib_state_get_board_accessory_state_ref(accessory_mapping->id->str, point)) != NULL) { accessory_state->data.state_id = NULL; - t_bidib_aspect *aspect_mapping; + t_bidib_aspect *aspect_mapping = NULL; for (size_t i = 0; i < accessory_mapping->aspects->len; i++) { aspect_mapping = &g_array_index(accessory_mapping->aspects, t_bidib_aspect, i); if (aspect_mapping->value == aspect) { @@ -119,6 +119,14 @@ void bidib_state_accessory_state(t_bidib_node_address node_address, uint8_t numb break; } } + if (aspect_mapping == NULL) { + syslog_libbidib(LOG_ERR, + "bidib_state_accessory_state: aspect mapping for accessory %s is NULL", + accessory_mapping->id->str); + pthread_rwlock_unlock(&bidib_state_boards_rwlock); + pthread_rwlock_unlock(&bidib_state_track_rwlock); + return; + } if (accessory_state->data.state_id == NULL) { syslog_libbidib(LOG_WARNING, "Aspect 0x%02x of accessory %s is not mapped in config files", From 22d5b6e18ca88817fd7954886d1b1a2dd81a1368 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Wed, 27 Nov 2024 10:39:08 +0100 Subject: [PATCH 04/23] improve accessory feedback recording and add some logging utilities --- test/physical/Readme.md | 2 - test/physical/test_common.c | 153 ++++++++++++++++++++++++++++++------ test/physical/test_common.h | 4 +- 3 files changed, 132 insertions(+), 27 deletions(-) diff --git a/test/physical/Readme.md b/test/physical/Readme.md index 0ec5d2d..55334cd 100644 --- a/test/physical/Readme.md +++ b/test/physical/Readme.md @@ -80,8 +80,6 @@ point10 -> unknownState: 0 ``` -Currently, the feedback state of points is determined immediately after setting them to a new aspect. The state of a point at that time may not yet reflect the state change bound to occur due to the new aspect being set. Feedback gathering will have to be adjusted to wait for some time after setting the point aspect to get an accurate picture of the state of the point. - ## Dependencies **SWTbahn Platform** diff --git a/test/physical/test_common.c b/test/physical/test_common.c index 5ae7455..62598a8 100644 --- a/test/physical/test_common.c +++ b/test/physical/test_common.c @@ -72,22 +72,26 @@ t_testsuite_test_result *testsuite_initTestSuite_common(char **excludedSignalAcc } t_bidib_id_list_query testsuite_filterOutIds(t_bidib_id_list_query inputIdQuery, t_testsuite_ids filterOutIds) { - const size_t count = inputIdQuery.length - filterOutIds.length; + ssize_t count = inputIdQuery.length - filterOutIds.length; if (count <= 0) { - printf("testsuite: No IDs will be left after filtering\n"); + printf("testsuite: No IDs might be left after filtering\n"); + count = 0; } t_bidib_id_list_query outputIdQuery; outputIdQuery.length = 0; - outputIdQuery.ids = malloc(sizeof(char *) * count); + // the outputIdQuery will likely be smaller, but we don't know if the IDs + // in filterOutIds are actually contained in inputIdQuery, thus theoretically + // the length of outputIdQuery can be that of inputIdQuery at most. + outputIdQuery.ids = malloc(sizeof(char *) * inputIdQuery.length); bool isFilteredOut = false; for (size_t i = 0; i < inputIdQuery.length; i++) { isFilteredOut = false; for (size_t j = 0; j < filterOutIds.length; j++) { - if (!strcmp(inputIdQuery.ids[i], filterOutIds.ids[j])) { + if (strcmp(inputIdQuery.ids[i], filterOutIds.ids[j]) == 0) { isFilteredOut = true; break; } @@ -99,8 +103,9 @@ t_bidib_id_list_query testsuite_filterOutIds(t_bidib_id_list_query inputIdQuery, } } - if (outputIdQuery.length != count) { - printf("testsuite: Error: %zu IDs were to be filtered, but %d IDs filtered instead\n", + if (outputIdQuery.length != (size_t) count) { + // can occur if the IDs to be filtered are those of accessories currently not connected. + printf("testsuite: Notice: %zu IDs were to be filtered, %d IDs were actually filtered\n", filterOutIds.length, (int)inputIdQuery.length - (int)outputIdQuery.length); } @@ -119,9 +124,9 @@ void testsuite_signal_callback_handler(int signum) { exit(signum); } -void testsuite_logTestResult(t_testsuite_test_result *result, - t_bidib_unified_accessory_state_query state, - int accessory_index) { +void testsuite_recordTestResult(t_testsuite_test_result *result, + t_bidib_unified_accessory_state_query state, + int accessory_index) { if (state.known) { switch (state.board_accessory_state.execution_state) { case BIDIB_EXEC_STATE_ERROR: @@ -188,7 +193,7 @@ void testsuite_driveTo(const char *segment, int speed, const char *train) { while (1) { t_bidib_train_position_query trainPosition = bidib_get_train_position(train); for (size_t i = 0; i < trainPosition.length; i++) { - if (!strcmp(segment, trainPosition.segments[i])) { + if (strcmp(segment, trainPosition.segments[i]) == 0) { bidib_free_train_position_query(trainPosition); return; } @@ -224,10 +229,20 @@ void testsuite_case_signal_common(char **aspects, size_t aspects_len) { } void testsuite_case_pointParallel_common(t_testsuite_test_result *result) { + // like the old pointParallel, but here an appropriate amount of time is waited + // after setting the points until feedback is gathered. Because point switchting + // takes some time, it doesn't make sense to get the state/feedback immediately + // after sending the command to switch the point. + for (size_t i = 0; i < points.length; i++) { testsuite_switch_point(points.ids[i], "reverse"); + } + + sleep(POINT_WAITING_TIME_S); + + for (size_t i = 0; i < points.length; i++) { t_bidib_unified_accessory_state_query state = bidib_get_point_state(points.ids[i]); - testsuite_logTestResult(result, state, i); + testsuite_recordTestResult(result, state, i); bidib_free_unified_accessory_state_query(state); } @@ -235,26 +250,116 @@ void testsuite_case_pointParallel_common(t_testsuite_test_result *result) { for (size_t i = 0; i < points.length; i++) { testsuite_switch_point(points.ids[i], "normal"); - t_bidib_unified_accessory_state_query state = bidib_get_point_state(points.ids[i]); - testsuite_logTestResult(result, state, i); - bidib_free_unified_accessory_state_query(state); } sleep(POINT_WAITING_TIME_S); -} - -void testsuite_case_pointSerial_common(t_testsuite_test_result *result) { + for (size_t i = 0; i < points.length; i++) { - testsuite_switch_point(points.ids[i], "reverse"); t_bidib_unified_accessory_state_query state = bidib_get_point_state(points.ids[i]); - testsuite_logTestResult(result, state, i); + testsuite_recordTestResult(result, state, i); bidib_free_unified_accessory_state_query(state); - sleep(POINT_WAITING_TIME_S); + } +} - testsuite_switch_point(points.ids[i], "normal"); - state = bidib_get_point_state(points.ids[i]); - testsuite_logTestResult(result, state, i); - bidib_free_unified_accessory_state_query(state); + +void testsuite_case_pointSerial_common(t_testsuite_test_result *result) { + // The points are first all switched to reverse one after the other. + // In iteration k, the switch for point with id at .ids[k] is commanded, + // AND the feedback for the point that was switched in iteration k-1 is gathered. + // -> this is done to avoid having to wait 4x3 seconds per point. + for (size_t i = 0; i <= points.length; i++) { + if (i < points.length) { + testsuite_switch_point(points.ids[i], "reverse"); + } + if (i >= 1) { + t_bidib_unified_accessory_state_query state = bidib_get_point_state(points.ids[i-1]); + testsuite_recordTestResult(result, state, i-1); + bidib_free_unified_accessory_state_query(state); + } + sleep(POINT_WAITING_TIME_S); + } + + // Now the same for switching the points to normal. + for (size_t i = 0; i <= points.length; i++) { + if (i < points.length) { + testsuite_switch_point(points.ids[i], "normal"); + } + if (i >= 1) { + t_bidib_unified_accessory_state_query state = bidib_get_point_state(points.ids[i-1]); + testsuite_recordTestResult(result, state, i-1); + bidib_free_unified_accessory_state_query(state); + } sleep(POINT_WAITING_TIME_S); } } + +const char * const testsuite_cs_state_str[] = { + [BIDIB_CS_OFF] = "BIDIB_CS_OFF", + [BIDIB_CS_STOP] = "BIDIB_CS_STOP", + [BIDIB_CS_SOFTSTOP] = "BIDIB_CS_SOFTSTOP", + [BIDIB_CS_GO] = "BIDIB_CS_GO", + [BIDIB_CS_GO_IGN_WD] = "BIDIB_CS_GO_IGN_WD", + [BIDIB_CS_PROG] = "BIDIB_CS_PROG", + [BIDIB_CS_PROGBUSY] = "BIDIB_CS_PROGBUSY", + [BIDIB_CS_BUSY] = "BIDIB_CS_BUSY", + [BIDIB_CS_QUERY] = "BIDIB_CS_QUERY" +}; + +void testsuite_logAllTrackOutputStates() { + t_bidib_id_list_query tr_outpts_query = bidib_get_track_outputs(); + if (tr_outpts_query.ids == NULL || tr_outpts_query.length == 0) { + printf("testsuite: list of track outputs ids is null or empty\n"); + return; + } + + for (size_t i = 0; i < tr_outpts_query.length; i++) { + t_bidib_track_output_state_query state_q; + state_q = bidib_get_track_output_state(tr_outpts_query.ids[i]); + if (!state_q.known) { + printf("testsuite: track output %s is unknown and/or has unknown state\n", + tr_outpts_query.ids[i]); + } else { + printf("testsuite: track output %s has state %s\n", + tr_outpts_query.ids[i], testsuite_cs_state_str[state_q.cs_state]); + } + } + + bidib_free_id_list_query(tr_outpts_query); +} + +// See also https://bidib.org/protokoll/bidib_booster.html -> MSG_BOOST_STAT +const char * const testsuite_bstr_powerstate_str[] = { + [BIDIB_BSTR_OFF] = "BIDIB_BSTR_OFF", + [BIDIB_BSTR_OFF_SHORT] = "BIDIB_BSTR_OFF_SHORT", + [BIDIB_BSTR_OFF_HOT] = "BIDIB_BSTR_OFF_HOT", + [BIDIB_BSTR_OFF_NOPOWER] = "BIDIB_BSTR_OFF_NOPOWER", + [BIDIB_BSTR_OFF_GO_REQ] = "BIDIB_BSTR_OFF_GO_REQ", + [BIDIB_BSTR_OFF_HERE] = "BIDIB_BSTR_OFF_HERE", + [BIDIB_BSTR_OFF_NO_DCC] = "BIDIB_BSTR_OFF_NO_DCC", + [BIDIB_BSTR_ON] = "BIDIB_BSTR_ON", + [BIDIB_BSTR_ON_LIMIT] = "BIDIB_BSTR_ON_LIMIT", + [BIDIB_BSTR_ON_HOT] = "BIDIB_BSTR_ON_HOT", + [BIDIB_BSTR_ON_STOP_REQ] = "BIDIB_BSTR_ON_STOP_REQ", + [BIDIB_BSTR_ON_HERE] = "BIDIB_BSTR_ON_HERE" +}; + +void testsuite_logAllBoosterPowerStates() { + t_bidib_id_list_query boosters_query = bidib_get_boosters(); + if (boosters_query.ids == NULL || boosters_query.length == 0) { + printf("testsuite: list of booster id query is null or empty\n"); + return; + } + + for (size_t i = 0; i < boosters_query.length; i++) { + t_bidib_booster_state_query b_state = bidib_get_booster_state(boosters_query.ids[i]); + if (!b_state.known) { + printf("testsuite: booster %s is unknown and/or has unknown state\n", + boosters_query.ids[i]); + } else { + printf("testsuite: booster %s has power state %s\n", + boosters_query.ids[i], testsuite_bstr_powerstate_str[b_state.data.power_state]); + } + + } + bidib_free_id_list_query(boosters_query); +} \ No newline at end of file diff --git a/test/physical/test_common.h b/test/physical/test_common.h index 60accbc..d772c3c 100644 --- a/test/physical/test_common.h +++ b/test/physical/test_common.h @@ -66,8 +66,10 @@ void testsuite_stopBidib(void); void testsuite_signal_callback_handler(int signum); // Logging -void testsuite_logTestResult(t_testsuite_test_result *result, t_bidib_unified_accessory_state_query state, int accessory_index); +void testsuite_recordTestResult(t_testsuite_test_result *result, t_bidib_unified_accessory_state_query state, int accessory_index); void testsuite_printTestResults(t_testsuite_test_result *result); +void testsuite_logAllTrackOutputStates(); +void testsuite_logAllBoosterPowerStates(); // Driving bool testsuite_trainReady(const char *train, const char *segment); From 6d423745e3e69ccdbf78b6e9725a3c2bd079cbea Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Wed, 27 Nov 2024 10:39:37 +0100 Subject: [PATCH 05/23] add debug logs for swtbahn-full testing track output and power states --- test/physical/swtbahn-standard/main.c | 33 +++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/test/physical/swtbahn-standard/main.c b/test/physical/swtbahn-standard/main.c index f83e6c5..0e47f07 100755 --- a/test/physical/swtbahn-standard/main.c +++ b/test/physical/swtbahn-standard/main.c @@ -65,25 +65,40 @@ int main(int argc, char **argv) { printf("testsuite: Test case %d\n", atoi(argv[1])); t_testsuite_test_result *result = testsuite_initTestSuite(); - const int repetitions = atoi(argv[2]); + + printf("--------\n"); + printf("testsuite: Track output states before test start:\n"); + testsuite_logAllTrackOutputStates(); + printf("--------\n"); + printf("testsuite: Booster power states before test start:\n"); + testsuite_logAllBoosterPowerStates(); + printf("--------\n"); + switch (atoi(argv[1])) { case 1: - bidib_set_track_output_state_all(BIDIB_CS_OFF); + ///TODO: Test if the track output state makes a difference. + // in https://github.com/uniba-swt/libbidib/commit/9fb28a411fcba765a9e3615703b7b7c64db28482 + // a line was introduced that would turn off the track output state + // for test cases 1-3. But it was not documented WHY. + //bidib_set_track_output_state_all(BIDIB_CS_GO); + //sleep(1); for (int i = 0; i < repetitions; i++) { testsuite_case_pointParallel(result); } testsuite_printTestResults(result); break; case 2: - bidib_set_track_output_state_all(BIDIB_CS_OFF); + //bidib_set_track_output_state_all(BIDIB_CS_GO); + //sleep(1); for (int i = 0; i < repetitions; i++) { testsuite_case_pointSerial(result); } testsuite_printTestResults(result); break; case 3: - bidib_set_track_output_state_all(BIDIB_CS_OFF); + //bidib_set_track_output_state_all(BIDIB_CS_GO); + //sleep(1); for (int i = 0; i < repetitions; i++) { testsuite_case_signal(); } @@ -102,6 +117,14 @@ int main(int argc, char **argv) { default: break; } + sleep(1); + printf("--------\n"); + printf("testsuite: Track output states after test completion:\n"); + testsuite_logAllTrackOutputStates(); + printf("--------\n"); + printf("testsuite: Booster power states after test completion:\n"); + testsuite_logAllBoosterPowerStates(); + printf("--------\n"); testsuite_stopBidib(); free(result); @@ -130,7 +153,7 @@ void printWelcome() { "* SWTbahn-testsuite *", "* *", "************************", - "* UniBa-SWT-2023 *", + "* UniBa-SWT-2024 *", "************************", "" }; From 3928a6911387ef14a325d3ad5450e87ec5e47c62 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Wed, 27 Nov 2024 10:44:52 +0100 Subject: [PATCH 06/23] update function name in readme --- test/physical/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/physical/Readme.md b/test/physical/Readme.md index 55334cd..b8cdcf8 100644 --- a/test/physical/Readme.md +++ b/test/physical/Readme.md @@ -67,7 +67,7 @@ For each point and signal, the `bidib_switch_point()` and `bidib_set_signal()` functions are used to set their aspect. The `t_testsuite_point_result` struct records the feedback state returned by a point, and is -updated by the `testsuite_logTestResult()` function. The following is an example of the +updated by the `testsuite_recordTestResult()` function. The following is an example of the feedback that is logged for a point: ``` From 308314003040a05a09584610fbfc268f38223922 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Wed, 27 Nov 2024 10:57:49 +0100 Subject: [PATCH 07/23] fix year --- test/physical/swtbahn-full/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/physical/swtbahn-full/main.c b/test/physical/swtbahn-full/main.c index 98efab6..1087dc4 100755 --- a/test/physical/swtbahn-full/main.c +++ b/test/physical/swtbahn-full/main.c @@ -168,7 +168,7 @@ void printWelcome() { "* SWTbahn-testsuite *", "* *", "************************", - "* UniBa-SWT-2023 *", + "* UniBa-SWT-2024 *", "************************", "" }; From 2b44b56aba925c93c7a256da78d9d9c3a08da58b Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Wed, 27 Nov 2024 11:00:38 +0100 Subject: [PATCH 08/23] add debug stuff to full physical test --- test/physical/swtbahn-full/main.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/test/physical/swtbahn-full/main.c b/test/physical/swtbahn-full/main.c index 1087dc4..85d2cd0 100755 --- a/test/physical/swtbahn-full/main.c +++ b/test/physical/swtbahn-full/main.c @@ -72,9 +72,23 @@ int main(int argc, char **argv) { t_testsuite_test_result *result = testsuite_initTestSuite(); const int repetitions = atoi(argv[2]); + + printf("--------\n"); + printf("testsuite: Track output states before test start:\n"); + testsuite_logAllTrackOutputStates(); + printf("--------\n"); + printf("testsuite: Booster power states before test start:\n"); + testsuite_logAllBoosterPowerStates(); + printf("--------\n"); + switch (atoi(argv[1])) { case 1: - bidib_set_track_output_state_all(BIDIB_CS_OFF); + ///TODO: Test if the track output state makes a difference. + // in https://github.com/uniba-swt/libbidib/commit/9fb28a411fcba765a9e3615703b7b7c64db28482 + // a line was introduced that would turn off the track output state + // for test cases 1-3. But it was not documented WHY. + //bidib_set_track_output_state_all(BIDIB_CS_OFF); + //sleep(1); for (int i = 0; i < repetitions; i++) { testsuite_case_pointParallel(result); } @@ -82,7 +96,8 @@ int main(int argc, char **argv) { break; case 2: - bidib_set_track_output_state_all(BIDIB_CS_OFF); + //bidib_set_track_output_state_all(BIDIB_CS_OFF); + //sleep(1); for (int i = 0; i < repetitions; i++) { testsuite_case_pointSerial(result); } @@ -90,7 +105,8 @@ int main(int argc, char **argv) { break; case 3: - bidib_set_track_output_state_all(BIDIB_CS_OFF); + //bidib_set_track_output_state_all(BIDIB_CS_OFF); + //sleep(1); for (int i = 0; i < repetitions; i++) { testsuite_case_signal(); } @@ -115,6 +131,15 @@ int main(int argc, char **argv) { default: break; } + sleep(1); + printf("--------\n"); + printf("testsuite: Track output states after test completion:\n"); + testsuite_logAllTrackOutputStates(); + printf("--------\n"); + printf("testsuite: Booster power states after test completion:\n"); + testsuite_logAllBoosterPowerStates(); + printf("--------\n"); + testsuite_stopBidib(); free(result->points); From 75a0ce3e2be8681ed3a3ec7764f666332270c1c4 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Wed, 4 Dec 2024 15:33:38 +0100 Subject: [PATCH 09/23] consistency for physical testsuites, improvements on checking point state for physical test for swtbahn-full --- test/physical/swtbahn-full/main.c | 39 +- test/physical/swtbahn-full/testsuite.c | 544 ++++++++++++++------- test/physical/swtbahn-standard/main.c | 45 +- test/physical/swtbahn-standard/testsuite.c | 3 +- test/physical/test_common.c | 43 +- test/physical/test_common.h | 2 + 6 files changed, 441 insertions(+), 235 deletions(-) diff --git a/test/physical/swtbahn-full/main.c b/test/physical/swtbahn-full/main.c index 85d2cd0..6ded28e 100755 --- a/test/physical/swtbahn-full/main.c +++ b/test/physical/swtbahn-full/main.c @@ -70,25 +70,19 @@ int main(int argc, char **argv) { printf("testsuite: Test case %d\n", atoi(argv[1])); t_testsuite_test_result *result = testsuite_initTestSuite(); - const int repetitions = atoi(argv[2]); - printf("--------\n"); - printf("testsuite: Track output states before test start:\n"); - testsuite_logAllTrackOutputStates(); - printf("--------\n"); - printf("testsuite: Booster power states before test start:\n"); - testsuite_logAllBoosterPowerStates(); - printf("--------\n"); - + // For cases 1-3, the track output state is set to OFF, + // as they do not involve any trains that should be driving around. + // If a previous test was aborted/failed/crashed, the system might not have + // been shut down properly, so trains might still have a set speed. + // In a new test execution, trains would then start to drive around. + // With the track output set to off, that's not a problem, and thus + // test cases 1-3 can be run even when a prior execution did not shut + // down properly. switch (atoi(argv[1])) { case 1: - ///TODO: Test if the track output state makes a difference. - // in https://github.com/uniba-swt/libbidib/commit/9fb28a411fcba765a9e3615703b7b7c64db28482 - // a line was introduced that would turn off the track output state - // for test cases 1-3. But it was not documented WHY. - //bidib_set_track_output_state_all(BIDIB_CS_OFF); - //sleep(1); + bidib_set_track_output_state_all(BIDIB_CS_OFF); for (int i = 0; i < repetitions; i++) { testsuite_case_pointParallel(result); } @@ -96,8 +90,7 @@ int main(int argc, char **argv) { break; case 2: - //bidib_set_track_output_state_all(BIDIB_CS_OFF); - //sleep(1); + bidib_set_track_output_state_all(BIDIB_CS_OFF); for (int i = 0; i < repetitions; i++) { testsuite_case_pointSerial(result); } @@ -105,8 +98,7 @@ int main(int argc, char **argv) { break; case 3: - //bidib_set_track_output_state_all(BIDIB_CS_OFF); - //sleep(1); + bidib_set_track_output_state_all(BIDIB_CS_OFF); for (int i = 0; i < repetitions; i++) { testsuite_case_signal(); } @@ -131,15 +123,6 @@ int main(int argc, char **argv) { default: break; } - sleep(1); - printf("--------\n"); - printf("testsuite: Track output states after test completion:\n"); - testsuite_logAllTrackOutputStates(); - printf("--------\n"); - printf("testsuite: Booster power states after test completion:\n"); - testsuite_logAllBoosterPowerStates(); - printf("--------\n"); - testsuite_stopBidib(); free(result->points); diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index 971cbec..7a7571d 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -42,8 +42,7 @@ t_testsuite_test_result *testsuite_initTestSuite() { char *excludedSignalAccessories[4] = {"platformlight1", "platformlight2", "platformlight4a", "platformlight4b"}; - t_testsuite_test_result *result = testsuite_initTestSuite_common(excludedSignalAccessories, 4); - return result; + return testsuite_initTestSuite_common(excludedSignalAccessories, 4); } void testsuite_case_signal() { @@ -76,6 +75,27 @@ bool route1(const char *train) { testsuite_switch_point("point20", "normal"); testsuite_switch_point("point19", "normal"); testsuite_switch_point("point18b", "reverse"); + + sleep(2); + // Check that points are in desired position + bool point_check = true; + point_check &= testsuite_check_point_aspect("point22", "reverse"); + point_check &= testsuite_check_point_aspect("point23", "normal"); + point_check &= testsuite_check_point_aspect("point24", "reverse"); + point_check &= testsuite_check_point_aspect("point12", "reverse"); + point_check &= testsuite_check_point_aspect("point13", "reverse"); + point_check &= testsuite_check_point_aspect("point14", "reverse"); + point_check &= testsuite_check_point_aspect("point15", "normal"); + point_check &= testsuite_check_point_aspect("point16", "reverse"); + point_check &= testsuite_check_point_aspect("point21", "reverse"); + point_check &= testsuite_check_point_aspect("point20", "normal"); + point_check &= testsuite_check_point_aspect("point19", "normal"); + point_check &= testsuite_check_point_aspect("point18b", "reverse"); + if (!point_check) { + printf("testsuite: route1 - one or more points are not in expected aspect."); + return false; + } + testsuite_set_signal("signal30", "aspect_go"); testsuite_set_signal("signal33", "aspect_go"); @@ -144,8 +164,35 @@ bool route2(const char *train) { testsuite_switch_point("point7", "normal"); testsuite_switch_point("point6", "reverse"); testsuite_switch_point("point17", "reverse"); + + sleep(2); + // Check that points are in desired position + bool point_check = true; + point_check &= testsuite_check_point_aspect("point22", "normal"); + point_check &= testsuite_check_point_aspect("point20", "reverse"); + point_check &= testsuite_check_point_aspect("point21", "reverse"); + point_check &= testsuite_check_point_aspect("point16", "reverse"); + point_check &= testsuite_check_point_aspect("point15", "reverse"); + point_check &= testsuite_check_point_aspect("point5", "reverse"); + point_check &= testsuite_check_point_aspect("point4", "reverse"); + point_check &= testsuite_check_point_aspect("point12", "reverse"); + point_check &= testsuite_check_point_aspect("point11", "reverse"); + point_check &= testsuite_check_point_aspect("point27", "reverse"); + point_check &= testsuite_check_point_aspect("point29", "reverse"); + point_check &= testsuite_check_point_aspect("point28", "reverse"); + point_check &= testsuite_check_point_aspect("point26", "normal"); + point_check &= testsuite_check_point_aspect("point9", "reverse"); + point_check &= testsuite_check_point_aspect("point8", "reverse"); + point_check &= testsuite_check_point_aspect("point1", "reverse"); + point_check &= testsuite_check_point_aspect("point7", "normal"); + point_check &= testsuite_check_point_aspect("point6", "reverse"); + point_check &= testsuite_check_point_aspect("point17", "reverse"); + if (!point_check) { + printf("testsuite: route2 - one or more points are not in expected aspect (1st check)."); + return false; + } - testsuite_driveTo("seg42b", 50, train); + testsuite_driveToStop("seg42b", 50, train); testsuite_switch_point("point16", "normal"); testsuite_switch_point("point15", "normal"); @@ -165,14 +212,47 @@ bool route2(const char *train) { testsuite_switch_point("point3", "reverse"); testsuite_switch_point("point4", "normal"); testsuite_switch_point("point5", "normal"); + + sleep(2); + // Check that points are in desired position + point_check &= testsuite_check_point_aspect("point16", "normal"); + point_check &= testsuite_check_point_aspect("point15", "normal"); + point_check &= testsuite_check_point_aspect("point14", "reverse"); + point_check &= testsuite_check_point_aspect("point13", "reverse"); + point_check &= testsuite_check_point_aspect("point12", "reverse"); + point_check &= testsuite_check_point_aspect("point24", "reverse"); + point_check &= testsuite_check_point_aspect("point23", "reverse"); + point_check &= testsuite_check_point_aspect("point19", "reverse"); + point_check &= testsuite_check_point_aspect("point18b", "normal"); + point_check &= testsuite_check_point_aspect("point18a", "reverse"); + point_check &= testsuite_check_point_aspect("point8", "normal"); + point_check &= testsuite_check_point_aspect("point9", "reverse"); + point_check &= testsuite_check_point_aspect("point26", "reverse"); + point_check &= testsuite_check_point_aspect("point27", "normal"); + point_check &= testsuite_check_point_aspect("point11", "normal"); + point_check &= testsuite_check_point_aspect("point3", "reverse"); + point_check &= testsuite_check_point_aspect("point4", "normal"); + point_check &= testsuite_check_point_aspect("point5", "normal"); + if (!point_check) { + printf("testsuite: route2 - one or more points are not in expected aspect (2nd check)."); + return false; + } - testsuite_driveTo("seg69", 50, train); + testsuite_driveToStop("seg69", 50, train); + testsuite_switch_point("point6", "normal"); testsuite_switch_point("point7", "reverse"); + sleep(2); + // Check that points are in desired position + point_check &= testsuite_check_point_aspect("point6", "normal"); + point_check &= testsuite_check_point_aspect("point7", "reverse"); + if (!point_check) { + printf("testsuite: route2 - one or more points are not in expected aspect (3rd check)."); + return false; + } testsuite_driveTo("seg46", 50, train); testsuite_driveToStop("seg47", 20, train); - return true; } @@ -197,6 +277,30 @@ bool route3(const char *train) { testsuite_switch_point("point8", "reverse"); testsuite_switch_point("point9", "normal"); testsuite_switch_point("point10", "reverse"); + + sleep(2); + // Check that points are in desired position + bool point_check = true; + point_check &= testsuite_check_point_aspect("point18b", "reverse"); + point_check &= testsuite_check_point_aspect("point19", "reverse"); + point_check &= testsuite_check_point_aspect("point23", "reverse"); + point_check &= testsuite_check_point_aspect("point24", "reverse"); + point_check &= testsuite_check_point_aspect("point12", "normal"); + point_check &= testsuite_check_point_aspect("point4", "reverse"); + point_check &= testsuite_check_point_aspect("point5", "reverse"); + point_check &= testsuite_check_point_aspect("point15", "reverse"); + point_check &= testsuite_check_point_aspect("point16", "normal"); + point_check &= testsuite_check_point_aspect("point17", "reverse"); + point_check &= testsuite_check_point_aspect("point6", "reverse"); + point_check &= testsuite_check_point_aspect("point7", "normal"); + point_check &= testsuite_check_point_aspect("point1", "reverse"); + point_check &= testsuite_check_point_aspect("point8", "reverse"); + point_check &= testsuite_check_point_aspect("point9", "normal"); + point_check &= testsuite_check_point_aspect("point10", "reverse"); + if (!point_check) { + printf("testsuite: route3 - one or more points are not in expected aspect."); + return false; + } testsuite_driveTo("seg29", -50, train); testsuite_driveToStop("seg78b", -20, train); @@ -224,6 +328,29 @@ bool route4(const char *train) { testsuite_switch_point("point24", "reverse"); testsuite_switch_point("point23", "normal"); testsuite_switch_point("point22", "reverse"); + + sleep(2); + // Check that points are in desired position + bool point_check = true; + point_check &= testsuite_check_point_aspect("point10", "reverse"); + point_check &= testsuite_check_point_aspect("point9", "normal"); + point_check &= testsuite_check_point_aspect("point8", "reverse"); + point_check &= testsuite_check_point_aspect("point1", "reverse"); + point_check &= testsuite_check_point_aspect("point7", "normal"); + point_check &= testsuite_check_point_aspect("point6", "reverse"); + point_check &= testsuite_check_point_aspect("point17", "reverse"); + point_check &= testsuite_check_point_aspect("point16", "normal"); + point_check &= testsuite_check_point_aspect("point15", "normal"); + point_check &= testsuite_check_point_aspect("point14", "reverse"); + point_check &= testsuite_check_point_aspect("point13", "reverse"); + point_check &= testsuite_check_point_aspect("point12", "reverse"); + point_check &= testsuite_check_point_aspect("point24", "reverse"); + point_check &= testsuite_check_point_aspect("point23", "normal"); + point_check &= testsuite_check_point_aspect("point22", "reverse"); + if (!point_check) { + printf("testsuite: route4 - one or more points are not in expected aspect."); + return false; + } testsuite_driveTo("seg58", 50, train); testsuite_driveToStop("seg59", 20, train); @@ -247,8 +374,32 @@ bool route5(const char *train) { testsuite_switch_point("point21", "reverse"); testsuite_switch_point("point20", "reverse"); - testsuite_driveTo("seg64", -50, train); + sleep(2); + // Check that points are in desired position + bool point_check = true; + point_check &= testsuite_check_point_aspect("point22", "reverse"); + point_check &= testsuite_check_point_aspect("point23", "normal"); + point_check &= testsuite_check_point_aspect("point24", "reverse"); + point_check &= testsuite_check_point_aspect("point12", "reverse"); + point_check &= testsuite_check_point_aspect("point13", "reverse"); + point_check &= testsuite_check_point_aspect("point14", "reverse"); + point_check &= testsuite_check_point_aspect("point15", "normal"); + point_check &= testsuite_check_point_aspect("point16", "reverse"); + point_check &= testsuite_check_point_aspect("point21", "reverse"); + point_check &= testsuite_check_point_aspect("point20", "reverse"); + if (!point_check) { + printf("testsuite: route5 - one or more points are not in expected aspect (1st check)."); + return false; + } + + testsuite_driveToStop("seg64", -50, train); testsuite_switch_point("point22", "normal"); + sleep(2); + // Check that point is in desired position + if (!testsuite_check_point_aspect("point21", "reverse")) { + printf("testsuite: route5 - point 21 is not in expected aspect (2nd check)."); + return false; + } testsuite_driveTo("seg58", -50, train); testsuite_driveToStop("seg59", -20, train); @@ -285,81 +436,93 @@ static void *route99(void *arg) { pthread_exit(NULL); } - while (true) { - // train1: forwards - testsuite_switch_point("point22", "reverse"); - testsuite_switch_point("point23", "normal"); - testsuite_switch_point("point24", "reverse"); - testsuite_switch_point("point12", "reverse"); - testsuite_switch_point("point13", "reverse"); - testsuite_switch_point("point14", "reverse"); - testsuite_switch_point("point15", "normal"); - testsuite_switch_point("point16", "reverse"); - testsuite_switch_point("point21", "reverse"); - testsuite_switch_point("point20", "normal"); - testsuite_switch_point("point19", "normal"); - testsuite_switch_point("point18b", "reverse"); - - sleep(1); - - testsuite_set_signal("signal30", "aspect_go"); - testsuite_set_signal("signal33", "aspect_go"); - testsuite_set_signal("signal35a", "aspect_go"); - testsuite_set_signal("signal35b", "aspect_go"); - testsuite_set_signal("signal37", "aspect_go"); - - sleep(1); - - testsuite_driveTo("seg57", 50, train1); - testsuite_set_signal("signal30", "aspect_stop"); - - testsuite_driveTo("seg64", 50, train1); - testsuite_set_signal("signal33", "aspect_stop"); - testsuite_set_signal("signal35a", "aspect_stop"); - testsuite_set_signal("signal35b", "aspect_stop"); - - testsuite_driveTo("seg69", 50, train1); - testsuite_set_signal("signal37", "aspect_stop"); - - testsuite_driveTo("seg46", 50, train1); - sleep(1); - testsuite_driveTo("seg46", 40, train1); - sleep(1); - testsuite_driveTo("seg46", 30, train1); - sleep(1); - testsuite_driveToStop("seg47", 20, train1); - - sleep(5); - - // train1: backwards - testsuite_set_signal("signal26", "aspect_go"); - testsuite_set_signal("signal38", "aspect_go"); - testsuite_set_signal("signal36", "aspect_go"); - testsuite_set_signal("signal34", "aspect_go"); - testsuite_set_signal("signal32", "aspect_go"); - - sleep(1); - - testsuite_driveTo("seg45", -50, train1); - testsuite_set_signal("signal26", "aspect_stop"); - - testsuite_driveTo("seg67", -50, train1); - testsuite_set_signal("signal38", "aspect_stop"); - testsuite_set_signal("signal36", "aspect_stop"); - - testsuite_driveTo("seg62", -50, train1); - testsuite_set_signal("signal34", "aspect_stop"); - testsuite_set_signal("signal32", "aspect_stop"); - - testsuite_driveTo("seg60", -50, train1); - testsuite_driveTo("seg53", -40, train1); - testsuite_driveTo("seg57", -30, train1); - testsuite_driveTo("seg58", -20, train1); - sleep(2); - testsuite_driveToStop("seg58", -20, train1); - - sleep(5); + // train1: forwards + testsuite_switch_point("point22", "reverse"); + testsuite_switch_point("point23", "normal"); + testsuite_switch_point("point24", "reverse"); + testsuite_switch_point("point12", "reverse"); + testsuite_switch_point("point13", "reverse"); + testsuite_switch_point("point14", "reverse"); + testsuite_switch_point("point15", "normal"); + testsuite_switch_point("point16", "reverse"); + testsuite_switch_point("point21", "reverse"); + testsuite_switch_point("point20", "normal"); + testsuite_switch_point("point19", "normal"); + testsuite_switch_point("point18b", "reverse"); + + sleep(1); + + testsuite_set_signal("signal30", "aspect_go"); + testsuite_set_signal("signal33", "aspect_go"); + testsuite_set_signal("signal35a", "aspect_go"); + testsuite_set_signal("signal35b", "aspect_go"); + testsuite_set_signal("signal37", "aspect_go"); + + sleep(1); + + // Check that points are in desired position + bool point_check = true; + point_check &= testsuite_check_point_aspect("point22", "reverse"); + point_check &= testsuite_check_point_aspect("point23", "normal"); + point_check &= testsuite_check_point_aspect("point24", "reverse"); + point_check &= testsuite_check_point_aspect("point12", "reverse"); + point_check &= testsuite_check_point_aspect("point13", "reverse"); + point_check &= testsuite_check_point_aspect("point14", "reverse"); + point_check &= testsuite_check_point_aspect("point15", "normal"); + point_check &= testsuite_check_point_aspect("point16", "reverse"); + point_check &= testsuite_check_point_aspect("point21", "reverse"); + point_check &= testsuite_check_point_aspect("point20", "normal"); + point_check &= testsuite_check_point_aspect("point19", "normal"); + point_check &= testsuite_check_point_aspect("point18b", "reverse"); + if (!point_check) { + printf("testsuite: route99 - one or more points are not in expected aspect."); + pthread_exit(NULL); } + + testsuite_driveTo("seg57", 50, train1); + testsuite_set_signal("signal30", "aspect_stop"); + + testsuite_driveTo("seg64", 50, train1); + testsuite_set_signal("signal33", "aspect_stop"); + testsuite_set_signal("signal35a", "aspect_stop"); + testsuite_set_signal("signal35b", "aspect_stop"); + + testsuite_driveTo("seg69", 50, train1); + testsuite_set_signal("signal37", "aspect_stop"); + + testsuite_driveTo("seg46", 50, train1); + sleep(1); + testsuite_driveToStop("seg47", 20, train1); + + sleep(4); + + // train1: backwards + testsuite_set_signal("signal26", "aspect_go"); + testsuite_set_signal("signal38", "aspect_go"); + testsuite_set_signal("signal36", "aspect_go"); + testsuite_set_signal("signal34", "aspect_go"); + testsuite_set_signal("signal32", "aspect_go"); + + sleep(1); + + testsuite_driveTo("seg45", -50, train1); + testsuite_set_signal("signal26", "aspect_stop"); + + testsuite_driveTo("seg67", -50, train1); + testsuite_set_signal("signal38", "aspect_stop"); + testsuite_set_signal("signal36", "aspect_stop"); + + testsuite_driveTo("seg62", -50, train1); + testsuite_set_signal("signal34", "aspect_stop"); + testsuite_set_signal("signal32", "aspect_stop"); + + testsuite_driveTo("seg60", -50, train1); + testsuite_driveTo("seg53", -40, train1); + testsuite_driveTo("seg58", -30, train1); + sleep(2); + testsuite_driveToStop("seg58", -20, train1); + sleep(2); + pthread_exit(NULL); } static void *route100(void *arg) { @@ -369,102 +532,116 @@ static void *route100(void *arg) { pthread_exit(NULL); } - while (true) { - // train2: forwards - testsuite_switch_point("point10", "reverse"); - testsuite_switch_point("point9", "normal"); - testsuite_switch_point("point8", "reverse"); - testsuite_switch_point("point1", "reverse"); - testsuite_switch_point("point7", "normal"); - testsuite_switch_point("point6", "normal"); - testsuite_switch_point("point5", "normal"); - testsuite_switch_point("point4", "normal"); - testsuite_switch_point("point3", "reverse"); - testsuite_switch_point("point11", "reverse"); - - sleep(1); - - testsuite_set_signal("signal43", "aspect_shunt"); - testsuite_set_signal("signal19", "aspect_go"); - testsuite_set_signal("signal3", "aspect_go"); - testsuite_set_signal("signal1", "aspect_go"); - testsuite_set_signal("signal13", "aspect_go"); - testsuite_set_signal("signal11", "aspect_go"); - testsuite_set_signal("signal10", "aspect_go"); - testsuite_set_signal("signal8", "aspect_go"); - - sleep(1); - - testsuite_driveTo("seg77", 126, train2); - testsuite_set_signal("signal43", "aspect_stop"); - - testsuite_driveTo("seg26", 126, train2); - testsuite_set_signal("signal19", "aspect_stop"); - - testsuite_driveTo("seg1", 126, train2); - testsuite_set_signal("signal3", "aspect_stop"); - testsuite_set_signal("signal1", "aspect_stop"); - - testsuite_driveTo("seg15", 126, train2); - testsuite_set_signal("signal13", "aspect_stop"); - testsuite_set_signal("signal11", "aspect_stop"); - - testsuite_driveTo("seg11", 126, train2); - testsuite_set_signal("signal10", "aspect_stop"); - testsuite_set_signal("signal8", "aspect_stop"); - - testsuite_driveTo("seg31b", 50, train2); - sleep(1); - testsuite_driveTo("seg31b", 40, train2); - sleep(1); - testsuite_driveTo("seg31a", 30, train2); - sleep(1); - testsuite_driveToStop("seg31a", 20, train2); - - sleep(5); - - // train2: backwards - testsuite_set_signal("signal22a", "aspect_go"); - testsuite_set_signal("signal22b", "aspect_go"); - testsuite_set_signal("signal9", "aspect_go"); - testsuite_set_signal("signal12", "aspect_go"); - testsuite_set_signal("signal14", "aspect_go"); - testsuite_set_signal("signal2", "aspect_go"); - testsuite_set_signal("signal4a", "aspect_go"); - testsuite_set_signal("signal4b", "aspect_go"); - testsuite_set_signal("signal20", "aspect_shunt"); - - sleep(1); - - testsuite_driveTo("seg32", -126, train2); - testsuite_set_signal("signal22a", "aspect_stop"); - testsuite_set_signal("signal22b", "aspect_stop"); - - testsuite_driveTo("seg13", -126, train2); - testsuite_set_signal("signal9", "aspect_stop"); - - testsuite_driveTo("seg17", -126, train2); - testsuite_set_signal("signal12", "aspect_stop"); - testsuite_set_signal("signal14", "aspect_stop"); - - testsuite_driveTo("seg3", -126, train2); - testsuite_set_signal("signal2", "aspect_stop"); - testsuite_set_signal("signal4a", "aspect_stop"); - testsuite_set_signal("signal4b", "aspect_stop"); - - testsuite_driveTo("seg28", -50, train2); - testsuite_set_signal("signal20", "aspect_stop"); - - testsuite_driveTo("seg78a", -50, train2); - sleep(1); - testsuite_driveTo("seg78a", -40, train2); - sleep(1); - testsuite_driveTo("seg78a", -30, train2); - sleep(1); - testsuite_driveToStop("seg78a", -20, train2); - - sleep(5); + // train2: forwards + testsuite_switch_point("point10", "reverse"); + testsuite_switch_point("point9", "normal"); + testsuite_switch_point("point8", "reverse"); + testsuite_switch_point("point1", "reverse"); + testsuite_switch_point("point7", "normal"); + testsuite_switch_point("point6", "normal"); + testsuite_switch_point("point5", "normal"); + testsuite_switch_point("point4", "normal"); + testsuite_switch_point("point3", "reverse"); + testsuite_switch_point("point11", "reverse"); + + sleep(1); + + testsuite_set_signal("signal43", "aspect_shunt"); + testsuite_set_signal("signal19", "aspect_go"); + testsuite_set_signal("signal3", "aspect_go"); + testsuite_set_signal("signal1", "aspect_go"); + testsuite_set_signal("signal13", "aspect_go"); + testsuite_set_signal("signal11", "aspect_go"); + testsuite_set_signal("signal10", "aspect_go"); + testsuite_set_signal("signal8", "aspect_go"); + + sleep(1); + + // Check that points are in desired position + bool point_check = true; + point_check &= testsuite_check_point_aspect("point10", "reverse"); + point_check &= testsuite_check_point_aspect("point9", "normal"); + point_check &= testsuite_check_point_aspect("point8", "reverse"); + point_check &= testsuite_check_point_aspect("point1", "reverse"); + point_check &= testsuite_check_point_aspect("point7", "normal"); + point_check &= testsuite_check_point_aspect("point6", "normal"); + point_check &= testsuite_check_point_aspect("point5", "normal"); + point_check &= testsuite_check_point_aspect("point4", "normal"); + point_check &= testsuite_check_point_aspect("point3", "reverse"); + point_check &= testsuite_check_point_aspect("point11", "reverse"); + if (!point_check) { + printf("testsuite: route100 - one or more points are not in expected aspect."); + pthread_exit(NULL); } + + testsuite_driveTo("seg77", 50, train2); + testsuite_set_signal("signal43", "aspect_stop"); + + testsuite_driveTo("seg26", 50, train2); + testsuite_set_signal("signal19", "aspect_stop"); + + testsuite_driveTo("seg1", 50, train2); + testsuite_set_signal("signal3", "aspect_stop"); + testsuite_set_signal("signal1", "aspect_stop"); + + testsuite_driveTo("seg15", 50, train2); + testsuite_set_signal("signal13", "aspect_stop"); + testsuite_set_signal("signal11", "aspect_stop"); + + testsuite_driveTo("seg11", 50, train2); + testsuite_set_signal("signal10", "aspect_stop"); + testsuite_set_signal("signal8", "aspect_stop"); + + testsuite_driveTo("seg31b", 50, train2); + testsuite_driveTo("seg31b", 40, train2); + sleep(1); + testsuite_driveTo("seg31a", 30, train2); + sleep(1); + testsuite_driveToStop("seg31a", 20, train2); + + sleep(4); + + // train2: backwards + testsuite_set_signal("signal22a", "aspect_go"); + testsuite_set_signal("signal22b", "aspect_go"); + testsuite_set_signal("signal9", "aspect_go"); + testsuite_set_signal("signal12", "aspect_go"); + testsuite_set_signal("signal14", "aspect_go"); + testsuite_set_signal("signal2", "aspect_go"); + testsuite_set_signal("signal4a", "aspect_go"); + testsuite_set_signal("signal4b", "aspect_go"); + testsuite_set_signal("signal20", "aspect_shunt"); + + sleep(1); + + testsuite_driveTo("seg32", -50, train2); + testsuite_set_signal("signal22a", "aspect_stop"); + testsuite_set_signal("signal22b", "aspect_stop"); + + testsuite_driveTo("seg13", -50, train2); + testsuite_set_signal("signal9", "aspect_stop"); + + testsuite_driveTo("seg17", -50, train2); + testsuite_set_signal("signal12", "aspect_stop"); + testsuite_set_signal("signal14", "aspect_stop"); + + testsuite_driveTo("seg3", -50, train2); + testsuite_set_signal("signal2", "aspect_stop"); + testsuite_set_signal("signal4a", "aspect_stop"); + testsuite_set_signal("signal4b", "aspect_stop"); + + testsuite_driveTo("seg28", -50, train2); + testsuite_set_signal("signal20", "aspect_stop"); + + testsuite_driveTo("seg78a", -50, train2); + sleep(1); + testsuite_driveTo("seg78a", -40, train2); + sleep(1); + testsuite_driveTo("seg78a", -30, train2); + sleep(1); + testsuite_driveToStop("seg78a", -20, train2); + sleep(2); + pthread_exit(NULL); } void testsuite_case_swtbahnFullMultipleTrains(const char *train1, const char *train2) { @@ -490,8 +667,23 @@ bool route_custom_short(const char *train) { testsuite_switch_point("point5", "normal"); testsuite_switch_point("point4", "normal"); testsuite_switch_point("point3", "normal"); + + sleep(2); + // Check that points are in desired position + bool point_check = true; + point_check &= testsuite_check_point_aspect("point2", "normal"); + point_check &= testsuite_check_point_aspect("point1", "normal"); + point_check &= testsuite_check_point_aspect("point7", "normal"); + point_check &= testsuite_check_point_aspect("point6", "normal"); + point_check &= testsuite_check_point_aspect("point5", "normal"); + point_check &= testsuite_check_point_aspect("point4", "normal"); + point_check &= testsuite_check_point_aspect("point3", "normal"); + if (!point_check) { + printf("testsuite: route_custom_short - one or more points are not in expected aspect."); + pthread_exit(NULL); + } - testsuite_driveToStop("seg7a", 50, train); + testsuite_driveTo("seg7a", 50, train); testsuite_driveToStop("seg7b", 50, train); return true; } diff --git a/test/physical/swtbahn-standard/main.c b/test/physical/swtbahn-standard/main.c index 0e47f07..04d5856 100755 --- a/test/physical/swtbahn-standard/main.c +++ b/test/physical/swtbahn-standard/main.c @@ -23,6 +23,7 @@ * present libbidib (in alphabetic order by surname): * * - Christof Lehanka + * - Bernhard Luedtke * - Eugene Yip * */ @@ -57,48 +58,43 @@ int main(int argc, char **argv) { return 0; } - if (bidib_start_serial("/dev/ttyUSB0", "../../swtbahn-cli/configurations/swtbahn-standard", 200)) { + if (bidib_start_serial("/dev/ttyUSB0", "../../swtbahn-cli/configurations/swtbahn-standard", 0)) { printf("testsuite: libbidib failed to start\n"); return 0; + } else { + printf("testsuite: libbidib started\n"); } sleep(2); // Wait for the points to finish switching to their default positions. printf("testsuite: Test case %d\n", atoi(argv[1])); t_testsuite_test_result *result = testsuite_initTestSuite(); const int repetitions = atoi(argv[2]); - - printf("--------\n"); - printf("testsuite: Track output states before test start:\n"); - testsuite_logAllTrackOutputStates(); - printf("--------\n"); - printf("testsuite: Booster power states before test start:\n"); - testsuite_logAllBoosterPowerStates(); - printf("--------\n"); - + + // For cases 1-3, the track output state is set to OFF, + // as they do not involve any trains that should be driving around. + // If a previous test was aborted/failed/crashed, the system might not have + // been shut down properly, so trains might still have a set speed. + // In a new test execution, trains would then start to drive around. + // With the track output set to off, that's not a problem, and thus + // test cases 1-3 can be run even when a prior execution did not shut + // down properly. switch (atoi(argv[1])) { case 1: - ///TODO: Test if the track output state makes a difference. - // in https://github.com/uniba-swt/libbidib/commit/9fb28a411fcba765a9e3615703b7b7c64db28482 - // a line was introduced that would turn off the track output state - // for test cases 1-3. But it was not documented WHY. - //bidib_set_track_output_state_all(BIDIB_CS_GO); - //sleep(1); + bidib_set_track_output_state_all(BIDIB_CS_OFF); for (int i = 0; i < repetitions; i++) { testsuite_case_pointParallel(result); } testsuite_printTestResults(result); break; case 2: - //bidib_set_track_output_state_all(BIDIB_CS_GO); - //sleep(1); + bidib_set_track_output_state_all(BIDIB_CS_OFF); for (int i = 0; i < repetitions; i++) { testsuite_case_pointSerial(result); } testsuite_printTestResults(result); break; case 3: - //bidib_set_track_output_state_all(BIDIB_CS_GO); - //sleep(1); + bidib_set_track_output_state_all(BIDIB_CS_OFF); for (int i = 0; i < repetitions; i++) { testsuite_case_signal(); } @@ -117,16 +113,9 @@ int main(int argc, char **argv) { default: break; } - sleep(1); - printf("--------\n"); - printf("testsuite: Track output states after test completion:\n"); - testsuite_logAllTrackOutputStates(); - printf("--------\n"); - printf("testsuite: Booster power states after test completion:\n"); - testsuite_logAllBoosterPowerStates(); - printf("--------\n"); testsuite_stopBidib(); + free(result->points); free(result); return 0; diff --git a/test/physical/swtbahn-standard/testsuite.c b/test/physical/swtbahn-standard/testsuite.c index c644da2..9141033 100644 --- a/test/physical/swtbahn-standard/testsuite.c +++ b/test/physical/swtbahn-standard/testsuite.c @@ -39,8 +39,7 @@ // This initialisation function is specific to SWTbahn Standard. t_testsuite_test_result *testsuite_initTestSuite() { char *excludedSignalAccessories[1] = {"platformlights"}; - t_testsuite_test_result *result = testsuite_initTestSuite_common(excludedSignalAccessories, 1); - return result; + return testsuite_initTestSuite_common(excludedSignalAccessories, 1); } void testsuite_case_signal() { diff --git a/test/physical/test_common.c b/test/physical/test_common.c index 62598a8..decccf7 100644 --- a/test/physical/test_common.c +++ b/test/physical/test_common.c @@ -119,8 +119,16 @@ void testsuite_stopBidib(void) { } void testsuite_signal_callback_handler(int signum) { + printf("testsuite: SIGINT - before stopping, debug logs:\n"); + printf(" Track output states:\n"); + testsuite_logAllTrackOutputStates(); + printf("\n"); + printf(" Booster power states:\n"); + testsuite_logAllBoosterPowerStates(); + printf("\n"); + printf("testsuite: SIGINT - now stopping libbidib.\n"); testsuite_stopBidib(); - printf("testsuite: SIGINT - stopping libbidib \n"); + printf("testsuite: SIGINT - libbidib stopped.\n"); exit(signum); } @@ -219,6 +227,39 @@ void testsuite_switch_point(const char *point, const char *aspect) { bidib_flush(); } +bool testsuite_check_point_aspect(const char *point, const char *aspect) { + if (point == NULL || aspect == NULL) { + printf("testsuite: check point aspect - invalid parameters"); + return false; + } + t_bidib_unified_accessory_state_query state = bidib_get_point_state(point); + if (state.known) { + printf("testsuite: check point aspect - unknown point"); + bidib_free_unified_accessory_state_query(state); + return false; + } + if (state.type == BIDIB_ACCESSORY_BOARD) { + if (strcmp(state.board_accessory_state.state_id, aspect) == 0) { + bidib_free_unified_accessory_state_query(state); + return true; + } else { + printf("testsuite: check point aspect - point %s is in aspect %s, not in %s", + point, state.board_accessory_state.state_id, aspect); + } + } else { + if (strcmp(state.dcc_accessory_state.state_id, aspect) == 0) { + bidib_free_unified_accessory_state_query(state); + return true; + } else { + printf("testsuite: check point aspect - point %s is in aspect %s, not in %s", + point, state.dcc_accessory_state.state_id, aspect); + } + } + + bidib_free_unified_accessory_state_query(state); + return false; +} + void testsuite_case_signal_common(char **aspects, size_t aspects_len) { for (size_t i = 0; i < aspects_len; i++) { for (size_t n = 0; n < signals.length; n++) { diff --git a/test/physical/test_common.h b/test/physical/test_common.h index d772c3c..2445159 100644 --- a/test/physical/test_common.h +++ b/test/physical/test_common.h @@ -79,6 +79,8 @@ void testsuite_driveToStop(const char *segment, int speed, const char *train); // Accessories void testsuite_set_signal(const char *signal, const char *aspect); void testsuite_switch_point(const char *point, const char *aspect); +// Returns true if the point's aspect matches a certain value/aspect. Otherwise returns false. +bool testsuite_check_point_aspect(const char *point, const char *aspect); // Common test base void testsuite_case_signal_common(char **aspects, size_t aspects_len); From cf458620faf1549508425320b0f43cfe1c2dda83 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Wed, 4 Dec 2024 15:40:52 +0100 Subject: [PATCH 10/23] point aspect validation for swtbahn-standard physical test + bugfix --- test/physical/swtbahn-full/testsuite.c | 2 +- test/physical/swtbahn-standard/testsuite.c | 85 +++++++++++++++++++++- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index 7a7571d..537d00c 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -680,7 +680,7 @@ bool route_custom_short(const char *train) { point_check &= testsuite_check_point_aspect("point3", "normal"); if (!point_check) { printf("testsuite: route_custom_short - one or more points are not in expected aspect."); - pthread_exit(NULL); + return false; } testsuite_driveTo("seg7a", 50, train); diff --git a/test/physical/swtbahn-standard/testsuite.c b/test/physical/swtbahn-standard/testsuite.c index 9141033..3825fa9 100644 --- a/test/physical/swtbahn-standard/testsuite.c +++ b/test/physical/swtbahn-standard/testsuite.c @@ -110,8 +110,19 @@ void testsuite_case_swtbahnStandardTrackCoverage(const char *train) { testsuite_switch_point("point1", "normal"); testsuite_switch_point("point2", "normal"); testsuite_switch_point("point3", "normal"); + + sleep(2); + // Check that points are in desired position + bool point_check = true; + point_check &= testsuite_check_point_aspect("point1", "normal"); + point_check &= testsuite_check_point_aspect("point2", "normal"); + point_check &= testsuite_check_point_aspect("point3", "normal"); + if (!point_check) { + printf("testsuite: standard track coverage - one or more points are not in expected aspect (1st check)."); + return; + } - testsuite_driveTo("seg12", 30, train); + testsuite_driveToStop("seg12", 30, train); testsuite_switch_point("point6", "reverse"); testsuite_switch_point("point8", "reverse"); @@ -124,25 +135,74 @@ void testsuite_case_swtbahnStandardTrackCoverage(const char *train) { testsuite_switch_point("point9", "reverse"); testsuite_switch_point("point11", "reverse"); + sleep(2); + // Check that points are in desired position + point_check &= testsuite_check_point_aspect("point6", "reverse"); + point_check &= testsuite_check_point_aspect("point8", "reverse"); + point_check &= testsuite_check_point_aspect("point2", "reverse"); + point_check &= testsuite_check_point_aspect("point3", "reverse"); + point_check &= testsuite_check_point_aspect("point4", "reverse"); + point_check &= testsuite_check_point_aspect("point5", "reverse"); + point_check &= testsuite_check_point_aspect("point12", "normal"); + point_check &= testsuite_check_point_aspect("point10", "reverse"); + point_check &= testsuite_check_point_aspect("point9", "reverse"); + point_check &= testsuite_check_point_aspect("point11", "reverse"); + if (!point_check) { + printf("testsuite: standard track coverage - one or more points are not in expected aspect (2nd check)."); + return; + } + testsuite_driveToStop("seg37", 30, train); testsuite_switch_point("point12", "reverse"); + sleep(2); + // Check that point is in desired position + if (!testsuite_check_point_aspect("point12", "reverse")) { + printf("testsuite: route5 - point 12 is not in expected aspect (3rd check)."); + return; + } testsuite_driveToStop("seg40", -30, train); testsuite_switch_point("point12", "normal"); testsuite_switch_point("point11", "normal"); testsuite_switch_point("point10", "normal"); + + sleep(2); + // Check that points are in desired position + point_check &= testsuite_check_point_aspect("point12", "normal"); + point_check &= testsuite_check_point_aspect("point11", "normal"); + point_check &= testsuite_check_point_aspect("point10", "normal"); + if (!point_check) { + printf("testsuite: standard track coverage - one or more points are not in expected aspect (4th check)."); + return; + } - testsuite_driveTo("seg28", 30, train); + testsuite_driveToStop("seg28", 30, train); testsuite_switch_point("point7", "normal"); testsuite_switch_point("point4", "normal"); testsuite_switch_point("point9", "normal"); + + sleep(2); + // Check that points are in desired position + point_check &= testsuite_check_point_aspect("point7", "normal"); + point_check &= testsuite_check_point_aspect("point4", "normal"); + point_check &= testsuite_check_point_aspect("point9", "normal"); + if (!point_check) { + printf("testsuite: standard track coverage - one or more points are not in expected aspect (5th check)."); + return; + } - testsuite_driveTo("seg21", 30, train); + testsuite_driveToStop("seg21", 30, train); testsuite_switch_point("point5", "normal"); + sleep(2); + // Check that point is in desired position + if (!testsuite_check_point_aspect("point5", "normal")) { + printf("testsuite: route5 - point 5 is not in expected aspect (6th check)."); + return; + } testsuite_driveTo("seg28", 30, train); @@ -152,10 +212,29 @@ void testsuite_case_swtbahnStandardTrackCoverage(const char *train) { testsuite_switch_point("point3", "normal"); testsuite_switch_point("point6", "normal"); testsuite_switch_point("point1", "reverse"); + + sleep(2); + // Check that points are in desired position + point_check &= testsuite_check_point_aspect("point7", "reverse"); + point_check &= testsuite_check_point_aspect("point8", "normal"); + point_check &= testsuite_check_point_aspect("point2", "reverse"); + point_check &= testsuite_check_point_aspect("point3", "normal"); + point_check &= testsuite_check_point_aspect("point6", "normal"); + point_check &= testsuite_check_point_aspect("point1", "reverse"); + if (!point_check) { + printf("testsuite: standard track coverage - one or more points are not in expected aspect (7th check)."); + return; + } testsuite_driveToStop("seg4", 30, train); testsuite_switch_point("point1", "normal"); + sleep(2); + // Check that point is in desired position + if (!testsuite_check_point_aspect("point1", "normal")) { + printf("testsuite: route5 - point 1 is not in expected aspect (8th check)."); + return; + } testsuite_driveTo("seg1", -20, train); sleep(1); From eec24899be17eb7ddacd483ce8fb555040975e81 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Thu, 5 Dec 2024 09:59:45 +0100 Subject: [PATCH 11/23] fix oversight in merging master into fix-physical-test --- src/state/bidib_state_setter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/state/bidib_state_setter.c b/src/state/bidib_state_setter.c index 2817185..fac8f0d 100644 --- a/src/state/bidib_state_setter.c +++ b/src/state/bidib_state_setter.c @@ -150,8 +150,8 @@ void bidib_state_accessory_state(t_bidib_node_address node_address, uint8_t numb syslog_libbidib(LOG_ERR, "bidib_state_accessory_state: aspect mapping for accessory %s is NULL", accessory_mapping->id->str); - pthread_rwlock_unlock(&bidib_state_boards_rwlock); - pthread_rwlock_unlock(&bidib_state_track_rwlock); + pthread_rwlock_unlock(&bidib_boards_rwlock); + pthread_mutex_unlock(&trackstate_accessories_mutex); return; } if (accessory_state->data.state_id == NULL) { From 1575444934b9e8c55c10b47d1d5e67961f6358b6 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Thu, 5 Dec 2024 11:30:51 +0100 Subject: [PATCH 12/23] added "is bidib running" util and a physical test occupancy observer/watchdog prototype. --- include/highlevel/bidib_highlevel_util.h | 10 +- src/highlevel/bidib_highlevel_util.c | 4 + test/physical/swtbahn-full/testsuite.c | 170 +++++++++++++++++++++++ test/physical/test_common.c | 39 +++++- test/physical/test_common.h | 3 + 5 files changed, 220 insertions(+), 6 deletions(-) diff --git a/include/highlevel/bidib_highlevel_util.h b/include/highlevel/bidib_highlevel_util.h index 1214b6e..ddccb7e 100644 --- a/include/highlevel/bidib_highlevel_util.h +++ b/include/highlevel/bidib_highlevel_util.h @@ -97,12 +97,20 @@ uint8_t *bidib_read_error_message(void); */ void bidib_flush(void); +/** + * Check if bidib is currently running. + * + * @return true if bidib is running + * @return false otherwise + */ +bool bidib_is_running(); + /** * Customised syslog function to prepend libbidib to log messages. * This is needed to differentiate log messages that originate from this bidib * library or from a user application. */ - void syslog_libbidib(int priority, const char *format, ...); +void syslog_libbidib(int priority, const char *format, ...); #endif diff --git a/src/highlevel/bidib_highlevel_util.c b/src/highlevel/bidib_highlevel_util.c index 71430ab..de7fb33 100644 --- a/src/highlevel/bidib_highlevel_util.c +++ b/src/highlevel/bidib_highlevel_util.c @@ -257,6 +257,10 @@ void bidib_stop(void) { } } +bool bidib_is_running() { + return bidib_running; +} + void syslog_libbidib(int priority, const char *format, ...) { char string[1024]; va_list arg; diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index ffb0ed4..6e6965d 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -58,6 +58,78 @@ void testsuite_case_pointSerial(t_testsuite_test_result *result) { testsuite_case_pointSerial_common(result); } +/* +typedef struct { + char *train; + char **forbidden_segments; + int forbidden_segments_len; + // if true, only checks whether any of the forbidden segments gets occupied, + // not if it gets occupied *by the train*. + bool check_occ_only; + // To be set by the caller to request the observer to terminate. + volatile bool stop_requested; +} t_bidib_occ_observer_info_multi; +*/ +typedef struct { + char *train; + char *forbidden_segment; + // if true, only checks whether any of the forbidden segments gets occupied, + // not if it gets occupied *by the train*. + bool check_occ_only; + // To be set by the caller to request the observer to terminate. + volatile bool stop_requested; +} t_bidib_occ_observer_info; + +void free_obs_info_util(t_bidib_occ_observer_info *obs_info_ptr) { + if (obs_info_ptr != NULL) { + if (obs_info_ptr->forbidden_segment != NULL) { + free(obs_info_ptr->forbidden_segment); + } + if (obs_info_ptr->train != NULL) { + free(obs_info_ptr->train); + } + free(obs_info_ptr); + obs_info_ptr = NULL; + } +} + +// Expects the arg pointer to be a pointer to a t_bidib_occ_observer_info struct. +static void *occupancy_observer(void *arg) { + if (arg == NULL) { + printf("testsuite: Occ-Observer exit: arg is NULL\n"); + pthread_exit(NULL); + } + t_bidib_occ_observer_info *obs_info = arg; + t_bidib_dcc_address_query tr_dcc_addr = bidib_get_train_dcc_addr(obs_info->train); + if (!tr_dcc_addr.known) { + printf("testsuite: Occ-Observer exit: tr_dcc_addr unknown\n"); + pthread_exit(NULL); + } + while (!obs_info->stop_requested) { + const char *i_segmt = obs_info->forbidden_segment; + bool violation = false; + if (i_segmt == NULL) { + continue; + } else if (obs_info->check_occ_only) { + violation = testsuite_is_segment_occupied(i_segmt); + } else { + violation = testsuite_is_segment_occupied_by_dcc_addr(i_segmt, tr_dcc_addr.dcc_address); + } + if (violation) { + printf("!!!\nOccupancy Observer: Train %s (or something else) occupies forbidden " + "segment %s! Stopping train, then stopping bidib.\n!!!\n", + obs_info->train, i_segmt); + bidib_set_train_speed(obs_info->train, 0, "master"); + bidib_flush(); + // Stop via the signal handler for consistent debugging + testsuite_signal_callback_handler(-1); + pthread_exit(NULL); + } + usleep(100000); // 0.1s + } + pthread_exit(NULL); +} + bool route1(const char *train) { if (!testsuite_trainReady(train, "seg58")) { return false; @@ -429,6 +501,18 @@ void testsuite_case_swtbahnFullTrackCoverage(const char *train) { } } +/* +typedef struct { + char *train; + char *forbidden_segment; + // if true, only checks whether any of the forbidden segments gets occupied, + // not if it gets occupied *by the train*. + bool check_occ_only; + // To be set by the caller to request the observer to terminate. + volatile bool stop_requested; +} t_bidib_occ_observer_info; +*/ + static void *route99(void *arg) { const char *train1 = arg; @@ -478,19 +562,65 @@ static void *route99(void *arg) { printf("testsuite: route99 - one or more points are not in expected aspect."); pthread_exit(NULL); } + + static pthread_t route99_observer_thread; + + t_bidib_occ_observer_info *obs1_info = malloc(sizeof(t_bidib_occ_observer_info)); + obs1_info->check_occ_only = false; + obs1_info->train = strdup(train1); + obs1_info->stop_requested = false; + obs1_info->forbidden_segment = strdup("seg60"); // skip 1 to give enough time for drive_to. + + pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg57", 50, train1); + + obs1_info->stop_requested = true; + pthread_join(route99_observer_thread, NULL); + testsuite_set_signal("signal30", "aspect_stop"); + + + obs1_info->stop_requested = false; + free(obs1_info->forbidden_segment); + obs1_info->forbidden_segment = strdup("seg66"); // skip 1 to give enough time for drive_to. + pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg64", 50, train1); + + obs1_info->stop_requested = true; + pthread_join(route99_observer_thread, NULL); + testsuite_set_signal("signal33", "aspect_stop"); testsuite_set_signal("signal35a", "aspect_stop"); testsuite_set_signal("signal35b", "aspect_stop"); + + obs1_info->stop_requested = false; + free(obs1_info->forbidden_segment); + obs1_info->forbidden_segment = strdup("seg40"); // skip 1 to give enough time for drive_to. + pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg69", 50, train1); + + obs1_info->stop_requested = true; + pthread_join(route99_observer_thread, NULL); + testsuite_set_signal("signal37", "aspect_stop"); + + obs1_info->stop_requested = false; + free(obs1_info->forbidden_segment); + obs1_info->forbidden_segment = strdup("seg47"); + pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg46", 50, train1); + + obs1_info->stop_requested = true; + pthread_join(route99_observer_thread, NULL); + sleep(1); testsuite_driveToStop("seg47", 20, train1); @@ -504,24 +634,64 @@ static void *route99(void *arg) { testsuite_set_signal("signal32", "aspect_go"); sleep(1); + + obs1_info->stop_requested = false; + free(obs1_info->forbidden_segment); + obs1_info->forbidden_segment = strdup("seg48"); // skip 1 to give enough time for drive_to. + pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg45", -50, train1); + + obs1_info->stop_requested = true; + pthread_join(route99_observer_thread, NULL); + testsuite_set_signal("signal26", "aspect_stop"); + + obs1_info->stop_requested = false; + free(obs1_info->forbidden_segment); + obs1_info->forbidden_segment = strdup("seg34"); // skip 1 to give enough time for drive_to. + pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg67", -50, train1); + + obs1_info->stop_requested = true; + pthread_join(route99_observer_thread, NULL); + testsuite_set_signal("signal38", "aspect_stop"); testsuite_set_signal("signal36", "aspect_stop"); + + obs1_info->stop_requested = false; + free(obs1_info->forbidden_segment); + obs1_info->forbidden_segment = strdup("seg60"); // skip 1 to give enough time for drive_to. + pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg62", -50, train1); + obs1_info->stop_requested = true; + pthread_join(route99_observer_thread, NULL); + testsuite_set_signal("signal34", "aspect_stop"); testsuite_set_signal("signal32", "aspect_stop"); + + obs1_info->stop_requested = false; + free(obs1_info->forbidden_segment); + obs1_info->forbidden_segment = strdup("seg59"); // for very last drive_to. + pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg60", -50, train1); testsuite_driveTo("seg53", -40, train1); testsuite_driveTo("seg58", -30, train1); sleep(2); testsuite_driveToStop("seg58", -20, train1); + + obs1_info->stop_requested = true; + pthread_join(route99_observer_thread, NULL); + sleep(2); + + free_obs_info_util(obs1_info); pthread_exit(NULL); } diff --git a/test/physical/test_common.c b/test/physical/test_common.c index 263425c..d336378 100644 --- a/test/physical/test_common.c +++ b/test/physical/test_common.c @@ -119,16 +119,16 @@ void testsuite_stopBidib(void) { } void testsuite_signal_callback_handler(int signum) { - printf("testsuite: SIGINT - before stopping, debug logs:\n"); + printf("testsuite: SIG %d - before stopping, debug logs:\n", signum); printf(" Track output states:\n"); testsuite_logAllTrackOutputStates(); printf("\n"); printf(" Booster power states:\n"); testsuite_logAllBoosterPowerStates(); printf("\n"); - printf("testsuite: SIGINT - now stopping libbidib.\n"); + printf("testsuite: SIG %d - now stopping libbidib.\n", signum); testsuite_stopBidib(); - printf("testsuite: SIGINT - libbidib stopped.\n"); + printf("testsuite: SIG %d - libbidib stopped.\n", signum); exit(signum); } @@ -201,7 +201,7 @@ void testsuite_driveTo_legacy(const char *segment, int speed, const char *train) bidib_set_train_speed(train, speed, "master"); bidib_flush(); long counter = 0; - while (1) { + while (bidib_is_running()) { t_bidib_train_position_query trainPosition = bidib_get_train_position(train); for (size_t i = 0; i < trainPosition.length; i++) { if (strcmp(segment, trainPosition.segments[i]) == 0) { @@ -236,7 +236,7 @@ void testsuite_driveTo(const char *segment, int speed, const char *train) { t_bidib_dcc_address_query tr_dcc_addr = bidib_get_train_dcc_addr(train); t_bidib_dcc_address dcc_address; long counter = 0; - while (1) { + while (bidib_is_running()) { t_bidib_segment_state_query seg_query = bidib_get_segment_state(segment); for (size_t j = 0; j < seg_query.data.dcc_address_cnt; j++) { dcc_address = seg_query.data.dcc_addresses[j]; @@ -269,6 +269,35 @@ void testsuite_driveToStop(const char *segment, int speed, const char *train) { bidib_flush(); } +bool testsuite_is_segment_occupied(const char *segment) { + t_bidib_segment_state_query seg_query = bidib_get_segment_state(segment); + bool ret = seg_query.known && seg_query.data.occupied; + bidib_free_segment_state_query(seg_query); + return ret; +} + +bool testsuite_is_segment_occupied_by_train(const char *segment, const char *train) { + t_bidib_dcc_address_query tr_dcc_addr = bidib_get_train_dcc_addr(train); + return testsuite_is_segment_occupied_by_dcc_addr(segment, tr_dcc_addr.dcc_address); +} + +bool testsuite_is_segment_occupied_by_dcc_addr(const char *segment, t_bidib_dcc_address dcc_address) { + t_bidib_segment_state_query seg_query = bidib_get_segment_state(segment); + if (!(seg_query.known && seg_query.data.occupied)) { + bidib_free_segment_state_query(seg_query); + return false; + } + for (size_t j = 0; j < seg_query.data.dcc_address_cnt; j++) { + t_bidib_dcc_address *seg_dcc_j = &seg_query.data.dcc_addresses[j]; + if (dcc_address.addrh == seg_dcc_j->addrh && dcc_address.addrl == seg_dcc_j->addrl) { + bidib_free_segment_state_query(seg_query); + return true; + } + } + bidib_free_segment_state_query(seg_query); + return false; +} + void testsuite_set_signal(const char *signal, const char *aspect) { bidib_set_signal(signal, aspect); bidib_flush(); diff --git a/test/physical/test_common.h b/test/physical/test_common.h index 2445159..63d73f0 100644 --- a/test/physical/test_common.h +++ b/test/physical/test_common.h @@ -75,6 +75,9 @@ void testsuite_logAllBoosterPowerStates(); bool testsuite_trainReady(const char *train, const char *segment); void testsuite_driveTo(const char *segment, int speed, const char *train); void testsuite_driveToStop(const char *segment, int speed, const char *train); +bool testsuite_is_segment_occupied(const char *segment); +bool testsuite_is_segment_occupied_by_train(const char *segment, const char *train); +bool testsuite_is_segment_occupied_by_dcc_addr(const char *segment, t_bidib_dcc_address dcc_address); // Accessories void testsuite_set_signal(const char *signal, const char *aspect); From 6351b60640fb0bd84497bb6855212dd519482760 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Thu, 5 Dec 2024 11:37:44 +0100 Subject: [PATCH 13/23] prototype for checking if bidib is still running during test exec --- test/physical/swtbahn-full/testsuite.c | 41 +++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index 6e6965d..5d8a9ea 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -578,11 +578,15 @@ static void *route99(void *arg) { obs1_info->stop_requested = true; pthread_join(route99_observer_thread, NULL); + if (!bidib_is_running()) { + printf("testsuite: route99 - stop, bidib is not running anymore"); + free_obs_info_util(obs1_info); + pthread_exit(NULL); + } testsuite_set_signal("signal30", "aspect_stop"); - obs1_info->stop_requested = false; free(obs1_info->forbidden_segment); obs1_info->forbidden_segment = strdup("seg66"); // skip 1 to give enough time for drive_to. @@ -592,6 +596,11 @@ static void *route99(void *arg) { obs1_info->stop_requested = true; pthread_join(route99_observer_thread, NULL); + if (!bidib_is_running()) { + printf("testsuite: route99 - stop, bidib is not running anymore"); + free_obs_info_util(obs1_info); + pthread_exit(NULL); + } testsuite_set_signal("signal33", "aspect_stop"); testsuite_set_signal("signal35a", "aspect_stop"); @@ -607,6 +616,11 @@ static void *route99(void *arg) { obs1_info->stop_requested = true; pthread_join(route99_observer_thread, NULL); + if (!bidib_is_running()) { + printf("testsuite: route99 - stop, bidib is not running anymore"); + free_obs_info_util(obs1_info); + pthread_exit(NULL); + } testsuite_set_signal("signal37", "aspect_stop"); @@ -620,11 +634,21 @@ static void *route99(void *arg) { obs1_info->stop_requested = true; pthread_join(route99_observer_thread, NULL); + if (!bidib_is_running()) { + printf("testsuite: route99 - stop, bidib is not running anymore"); + free_obs_info_util(obs1_info); + pthread_exit(NULL); + } sleep(1); testsuite_driveToStop("seg47", 20, train1); sleep(4); + if (!bidib_is_running()) { + printf("testsuite: route99 - stop, bidib is not running anymore"); + free_obs_info_util(obs1_info); + pthread_exit(NULL); + } // train1: backwards testsuite_set_signal("signal26", "aspect_go"); @@ -644,6 +668,11 @@ static void *route99(void *arg) { obs1_info->stop_requested = true; pthread_join(route99_observer_thread, NULL); + if (!bidib_is_running()) { + printf("testsuite: route99 - stop, bidib is not running anymore"); + free_obs_info_util(obs1_info); + pthread_exit(NULL); + } testsuite_set_signal("signal26", "aspect_stop"); @@ -657,6 +686,11 @@ static void *route99(void *arg) { obs1_info->stop_requested = true; pthread_join(route99_observer_thread, NULL); + if (!bidib_is_running()) { + printf("testsuite: route99 - stop, bidib is not running anymore"); + free_obs_info_util(obs1_info); + pthread_exit(NULL); + } testsuite_set_signal("signal38", "aspect_stop"); testsuite_set_signal("signal36", "aspect_stop"); @@ -670,6 +704,11 @@ static void *route99(void *arg) { testsuite_driveTo("seg62", -50, train1); obs1_info->stop_requested = true; pthread_join(route99_observer_thread, NULL); + if (!bidib_is_running()) { + printf("testsuite: route99 - stop, bidib is not running anymore"); + free_obs_info_util(obs1_info); + pthread_exit(NULL); + } testsuite_set_signal("signal34", "aspect_stop"); testsuite_set_signal("signal32", "aspect_stop"); From 5686a72054c6e0e423b940b4f05b892b1f96f9eb Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Fri, 6 Dec 2024 14:33:32 +0100 Subject: [PATCH 14/23] helper function for setting and checking points, and for setting signals --- test/physical/swtbahn-full/testsuite.c | 663 ++++++++----------------- test/physical/test_common.c | 35 ++ test/physical/test_common.h | 3 + 3 files changed, 239 insertions(+), 462 deletions(-) diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index 5d8a9ea..0d150c2 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -58,18 +58,6 @@ void testsuite_case_pointSerial(t_testsuite_test_result *result) { testsuite_case_pointSerial_common(result); } -/* -typedef struct { - char *train; - char **forbidden_segments; - int forbidden_segments_len; - // if true, only checks whether any of the forbidden segments gets occupied, - // not if it gets occupied *by the train*. - bool check_occ_only; - // To be set by the caller to request the observer to terminate. - volatile bool stop_requested; -} t_bidib_occ_observer_info_multi; -*/ typedef struct { char *train; char *forbidden_segment; @@ -80,7 +68,7 @@ typedef struct { volatile bool stop_requested; } t_bidib_occ_observer_info; -void free_obs_info_util(t_bidib_occ_observer_info *obs_info_ptr) { +static void free_obs_info_util(t_bidib_occ_observer_info *obs_info_ptr) { if (obs_info_ptr != NULL) { if (obs_info_ptr->forbidden_segment != NULL) { free(obs_info_ptr->forbidden_segment); @@ -130,58 +118,54 @@ static void *occupancy_observer(void *arg) { pthread_exit(NULL); } -bool route1(const char *train) { - if (!testsuite_trainReady(train, "seg58")) { +static void prep_observer_segment_info(t_bidib_occ_observer_info *obs_info, const char *segment) { + obs_info->stop_requested = false; + if (obs_info->forbidden_segment != NULL) { + free(obs_info->forbidden_segment); + } + obs_info->forbidden_segment = strdup(segment); +} + +static bool stop_observer_and_check_still_running(t_bidib_occ_observer_info *obs_info, + pthread_t observer_thread, + const char *callerlogname) { + obs_info->stop_requested = true; + pthread_join(observer_thread, NULL); + if (!bidib_is_running()) { + printf("testsuite: %s - stop, bidib is not running anymore", callerlogname); + free_obs_info_util(obs_info); return false; } + return true; +} - testsuite_switch_point("point22", "reverse"); - testsuite_switch_point("point23", "normal"); - testsuite_switch_point("point24", "reverse"); - testsuite_switch_point("point12", "reverse"); - testsuite_switch_point("point13", "reverse"); - testsuite_switch_point("point14", "reverse"); - testsuite_switch_point("point15", "normal"); - testsuite_switch_point("point16", "reverse"); - testsuite_switch_point("point21", "reverse"); - testsuite_switch_point("point20", "normal"); - testsuite_switch_point("point19", "normal"); - testsuite_switch_point("point18b", "reverse"); - - sleep(2); - // Check that points are in desired position - bool point_check = true; - point_check &= testsuite_check_point_aspect("point22", "reverse"); - point_check &= testsuite_check_point_aspect("point23", "normal"); - point_check &= testsuite_check_point_aspect("point24", "reverse"); - point_check &= testsuite_check_point_aspect("point12", "reverse"); - point_check &= testsuite_check_point_aspect("point13", "reverse"); - point_check &= testsuite_check_point_aspect("point14", "reverse"); - point_check &= testsuite_check_point_aspect("point15", "normal"); - point_check &= testsuite_check_point_aspect("point16", "reverse"); - point_check &= testsuite_check_point_aspect("point21", "reverse"); - point_check &= testsuite_check_point_aspect("point20", "normal"); - point_check &= testsuite_check_point_aspect("point19", "normal"); - point_check &= testsuite_check_point_aspect("point18b", "reverse"); - if (!point_check) { +static bool route1(const char *train) { + if (train == NULL || !testsuite_trainReady(train, "seg58")) { + return false; + } + + const char *points_normal[4] = { + "point15", "point23", "point20", "point19" + }; + const char *points_reverse[8] = { + "point22", "point24", "point12", "point13", "point14", "point16", "point21", "point18b" + }; + + if (!testsuite_set_and_check_points(points_normal, 4, points_reverse, 8)) { printf("testsuite: route1 - one or more points are not in expected aspect."); return false; } - - testsuite_set_signal("signal30", "aspect_go"); - testsuite_set_signal("signal33", "aspect_go"); - testsuite_set_signal("signal35a", "aspect_go"); - testsuite_set_signal("signal35b", "aspect_go"); - testsuite_set_signal("signal37", "aspect_go"); + const char* signals_go_1[5] = {"signal30", "signal33", "signal35a", "signal35b", "signal37"}; + testsuite_set_signals_to(signals_go_1, 5, "aspect_go"); testsuite_driveTo("seg57", 50, train); testsuite_set_signal("signal30", "aspect_stop"); testsuite_driveTo("seg64", 50, train); - testsuite_set_signal("signal33", "aspect_stop"); - testsuite_set_signal("signal35a", "aspect_stop"); - testsuite_set_signal("signal35b", "aspect_stop"); + + const char* signals_stop_1[3] = {"signal33", "signal35a", "signal35b"}; + testsuite_set_signals_to(signals_stop_1, 3, "aspect_stop"); testsuite_driveTo("seg69", 50, train); testsuite_set_signal("signal37", "aspect_stop"); @@ -190,11 +174,8 @@ bool route1(const char *train) { testsuite_driveToStop("seg47", 20, train); // Drive backwards through the route - testsuite_set_signal("signal26", "aspect_go"); - testsuite_set_signal("signal38", "aspect_go"); - testsuite_set_signal("signal36", "aspect_go"); - testsuite_set_signal("signal34", "aspect_go"); - testsuite_set_signal("signal32", "aspect_go"); + const char* signals_go_2[5] = {"signal26", "signal38", "signal36", "signal34", "signal32"}; + testsuite_set_signals_to(signals_go_2, 5, "aspect_go"); testsuite_driveTo("seg45", -50, train); testsuite_set_signal("signal26", "aspect_stop"); @@ -212,113 +193,45 @@ bool route1(const char *train) { return true; } -bool route2(const char *train) { - if (!testsuite_trainReady(train, "seg58")) { +static bool route2(const char *train) { + if (train == NULL || !testsuite_trainReady(train, "seg58")) { return false; } - testsuite_switch_point("point22", "normal"); - testsuite_switch_point("point20", "reverse"); - testsuite_switch_point("point21", "reverse"); - testsuite_switch_point("point16", "reverse"); - testsuite_switch_point("point15", "reverse"); - testsuite_switch_point("point5", "reverse"); - testsuite_switch_point("point4", "reverse"); - testsuite_switch_point("point12", "reverse"); - testsuite_switch_point("point11", "reverse"); - testsuite_switch_point("point27", "reverse"); - testsuite_switch_point("point29", "reverse"); - testsuite_switch_point("point28", "reverse"); - testsuite_switch_point("point26", "normal"); - testsuite_switch_point("point9", "reverse"); - testsuite_switch_point("point8", "reverse"); - testsuite_switch_point("point1", "reverse"); - testsuite_switch_point("point7", "normal"); - testsuite_switch_point("point6", "reverse"); - testsuite_switch_point("point17", "reverse"); - - sleep(2); - // Check that points are in desired position - bool point_check = true; - point_check &= testsuite_check_point_aspect("point22", "normal"); - point_check &= testsuite_check_point_aspect("point20", "reverse"); - point_check &= testsuite_check_point_aspect("point21", "reverse"); - point_check &= testsuite_check_point_aspect("point16", "reverse"); - point_check &= testsuite_check_point_aspect("point15", "reverse"); - point_check &= testsuite_check_point_aspect("point5", "reverse"); - point_check &= testsuite_check_point_aspect("point4", "reverse"); - point_check &= testsuite_check_point_aspect("point12", "reverse"); - point_check &= testsuite_check_point_aspect("point11", "reverse"); - point_check &= testsuite_check_point_aspect("point27", "reverse"); - point_check &= testsuite_check_point_aspect("point29", "reverse"); - point_check &= testsuite_check_point_aspect("point28", "reverse"); - point_check &= testsuite_check_point_aspect("point26", "normal"); - point_check &= testsuite_check_point_aspect("point9", "reverse"); - point_check &= testsuite_check_point_aspect("point8", "reverse"); - point_check &= testsuite_check_point_aspect("point1", "reverse"); - point_check &= testsuite_check_point_aspect("point7", "normal"); - point_check &= testsuite_check_point_aspect("point6", "reverse"); - point_check &= testsuite_check_point_aspect("point17", "reverse"); - if (!point_check) { + const char *points_normal_c1[3] = { + "point22", "point26", "point7" + }; + const char *points_reverse_c1[16] = { + "point20", "point21", "point16", "point15", "point5", "point4", "point12", "point11", + "point27", "point29", "point28", "point9", "point8", "point1", "point6", "point17", + }; + + if (!testsuite_set_and_check_points(points_normal_c1, 3, points_reverse_c1, 16)) { printf("testsuite: route2 - one or more points are not in expected aspect (1st check)."); return false; } testsuite_driveToStop("seg42b", 50, train); - - testsuite_switch_point("point16", "normal"); - testsuite_switch_point("point15", "normal"); - testsuite_switch_point("point14", "reverse"); - testsuite_switch_point("point13", "reverse"); - testsuite_switch_point("point12", "reverse"); - testsuite_switch_point("point24", "reverse"); - testsuite_switch_point("point23", "reverse"); - testsuite_switch_point("point19", "reverse"); - testsuite_switch_point("point18b", "normal"); - testsuite_switch_point("point18a", "reverse"); - testsuite_switch_point("point8", "normal"); - testsuite_switch_point("point9", "reverse"); - testsuite_switch_point("point26", "reverse"); - testsuite_switch_point("point27", "normal"); - testsuite_switch_point("point11", "normal"); - testsuite_switch_point("point3", "reverse"); - testsuite_switch_point("point4", "normal"); - testsuite_switch_point("point5", "normal"); - - sleep(2); - // Check that points are in desired position - point_check &= testsuite_check_point_aspect("point16", "normal"); - point_check &= testsuite_check_point_aspect("point15", "normal"); - point_check &= testsuite_check_point_aspect("point14", "reverse"); - point_check &= testsuite_check_point_aspect("point13", "reverse"); - point_check &= testsuite_check_point_aspect("point12", "reverse"); - point_check &= testsuite_check_point_aspect("point24", "reverse"); - point_check &= testsuite_check_point_aspect("point23", "reverse"); - point_check &= testsuite_check_point_aspect("point19", "reverse"); - point_check &= testsuite_check_point_aspect("point18b", "normal"); - point_check &= testsuite_check_point_aspect("point18a", "reverse"); - point_check &= testsuite_check_point_aspect("point8", "normal"); - point_check &= testsuite_check_point_aspect("point9", "reverse"); - point_check &= testsuite_check_point_aspect("point26", "reverse"); - point_check &= testsuite_check_point_aspect("point27", "normal"); - point_check &= testsuite_check_point_aspect("point11", "normal"); - point_check &= testsuite_check_point_aspect("point3", "reverse"); - point_check &= testsuite_check_point_aspect("point4", "normal"); - point_check &= testsuite_check_point_aspect("point5", "normal"); - if (!point_check) { + + const char *points_normal_c2[8] = { + "point16", "point15", "point8", "point18b", "point27", "point11", "point4", "point5" + }; + const char *points_reverse_c2[10] = { + "point14", "point13", "point12", "point24", "point23", + "point19", "point18a", "point9", "point26", "point3" + }; + + if (!testsuite_set_and_check_points(points_normal_c2, 8, points_reverse_c2, 10)) { printf("testsuite: route2 - one or more points are not in expected aspect (2nd check)."); return false; } testsuite_driveToStop("seg69", 50, train); - - testsuite_switch_point("point6", "normal"); - testsuite_switch_point("point7", "reverse"); - sleep(2); - // Check that points are in desired position - point_check &= testsuite_check_point_aspect("point6", "normal"); - point_check &= testsuite_check_point_aspect("point7", "reverse"); - if (!point_check) { + + const char *points_normal_c3[1] = { "point6" }; + const char *points_reverse_c3[1] = { "point7" }; + + if (!testsuite_set_and_check_points(points_normal_c3, 1, points_reverse_c3, 1)) { printf("testsuite: route2 - one or more points are not in expected aspect (3rd check)."); return false; } @@ -328,48 +241,20 @@ bool route2(const char *train) { return true; } -bool route3(const char *train) { - if (!testsuite_trainReady(train, "seg46")) { +static bool route3(const char *train) { + if (train == NULL || !testsuite_trainReady(train, "seg46")) { return false; } - testsuite_switch_point("point18b", "reverse"); - testsuite_switch_point("point19", "reverse"); - testsuite_switch_point("point23", "reverse"); - testsuite_switch_point("point24", "reverse"); - testsuite_switch_point("point12", "normal"); - testsuite_switch_point("point4", "reverse"); - testsuite_switch_point("point5", "reverse"); - testsuite_switch_point("point15", "reverse"); - testsuite_switch_point("point16", "normal"); - testsuite_switch_point("point17", "reverse"); - testsuite_switch_point("point6", "reverse"); - testsuite_switch_point("point7", "normal"); - testsuite_switch_point("point1", "reverse"); - testsuite_switch_point("point8", "reverse"); - testsuite_switch_point("point9", "normal"); - testsuite_switch_point("point10", "reverse"); - - sleep(2); - // Check that points are in desired position - bool point_check = true; - point_check &= testsuite_check_point_aspect("point18b", "reverse"); - point_check &= testsuite_check_point_aspect("point19", "reverse"); - point_check &= testsuite_check_point_aspect("point23", "reverse"); - point_check &= testsuite_check_point_aspect("point24", "reverse"); - point_check &= testsuite_check_point_aspect("point12", "normal"); - point_check &= testsuite_check_point_aspect("point4", "reverse"); - point_check &= testsuite_check_point_aspect("point5", "reverse"); - point_check &= testsuite_check_point_aspect("point15", "reverse"); - point_check &= testsuite_check_point_aspect("point16", "normal"); - point_check &= testsuite_check_point_aspect("point17", "reverse"); - point_check &= testsuite_check_point_aspect("point6", "reverse"); - point_check &= testsuite_check_point_aspect("point7", "normal"); - point_check &= testsuite_check_point_aspect("point1", "reverse"); - point_check &= testsuite_check_point_aspect("point8", "reverse"); - point_check &= testsuite_check_point_aspect("point9", "normal"); - point_check &= testsuite_check_point_aspect("point10", "reverse"); - if (!point_check) { + const char *points_normal[4] = { + "point7", "point12", "point16", "point9" + }; + const char *points_reverse[12] = { + "point18b", "point19", "point23", "point24", "point4", "point5", + "point15", "point17", "point6", "point1", "point8", "point10", + }; + + if (!testsuite_set_and_check_points(points_normal, 4, points_reverse, 12)) { printf("testsuite: route3 - one or more points are not in expected aspect."); return false; } @@ -380,46 +265,20 @@ bool route3(const char *train) { return true; } -bool route4(const char *train) { - if (!testsuite_trainReady(train, "seg78a")) { +static bool route4(const char *train) { + if (train == NULL || !testsuite_trainReady(train, "seg78a")) { return false; } - testsuite_switch_point("point10", "reverse"); - testsuite_switch_point("point9", "normal"); - testsuite_switch_point("point8", "reverse"); - testsuite_switch_point("point1", "reverse"); - testsuite_switch_point("point7", "normal"); - testsuite_switch_point("point6", "reverse"); - testsuite_switch_point("point17", "reverse"); - testsuite_switch_point("point16", "normal"); - testsuite_switch_point("point15", "normal"); - testsuite_switch_point("point14", "reverse"); - testsuite_switch_point("point13", "reverse"); - testsuite_switch_point("point12", "reverse"); - testsuite_switch_point("point24", "reverse"); - testsuite_switch_point("point23", "normal"); - testsuite_switch_point("point22", "reverse"); - - sleep(2); - // Check that points are in desired position - bool point_check = true; - point_check &= testsuite_check_point_aspect("point10", "reverse"); - point_check &= testsuite_check_point_aspect("point9", "normal"); - point_check &= testsuite_check_point_aspect("point8", "reverse"); - point_check &= testsuite_check_point_aspect("point1", "reverse"); - point_check &= testsuite_check_point_aspect("point7", "normal"); - point_check &= testsuite_check_point_aspect("point6", "reverse"); - point_check &= testsuite_check_point_aspect("point17", "reverse"); - point_check &= testsuite_check_point_aspect("point16", "normal"); - point_check &= testsuite_check_point_aspect("point15", "normal"); - point_check &= testsuite_check_point_aspect("point14", "reverse"); - point_check &= testsuite_check_point_aspect("point13", "reverse"); - point_check &= testsuite_check_point_aspect("point12", "reverse"); - point_check &= testsuite_check_point_aspect("point24", "reverse"); - point_check &= testsuite_check_point_aspect("point23", "normal"); - point_check &= testsuite_check_point_aspect("point22", "reverse"); - if (!point_check) { + const char *points_normal[5] = { + "point9", "point7", "point16", "point15", "point23" + }; + const char *points_reverse[10] = { + "point10", "point8", "point1", "point6", "point17", + "point14", "point13", "point12", "point24", "point22" + }; + + if (!testsuite_set_and_check_points(points_normal, 5, points_reverse, 10)) { printf("testsuite: route4 - one or more points are not in expected aspect."); return false; } @@ -430,43 +289,26 @@ bool route4(const char *train) { return true; } -bool route5(const char *train) { - if (!testsuite_trainReady(train, "seg58")) { +static bool route5(const char *train) { + if (train == NULL || !testsuite_trainReady(train, "seg58")) { return false; } - - testsuite_switch_point("point22", "reverse"); - testsuite_switch_point("point23", "normal"); - testsuite_switch_point("point24", "reverse"); - testsuite_switch_point("point12", "reverse"); - testsuite_switch_point("point13", "reverse"); - testsuite_switch_point("point14", "reverse"); - testsuite_switch_point("point15", "normal"); - testsuite_switch_point("point16", "reverse"); - testsuite_switch_point("point21", "reverse"); - testsuite_switch_point("point20", "reverse"); - - sleep(2); - // Check that points are in desired position - bool point_check = true; - point_check &= testsuite_check_point_aspect("point22", "reverse"); - point_check &= testsuite_check_point_aspect("point23", "normal"); - point_check &= testsuite_check_point_aspect("point24", "reverse"); - point_check &= testsuite_check_point_aspect("point12", "reverse"); - point_check &= testsuite_check_point_aspect("point13", "reverse"); - point_check &= testsuite_check_point_aspect("point14", "reverse"); - point_check &= testsuite_check_point_aspect("point15", "normal"); - point_check &= testsuite_check_point_aspect("point16", "reverse"); - point_check &= testsuite_check_point_aspect("point21", "reverse"); - point_check &= testsuite_check_point_aspect("point20", "reverse"); - if (!point_check) { + + const char *points_normal_c1[2] = { + "point23", "point15" + }; + const char *points_reverse_c1[8] = { + "point22", "point24", "point12", "point13", "point14", "point16", "point21", "point20" + }; + + if (!testsuite_set_and_check_points(points_normal_c1, 2, points_reverse_c1, 8)) { printf("testsuite: route5 - one or more points are not in expected aspect (1st check)."); return false; } testsuite_driveToStop("seg64", -50, train); testsuite_switch_point("point22", "normal"); - sleep(2); + sleep(3); // Check that point is in desired position if (!testsuite_check_point_aspect("point21", "reverse")) { printf("testsuite: route5 - point 21 is not in expected aspect (2nd check)."); @@ -480,163 +322,110 @@ bool route5(const char *train) { } void testsuite_case_swtbahnFullTrackCoverage(const char *train) { + if (train == NULL) { + printf("testsuite: swtbahn-full track coverage single train - train is NULL"); + return; + } + if (!route1(train)) { + printf("testsuite: swtbahn-full track coverage single train - route1 failed."); return; } if (!route2(train)) { + printf("testsuite: swtbahn-full track coverage single train - route2 failed."); return; } if (!route3(train)) { + printf("testsuite: swtbahn-full track coverage single train - route3 failed."); return; } if (!route4(train)) { + printf("testsuite: swtbahn-full track coverage single train - route4 failed."); return; } if (!route5(train)) { + printf("testsuite: swtbahn-full track coverage single train - route5 failed."); return; } } -/* -typedef struct { - char *train; - char *forbidden_segment; - // if true, only checks whether any of the forbidden segments gets occupied, - // not if it gets occupied *by the train*. - bool check_occ_only; - // To be set by the caller to request the observer to terminate. - volatile bool stop_requested; -} t_bidib_occ_observer_info; -*/ - static void *route99(void *arg) { const char *train1 = arg; - if (!testsuite_trainReady(train1, "seg58")) { + if (train1 == NULL || !testsuite_trainReady(train1, "seg58")) { pthread_exit(NULL); } - - // train1: forwards - testsuite_switch_point("point22", "reverse"); - testsuite_switch_point("point23", "normal"); - testsuite_switch_point("point24", "reverse"); - testsuite_switch_point("point12", "reverse"); - testsuite_switch_point("point13", "reverse"); - testsuite_switch_point("point14", "reverse"); - testsuite_switch_point("point15", "normal"); - testsuite_switch_point("point16", "reverse"); - testsuite_switch_point("point21", "reverse"); - testsuite_switch_point("point20", "normal"); - testsuite_switch_point("point19", "normal"); - testsuite_switch_point("point18b", "reverse"); - sleep(1); - - testsuite_set_signal("signal30", "aspect_go"); - testsuite_set_signal("signal33", "aspect_go"); - testsuite_set_signal("signal35a", "aspect_go"); - testsuite_set_signal("signal35b", "aspect_go"); - testsuite_set_signal("signal37", "aspect_go"); + // train1: forwards - sleep(1); + const char *points_normal[4] = { + "point23", "point15", "point20", "point19" + }; + const char *points_reverse[8] = { + "point22", "point24", "point12", "point13", "point14", "point16", "point21", "point18b" + }; - // Check that points are in desired position - bool point_check = true; - point_check &= testsuite_check_point_aspect("point22", "reverse"); - point_check &= testsuite_check_point_aspect("point23", "normal"); - point_check &= testsuite_check_point_aspect("point24", "reverse"); - point_check &= testsuite_check_point_aspect("point12", "reverse"); - point_check &= testsuite_check_point_aspect("point13", "reverse"); - point_check &= testsuite_check_point_aspect("point14", "reverse"); - point_check &= testsuite_check_point_aspect("point15", "normal"); - point_check &= testsuite_check_point_aspect("point16", "reverse"); - point_check &= testsuite_check_point_aspect("point21", "reverse"); - point_check &= testsuite_check_point_aspect("point20", "normal"); - point_check &= testsuite_check_point_aspect("point19", "normal"); - point_check &= testsuite_check_point_aspect("point18b", "reverse"); - if (!point_check) { + if (!testsuite_set_and_check_points(points_normal, 4, points_reverse, 8)) { printf("testsuite: route99 - one or more points are not in expected aspect."); pthread_exit(NULL); } + + const char* signals_go_1[5] = {"signal30", "signal33", "signal35a", "signal35b", "signal37"}; + testsuite_set_signals_to(signals_go_1, 5, "aspect_go"); + + sleep(1); - static pthread_t route99_observer_thread; + static pthread_t route_observer_thread; t_bidib_occ_observer_info *obs1_info = malloc(sizeof(t_bidib_occ_observer_info)); obs1_info->check_occ_only = false; obs1_info->train = strdup(train1); obs1_info->stop_requested = false; - obs1_info->forbidden_segment = strdup("seg60"); // skip 1 to give enough time for drive_to. - + // skip 1 to give enough time for drive_to. + obs1_info->forbidden_segment = strdup("seg60"); - pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg57", 50, train1); - - obs1_info->stop_requested = true; - pthread_join(route99_observer_thread, NULL); - if (!bidib_is_running()) { - printf("testsuite: route99 - stop, bidib is not running anymore"); - free_obs_info_util(obs1_info); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { pthread_exit(NULL); } - testsuite_set_signal("signal30", "aspect_stop"); - obs1_info->stop_requested = false; - free(obs1_info->forbidden_segment); - obs1_info->forbidden_segment = strdup("seg66"); // skip 1 to give enough time for drive_to. - pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + // skip 1 segment to give enough time for drive_to. + prep_observer_segment_info(obs1_info, "seg66"); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg64", 50, train1); - - obs1_info->stop_requested = true; - pthread_join(route99_observer_thread, NULL); - if (!bidib_is_running()) { - printf("testsuite: route99 - stop, bidib is not running anymore"); - free_obs_info_util(obs1_info); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { pthread_exit(NULL); } - - testsuite_set_signal("signal33", "aspect_stop"); - testsuite_set_signal("signal35a", "aspect_stop"); - testsuite_set_signal("signal35b", "aspect_stop"); + const char* signals_stop_1[3] = {"signal33", "signal35a", "signal35b"}; + testsuite_set_signals_to(signals_stop_1, 3, "aspect_stop"); - obs1_info->stop_requested = false; - free(obs1_info->forbidden_segment); - obs1_info->forbidden_segment = strdup("seg40"); // skip 1 to give enough time for drive_to. - pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + + // skip 1 segment to give enough time for drive_to. + prep_observer_segment_info(obs1_info, "seg40"); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg69", 50, train1); - - obs1_info->stop_requested = true; - pthread_join(route99_observer_thread, NULL); - if (!bidib_is_running()) { - printf("testsuite: route99 - stop, bidib is not running anymore"); - free_obs_info_util(obs1_info); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { pthread_exit(NULL); } - testsuite_set_signal("signal37", "aspect_stop"); - obs1_info->stop_requested = false; - free(obs1_info->forbidden_segment); - obs1_info->forbidden_segment = strdup("seg47"); - pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + prep_observer_segment_info(obs1_info, "seg47"); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg46", 50, train1); - - obs1_info->stop_requested = true; - pthread_join(route99_observer_thread, NULL); - if (!bidib_is_running()) { - printf("testsuite: route99 - stop, bidib is not running anymore"); - free_obs_info_util(obs1_info); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { pthread_exit(NULL); } @@ -651,73 +440,49 @@ static void *route99(void *arg) { } // train1: backwards - testsuite_set_signal("signal26", "aspect_go"); - testsuite_set_signal("signal38", "aspect_go"); - testsuite_set_signal("signal36", "aspect_go"); - testsuite_set_signal("signal34", "aspect_go"); - testsuite_set_signal("signal32", "aspect_go"); + + const char* signals_go_2[5] = {"signal26", "signal38", "signal36", "signal34", "signal32"}; + testsuite_set_signals_to(signals_go_2, 5, "aspect_go"); sleep(1); - - obs1_info->stop_requested = false; - free(obs1_info->forbidden_segment); - obs1_info->forbidden_segment = strdup("seg48"); // skip 1 to give enough time for drive_to. - pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + + // skip 1 segment to give enough time for drive_to. + prep_observer_segment_info(obs1_info, "seg48"); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg45", -50, train1); - - obs1_info->stop_requested = true; - pthread_join(route99_observer_thread, NULL); - if (!bidib_is_running()) { - printf("testsuite: route99 - stop, bidib is not running anymore"); - free_obs_info_util(obs1_info); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { pthread_exit(NULL); } - testsuite_set_signal("signal26", "aspect_stop"); - obs1_info->stop_requested = false; - free(obs1_info->forbidden_segment); - obs1_info->forbidden_segment = strdup("seg34"); // skip 1 to give enough time for drive_to. - pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + // skip 1 segment to give enough time for drive_to. + prep_observer_segment_info(obs1_info, "seg34"); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg67", -50, train1); - - obs1_info->stop_requested = true; - pthread_join(route99_observer_thread, NULL); - if (!bidib_is_running()) { - printf("testsuite: route99 - stop, bidib is not running anymore"); - free_obs_info_util(obs1_info); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { pthread_exit(NULL); } - testsuite_set_signal("signal38", "aspect_stop"); testsuite_set_signal("signal36", "aspect_stop"); - obs1_info->stop_requested = false; - free(obs1_info->forbidden_segment); - obs1_info->forbidden_segment = strdup("seg60"); // skip 1 to give enough time for drive_to. - pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + // skip 1 segment to give enough time for drive_to. + prep_observer_segment_info(obs1_info, "seg60"); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg62", -50, train1); - obs1_info->stop_requested = true; - pthread_join(route99_observer_thread, NULL); - if (!bidib_is_running()) { - printf("testsuite: route99 - stop, bidib is not running anymore"); - free_obs_info_util(obs1_info); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { pthread_exit(NULL); } - testsuite_set_signal("signal34", "aspect_stop"); testsuite_set_signal("signal32", "aspect_stop"); - obs1_info->stop_requested = false; - free(obs1_info->forbidden_segment); - obs1_info->forbidden_segment = strdup("seg59"); // for very last drive_to. - pthread_create(&route99_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + prep_observer_segment_info(obs1_info, "seg59"); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg60", -50, train1); testsuite_driveTo("seg53", -40, train1); @@ -726,62 +491,53 @@ static void *route99(void *arg) { testsuite_driveToStop("seg58", -20, train1); obs1_info->stop_requested = true; - pthread_join(route99_observer_thread, NULL); - - sleep(2); - + pthread_join(route_observer_thread, NULL); free_obs_info_util(obs1_info); + + sleep(1); pthread_exit(NULL); } static void *route100(void *arg) { const char *train2 = arg; - if (!testsuite_trainReady(train2, "seg78a")) { + if (train2 == NULL || !testsuite_trainReady(train2, "seg78a")) { pthread_exit(NULL); } // train2: forwards - testsuite_switch_point("point10", "reverse"); - testsuite_switch_point("point9", "normal"); - testsuite_switch_point("point8", "reverse"); - testsuite_switch_point("point1", "reverse"); - testsuite_switch_point("point7", "normal"); - testsuite_switch_point("point6", "normal"); - testsuite_switch_point("point5", "normal"); - testsuite_switch_point("point4", "normal"); - testsuite_switch_point("point3", "reverse"); - testsuite_switch_point("point11", "reverse"); - - sleep(1); + const char *points_normal[5] = { + "point9", "point7", "point6", "point5", "point4" + }; + const char *points_reverse[5] = { + "point10", "point8", "point1", "point3", "point11" + }; + + if (!testsuite_set_and_check_points(points_normal, 5, points_reverse, 5)) { + printf("testsuite: route100 - one or more points are not in expected aspect."); + pthread_exit(NULL); + } + + const char* signals_go_1[7] = { + "signal19", "signal3", "signal1", "signal13", "signal11", "signal10", "signal8" + }; + testsuite_set_signals_to(signals_go_1, 7, "aspect_go"); testsuite_set_signal("signal43", "aspect_shunt"); - testsuite_set_signal("signal19", "aspect_go"); - testsuite_set_signal("signal3", "aspect_go"); - testsuite_set_signal("signal1", "aspect_go"); - testsuite_set_signal("signal13", "aspect_go"); - testsuite_set_signal("signal11", "aspect_go"); - testsuite_set_signal("signal10", "aspect_go"); - testsuite_set_signal("signal8", "aspect_go"); sleep(1); - // Check that points are in desired position - bool point_check = true; - point_check &= testsuite_check_point_aspect("point10", "reverse"); - point_check &= testsuite_check_point_aspect("point9", "normal"); - point_check &= testsuite_check_point_aspect("point8", "reverse"); - point_check &= testsuite_check_point_aspect("point1", "reverse"); - point_check &= testsuite_check_point_aspect("point7", "normal"); - point_check &= testsuite_check_point_aspect("point6", "normal"); - point_check &= testsuite_check_point_aspect("point5", "normal"); - point_check &= testsuite_check_point_aspect("point4", "normal"); - point_check &= testsuite_check_point_aspect("point3", "reverse"); - point_check &= testsuite_check_point_aspect("point11", "reverse"); - if (!point_check) { - printf("testsuite: route100 - one or more points are not in expected aspect."); - pthread_exit(NULL); - } + + static pthread_t route_observer_thread; + + t_bidib_occ_observer_info *obs1_info = malloc(sizeof(t_bidib_occ_observer_info)); + obs1_info->check_occ_only = false; + obs1_info->train = strdup(train2); + obs1_info->stop_requested = false; + // skip 1 to give enough time for drive_to. + ///TODO: Continue here. + obs1_info->forbidden_segment = strdup("seg TODO "); + testsuite_driveTo("seg77", 60, train2); testsuite_set_signal("signal43", "aspect_stop"); @@ -811,14 +567,12 @@ static void *route100(void *arg) { sleep(3); // train2: backwards - testsuite_set_signal("signal22a", "aspect_go"); - testsuite_set_signal("signal22b", "aspect_go"); - testsuite_set_signal("signal9", "aspect_go"); - testsuite_set_signal("signal12", "aspect_go"); - testsuite_set_signal("signal14", "aspect_go"); - testsuite_set_signal("signal2", "aspect_go"); - testsuite_set_signal("signal4a", "aspect_go"); - testsuite_set_signal("signal4b", "aspect_go"); + + const char* signals_go_2[8] = { + "signal22a", "signal22b", "signal9", "signal12", + "signal14", "signal2", "signal4a", "signal4b" + }; + testsuite_set_signals_to(signals_go_2, 8, "aspect_go"); testsuite_set_signal("signal20", "aspect_shunt"); sleep(1); @@ -865,25 +619,10 @@ bool route_custom_short(const char *train) { return false; } - testsuite_switch_point("point2", "normal"); - testsuite_switch_point("point1", "normal"); - testsuite_switch_point("point7", "normal"); - testsuite_switch_point("point6", "normal"); - testsuite_switch_point("point5", "normal"); - testsuite_switch_point("point4", "normal"); - testsuite_switch_point("point3", "normal"); - - sleep(2); - // Check that points are in desired position - bool point_check = true; - point_check &= testsuite_check_point_aspect("point2", "normal"); - point_check &= testsuite_check_point_aspect("point1", "normal"); - point_check &= testsuite_check_point_aspect("point7", "normal"); - point_check &= testsuite_check_point_aspect("point6", "normal"); - point_check &= testsuite_check_point_aspect("point5", "normal"); - point_check &= testsuite_check_point_aspect("point4", "normal"); - point_check &= testsuite_check_point_aspect("point3", "normal"); - if (!point_check) { + const char *points_normal[7] = { + "point2", "point1", "point7", "point6", "point5", "point4", "point3" + }; + if (!testsuite_set_and_check_points(points_normal, 7, NULL, 0)) { printf("testsuite: route_custom_short - one or more points are not in expected aspect."); return false; } diff --git a/test/physical/test_common.c b/test/physical/test_common.c index d336378..468bccf 100644 --- a/test/physical/test_common.c +++ b/test/physical/test_common.c @@ -341,6 +341,41 @@ bool testsuite_check_point_aspect(const char *point, const char *aspect) { return false; } +bool testsuite_set_and_check_points(const char **points_normal, int points_normal_len, + const char **points_reverse, int points_reverse_len) { + if (points_normal_len > 0 && points_normal != NULL) { + for (int i = 0; i < points_normal_len; i++) { + testsuite_switch_point(points_normal[i], "normal"); + } + } + if (points_reverse_len > 0 && points_reverse != NULL) { + for (int i = 0; i < points_reverse_len; i++) { + testsuite_switch_point(points_reverse[i], "reverse"); + } + } + sleep(POINT_WAITING_TIME_S); + bool point_check = true; + if (points_normal_len > 0 && points_normal != NULL) { + for (int i = 0; i < points_normal_len; i++) { + point_check &= testsuite_check_point_aspect(points_normal[i], "normal"); + } + } + if (points_reverse_len > 0 && points_reverse != NULL) { + for (int i = 0; i < points_reverse_len; i++) { + point_check &= testsuite_check_point_aspect(points_reverse[i], "reverse"); + } + } + return point_check; +} + +void testsuite_set_signals_to(const char **signals, int signals_len, const char *aspect) { + if (signals_len > 0 && signals != NULL && aspect != NULL) { + for (int i = 0; i < signals_len; i++) { + testsuite_set_signal(signals[i], aspect); + } + } +} + void testsuite_case_signal_common(char **aspects, size_t aspects_len) { for (size_t i = 0; i < aspects_len; i++) { for (size_t n = 0; n < signals.length; n++) { diff --git a/test/physical/test_common.h b/test/physical/test_common.h index 63d73f0..9d8ab8e 100644 --- a/test/physical/test_common.h +++ b/test/physical/test_common.h @@ -84,6 +84,9 @@ void testsuite_set_signal(const char *signal, const char *aspect); void testsuite_switch_point(const char *point, const char *aspect); // Returns true if the point's aspect matches a certain value/aspect. Otherwise returns false. bool testsuite_check_point_aspect(const char *point, const char *aspect); +bool testsuite_set_and_check_points(const char **points_normal, int points_normal_len, + const char **points_reverse, int points_reverse_len); +void testsuite_set_signals_to(const char **signals, int signals_len, const char *aspect); // Common test base void testsuite_case_signal_common(char **aspects, size_t aspects_len); From 3bfc75f97b0f3f319e6b70c80e89fa417e4785ee Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Fri, 6 Dec 2024 14:59:16 +0100 Subject: [PATCH 15/23] more observer prototyping --- test/physical/swtbahn-full/testsuite.c | 125 ++++++++++++++++++++----- 1 file changed, 104 insertions(+), 21 deletions(-) diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index 0d150c2..68d83e5 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -381,11 +381,15 @@ static void *route99(void *arg) { static pthread_t route_observer_thread; + // Note: Most but not all segments the observer is configured to observe + // for this route are not the immediate successors of the segment in driveTo, + // but rather the successor of the successor -> to prevent the observer + // from falsely recognizing a violation due to the combination of sleep + // statements (observer sleeps 0.1s, driveTo 0.25s -> fast train could cause issues). t_bidib_occ_observer_info *obs1_info = malloc(sizeof(t_bidib_occ_observer_info)); obs1_info->check_occ_only = false; obs1_info->train = strdup(train1); obs1_info->stop_requested = false; - // skip 1 to give enough time for drive_to. obs1_info->forbidden_segment = strdup("seg60"); pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); @@ -397,7 +401,6 @@ static void *route99(void *arg) { testsuite_set_signal("signal30", "aspect_stop"); - // skip 1 segment to give enough time for drive_to. prep_observer_segment_info(obs1_info, "seg66"); pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); @@ -410,7 +413,6 @@ static void *route99(void *arg) { testsuite_set_signals_to(signals_stop_1, 3, "aspect_stop"); - // skip 1 segment to give enough time for drive_to. prep_observer_segment_info(obs1_info, "seg40"); pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); @@ -443,10 +445,9 @@ static void *route99(void *arg) { const char* signals_go_2[5] = {"signal26", "signal38", "signal36", "signal34", "signal32"}; testsuite_set_signals_to(signals_go_2, 5, "aspect_go"); - sleep(1); - // skip 1 segment to give enough time for drive_to. + prep_observer_segment_info(obs1_info, "seg48"); pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); @@ -457,7 +458,6 @@ static void *route99(void *arg) { testsuite_set_signal("signal26", "aspect_stop"); - // skip 1 segment to give enough time for drive_to. prep_observer_segment_info(obs1_info, "seg34"); pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); @@ -469,7 +469,6 @@ static void *route99(void *arg) { testsuite_set_signal("signal36", "aspect_stop"); - // skip 1 segment to give enough time for drive_to. prep_observer_segment_info(obs1_info, "seg60"); pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); @@ -529,41 +528,82 @@ static void *route100(void *arg) { static pthread_t route_observer_thread; - + // Note: Most but not all segments the observer is configured to observe + // for this route are not the immediate successors of the segment in driveTo, + // but rather the successor of the successor -> to prevent the observer + // from falsely recognizing a violation due to the combination of sleep + // statements (observer sleeps 0.1s, driveTo 0.25s -> fast train could cause issues). t_bidib_occ_observer_info *obs1_info = malloc(sizeof(t_bidib_occ_observer_info)); obs1_info->check_occ_only = false; obs1_info->train = strdup(train2); obs1_info->stop_requested = false; - // skip 1 to give enough time for drive_to. - ///TODO: Continue here. - obs1_info->forbidden_segment = strdup("seg TODO "); + obs1_info->forbidden_segment = strdup("seg28"); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg77", 60, train2); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } testsuite_set_signal("signal43", "aspect_stop"); + + + prep_observer_segment_info(obs1_info, "seg4"); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg26", 60, train2); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } testsuite_set_signal("signal19", "aspect_stop"); + + + prep_observer_segment_info(obs1_info, "seg18"); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg1", 60, train2); - testsuite_set_signal("signal3", "aspect_stop"); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } testsuite_set_signal("signal1", "aspect_stop"); - + testsuite_set_signal("signal3", "aspect_stop"); + + + prep_observer_segment_info(obs1_info, "seg13"); + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg15", 60, train2); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } testsuite_set_signal("signal13", "aspect_stop"); testsuite_set_signal("signal11", "aspect_stop"); - + + + prep_observer_segment_info(obs1_info, "seg9"); // seg11 -> seg10 -> *seg9* + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg11", 60, train2); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } testsuite_set_signal("signal10", "aspect_stop"); testsuite_set_signal("signal8", "aspect_stop"); - + + + prep_observer_segment_info(obs1_info, "seg30"); // seg31a -> *seg30* + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg31b", 60, train2); testsuite_driveTo("seg31b", 40, train2); sleep(1); testsuite_driveTo("seg31a", 30, train2); sleep(1); testsuite_driveToStop("seg31a", 20, train2); - + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } + sleep(3); // train2: backwards @@ -577,29 +617,72 @@ static void *route100(void *arg) { sleep(1); + prep_observer_segment_info(obs1_info, "seg9"); // seg32 -> seg33 -> *seg9* + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg32", -60, train2); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } testsuite_set_signal("signal22a", "aspect_stop"); testsuite_set_signal("signal22b", "aspect_stop"); - + + + prep_observer_segment_info(obs1_info, "seg15"); // seg13 -> seg14 -> *seg15* + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg13", -60, train2); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } testsuite_set_signal("signal9", "aspect_stop"); - + + + prep_observer_segment_info(obs1_info, "seg19"); // seg17 -> seg18 -> *seg19* + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg17", -60, train2); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } testsuite_set_signal("signal12", "aspect_stop"); testsuite_set_signal("signal14", "aspect_stop"); - + + + prep_observer_segment_info(obs1_info, "seg24"); // seg3 -> seg4 -> *seg24* + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg3", -60, train2); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } testsuite_set_signal("signal2", "aspect_stop"); testsuite_set_signal("signal4a", "aspect_stop"); testsuite_set_signal("signal4b", "aspect_stop"); - + + + prep_observer_segment_info(obs1_info, "seg77"); // seg28 -> seg29 -> *seg77* + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + testsuite_driveTo("seg28", -50, train2); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } testsuite_set_signal("signal20", "aspect_stop"); + + + prep_observer_segment_info(obs1_info, "seg78b"); // seg78a -> *seg78b* + pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); testsuite_driveTo("seg78a", -50, train2); sleep(2); testsuite_driveToStop("seg78a", -20, train2); - sleep(2); + if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { + pthread_exit(NULL); + } + sleep(1); + + free_obs_info_util(obs1_info); pthread_exit(NULL); } From b3ae4a34c3a1bedabebe0cc17ac34d0adf2f460e Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Fri, 6 Dec 2024 15:30:16 +0100 Subject: [PATCH 16/23] wrapper for testsuite drive and observe --- test/physical/swtbahn-full/testsuite.c | 101 ++++++++++--------------- 1 file changed, 42 insertions(+), 59 deletions(-) diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index 68d83e5..4335fcc 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -97,7 +97,7 @@ static void *occupancy_observer(void *arg) { const char *i_segmt = obs_info->forbidden_segment; bool violation = false; if (i_segmt == NULL) { - continue; + pthread_exit(NULL); } else if (obs_info->check_occ_only) { violation = testsuite_is_segment_occupied(i_segmt); } else { @@ -128,11 +128,11 @@ static void prep_observer_segment_info(t_bidib_occ_observer_info *obs_info, cons static bool stop_observer_and_check_still_running(t_bidib_occ_observer_info *obs_info, pthread_t observer_thread, - const char *callerlogname) { + const char *logname) { obs_info->stop_requested = true; pthread_join(observer_thread, NULL); if (!bidib_is_running()) { - printf("testsuite: %s - stop, bidib is not running anymore", callerlogname); + printf("testsuite: %s - stop, bidib is not running anymore", logname); free_obs_info_util(obs_info); return false; } @@ -353,6 +353,24 @@ void testsuite_case_swtbahnFullTrackCoverage(const char *train) { } } +static bool wrap_drive_and_observe(t_bidib_occ_observer_info *obs_info, + int speed, const char *train, bool driveToStop, + const char *target_segment, const char *observe_segment, + const char *logname) +{ + pthread_t r_obs_thr; + prep_observer_segment_info(obs_info, observe_segment); + pthread_create(&r_obs_thr, NULL, occupancy_observer, (void*) obs_info); + + if (driveToStop) { + testsuite_driveToStop(target_segment, speed, train); + } else { + testsuite_driveTo(target_segment, speed, train); + } + + return stop_observer_and_check_still_running(obs_info, r_obs_thr, logname); +} + static void *route99(void *arg) { const char *train1 = arg; @@ -379,65 +397,49 @@ static void *route99(void *arg) { sleep(1); - static pthread_t route_observer_thread; // Note: Most but not all segments the observer is configured to observe // for this route are not the immediate successors of the segment in driveTo, // but rather the successor of the successor -> to prevent the observer // from falsely recognizing a violation due to the combination of sleep // statements (observer sleeps 0.1s, driveTo 0.25s -> fast train could cause issues). - t_bidib_occ_observer_info *obs1_info = malloc(sizeof(t_bidib_occ_observer_info)); - obs1_info->check_occ_only = false; - obs1_info->train = strdup(train1); - obs1_info->stop_requested = false; - obs1_info->forbidden_segment = strdup("seg60"); - - pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); + t_bidib_occ_observer_info *obs_i = malloc(sizeof(t_bidib_occ_observer_info)); + obs_i->check_occ_only = false; + obs_i->train = strdup(train1); + obs_i->stop_requested = false; + obs_i->forbidden_segment = NULL; + const char *l_name = "route99"; - testsuite_driveTo("seg57", 50, train1); - if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { + if (!wrap_drive_and_observe(obs_i, 50, train1, false, "seg56", "seg60", l_name)) { pthread_exit(NULL); } testsuite_set_signal("signal30", "aspect_stop"); - - prep_observer_segment_info(obs1_info, "seg66"); - pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); - - testsuite_driveTo("seg64", 50, train1); - if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { + if (!wrap_drive_and_observe(obs_i, 50, train1, false, "seg64", "seg66", l_name)) { pthread_exit(NULL); } - const char* signals_stop_1[3] = {"signal33", "signal35a", "signal35b"}; testsuite_set_signals_to(signals_stop_1, 3, "aspect_stop"); - prep_observer_segment_info(obs1_info, "seg40"); - pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); - - testsuite_driveTo("seg69", 50, train1); - if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { + if (!wrap_drive_and_observe(obs_i, 50, train1, false, "seg69", "seg40", l_name)) { pthread_exit(NULL); } testsuite_set_signal("signal37", "aspect_stop"); - prep_observer_segment_info(obs1_info, "seg47"); - pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); - - testsuite_driveTo("seg46", 50, train1); - if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { + if (!wrap_drive_and_observe(obs_i, 50, train1, false, "seg46", "seg47", l_name)) { pthread_exit(NULL); } sleep(1); + // -> last segment before end of that platform - can't observe any overrun. testsuite_driveToStop("seg47", 20, train1); sleep(4); if (!bidib_is_running()) { printf("testsuite: route99 - stop, bidib is not running anymore"); - free_obs_info_util(obs1_info); + free_obs_info_util(obs_i); pthread_exit(NULL); } @@ -447,53 +449,34 @@ static void *route99(void *arg) { testsuite_set_signals_to(signals_go_2, 5, "aspect_go"); sleep(1); - - prep_observer_segment_info(obs1_info, "seg48"); - pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); - - testsuite_driveTo("seg45", -50, train1); - if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { + if (!wrap_drive_and_observe(obs_i, -50, train1, false, "seg45", "seg48", l_name)) { pthread_exit(NULL); } testsuite_set_signal("signal26", "aspect_stop"); - - prep_observer_segment_info(obs1_info, "seg34"); - pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); - - testsuite_driveTo("seg67", -50, train1); - if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { + if (!wrap_drive_and_observe(obs_i, -50, train1, false, "seg67", "seg34", l_name)) { pthread_exit(NULL); } testsuite_set_signal("signal38", "aspect_stop"); testsuite_set_signal("signal36", "aspect_stop"); - prep_observer_segment_info(obs1_info, "seg60"); - pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); - - testsuite_driveTo("seg62", -50, train1); - if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route99")) { + if (!wrap_drive_and_observe(obs_i, -50, train1, false, "seg62", "seg60", l_name)) { pthread_exit(NULL); } testsuite_set_signal("signal34", "aspect_stop"); testsuite_set_signal("signal32", "aspect_stop"); - prep_observer_segment_info(obs1_info, "seg59"); - pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); - - testsuite_driveTo("seg60", -50, train1); - testsuite_driveTo("seg53", -40, train1); - testsuite_driveTo("seg58", -30, train1); + if (!wrap_drive_and_observe(obs_i, -30, train1, false, "seg58", "seg59", l_name)) { + pthread_exit(NULL); + } + sleep(2); testsuite_driveToStop("seg58", -20, train1); - - obs1_info->stop_requested = true; - pthread_join(route_observer_thread, NULL); - free_obs_info_util(obs1_info); - sleep(1); + + free_obs_info_util(obs_i); pthread_exit(NULL); } From addbca847f5033ecf8d125e3d6a59eb1f01b768e Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Fri, 6 Dec 2024 15:54:22 +0100 Subject: [PATCH 17/23] node state adjustment: allow more responses to be queued. --- src/transmission/bidib_transmission_node_states.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/transmission/bidib_transmission_node_states.c b/src/transmission/bidib_transmission_node_states.c index 8f375eb..26e43bb 100644 --- a/src/transmission/bidib_transmission_node_states.c +++ b/src/transmission/bidib_transmission_node_states.c @@ -42,7 +42,7 @@ pthread_mutex_t bidib_node_state_table_mutex; static GHashTable *node_state_table = NULL; -static int response_limit = 48; +static int response_limit = 128; void bidib_node_state_table_init() { node_state_table = g_hash_table_new(g_str_hash, g_str_equal); @@ -123,8 +123,8 @@ static bool bidib_node_stall_ready(const uint8_t *const addr_stack) { if (state != NULL && state->stall) { // Node at addr_cpy is stalled -> search its stall_affected_nodes_queue to see // if the queue contains the (node at) addr_stack. - if (!g_queue_find_custom(state->stall_affected_nodes_queue, addr_stack, - (GCompareFunc)bidib_node_stall_queue_entry_equals)) + if (g_queue_find_custom(state->stall_affected_nodes_queue, addr_stack, + (GCompareFunc)bidib_node_stall_queue_entry_equals) == NULL) { // stalled subnode (addr_stack) is not yet in stall_affected_nodes_queue, // so add it From 22960ba9e0f1a283481702c78656e98f8abb21e6 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Fri, 6 Dec 2024 15:56:56 +0100 Subject: [PATCH 18/23] reverted large amount of responses to not overload node, reduce log level of waiting for space in queue. --- src/transmission/bidib_transmission_node_states.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/transmission/bidib_transmission_node_states.c b/src/transmission/bidib_transmission_node_states.c index 26e43bb..9d35418 100644 --- a/src/transmission/bidib_transmission_node_states.c +++ b/src/transmission/bidib_transmission_node_states.c @@ -42,7 +42,7 @@ pthread_mutex_t bidib_node_state_table_mutex; static GHashTable *node_state_table = NULL; -static int response_limit = 128; +static int response_limit = 48; void bidib_node_state_table_init() { node_state_table = g_hash_table_new(g_str_hash, g_str_equal); @@ -192,7 +192,7 @@ static void bidib_node_try_queued_messages(t_bidib_node_state *state) { free(queued_msg); sent_count++; } else { - syslog_libbidib(LOG_WARNING, + syslog_libbidib(LOG_INFO, "bidib_node_try_queued_messages - Unable to send queued msg, " "not enough space in response queue. Message info: " "type: 0x%02x addressed to: 0x%02x 0x%02x 0x%02x 0x%02x" From fea80693e2d16402f0306d7bcd589b684f9a7345 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Fri, 6 Dec 2024 16:02:23 +0100 Subject: [PATCH 19/23] fix missing conditional negation and missing linebreaks in printf --- test/physical/swtbahn-full/testsuite.c | 38 +++++++++++++------------- test/physical/test_common.c | 14 +++++----- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index 4335fcc..206c5be 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -132,7 +132,7 @@ static bool stop_observer_and_check_still_running(t_bidib_occ_observer_info *obs obs_info->stop_requested = true; pthread_join(observer_thread, NULL); if (!bidib_is_running()) { - printf("testsuite: %s - stop, bidib is not running anymore", logname); + printf("testsuite: %s - stop, bidib is not running anymore.\n", logname); free_obs_info_util(obs_info); return false; } @@ -152,7 +152,7 @@ static bool route1(const char *train) { }; if (!testsuite_set_and_check_points(points_normal, 4, points_reverse, 8)) { - printf("testsuite: route1 - one or more points are not in expected aspect."); + printf("testsuite: route1 - one or more points are not in expected aspect.\n"); return false; } @@ -207,7 +207,7 @@ static bool route2(const char *train) { }; if (!testsuite_set_and_check_points(points_normal_c1, 3, points_reverse_c1, 16)) { - printf("testsuite: route2 - one or more points are not in expected aspect (1st check)."); + printf("testsuite: route2 - one or more points are not in expected aspect (1st check).\n"); return false; } @@ -222,7 +222,7 @@ static bool route2(const char *train) { }; if (!testsuite_set_and_check_points(points_normal_c2, 8, points_reverse_c2, 10)) { - printf("testsuite: route2 - one or more points are not in expected aspect (2nd check)."); + printf("testsuite: route2 - one or more points are not in expected aspect (2nd check).\n"); return false; } @@ -232,7 +232,7 @@ static bool route2(const char *train) { const char *points_reverse_c3[1] = { "point7" }; if (!testsuite_set_and_check_points(points_normal_c3, 1, points_reverse_c3, 1)) { - printf("testsuite: route2 - one or more points are not in expected aspect (3rd check)."); + printf("testsuite: route2 - one or more points are not in expected aspect (3rd check).\n"); return false; } @@ -255,7 +255,7 @@ static bool route3(const char *train) { }; if (!testsuite_set_and_check_points(points_normal, 4, points_reverse, 12)) { - printf("testsuite: route3 - one or more points are not in expected aspect."); + printf("testsuite: route3 - one or more points are not in expected aspect.\n"); return false; } @@ -279,7 +279,7 @@ static bool route4(const char *train) { }; if (!testsuite_set_and_check_points(points_normal, 5, points_reverse, 10)) { - printf("testsuite: route4 - one or more points are not in expected aspect."); + printf("testsuite: route4 - one or more points are not in expected aspect.\n"); return false; } @@ -302,7 +302,7 @@ static bool route5(const char *train) { }; if (!testsuite_set_and_check_points(points_normal_c1, 2, points_reverse_c1, 8)) { - printf("testsuite: route5 - one or more points are not in expected aspect (1st check)."); + printf("testsuite: route5 - one or more points are not in expected aspect (1st check).\n"); return false; } @@ -311,7 +311,7 @@ static bool route5(const char *train) { sleep(3); // Check that point is in desired position if (!testsuite_check_point_aspect("point21", "reverse")) { - printf("testsuite: route5 - point 21 is not in expected aspect (2nd check)."); + printf("testsuite: route5 - point 21 is not in expected aspect (2nd check).\n"); return false; } @@ -323,32 +323,32 @@ static bool route5(const char *train) { void testsuite_case_swtbahnFullTrackCoverage(const char *train) { if (train == NULL) { - printf("testsuite: swtbahn-full track coverage single train - train is NULL"); + printf("testsuite: swtbahn-full track coverage single train - train is NULL\n"); return; } if (!route1(train)) { - printf("testsuite: swtbahn-full track coverage single train - route1 failed."); + printf("testsuite: swtbahn-full track coverage single train - route1 failed.\n"); return; } if (!route2(train)) { - printf("testsuite: swtbahn-full track coverage single train - route2 failed."); + printf("testsuite: swtbahn-full track coverage single train - route2 failed.\n"); return; } if (!route3(train)) { - printf("testsuite: swtbahn-full track coverage single train - route3 failed."); + printf("testsuite: swtbahn-full track coverage single train - route3 failed.\n"); return; } if (!route4(train)) { - printf("testsuite: swtbahn-full track coverage single train - route4 failed."); + printf("testsuite: swtbahn-full track coverage single train - route4 failed.\n"); return; } if (!route5(train)) { - printf("testsuite: swtbahn-full track coverage single train - route5 failed."); + printf("testsuite: swtbahn-full track coverage single train - route5 failed.\n"); return; } } @@ -388,7 +388,7 @@ static void *route99(void *arg) { }; if (!testsuite_set_and_check_points(points_normal, 4, points_reverse, 8)) { - printf("testsuite: route99 - one or more points are not in expected aspect."); + printf("testsuite: route99 - one or more points are not in expected aspect.\n"); pthread_exit(NULL); } @@ -438,7 +438,7 @@ static void *route99(void *arg) { sleep(4); if (!bidib_is_running()) { - printf("testsuite: route99 - stop, bidib is not running anymore"); + printf("testsuite: route99 - stop, bidib is not running anymore\n"); free_obs_info_util(obs_i); pthread_exit(NULL); } @@ -497,7 +497,7 @@ static void *route100(void *arg) { }; if (!testsuite_set_and_check_points(points_normal, 5, points_reverse, 5)) { - printf("testsuite: route100 - one or more points are not in expected aspect."); + printf("testsuite: route100 - one or more points are not in expected aspect.\n"); pthread_exit(NULL); } @@ -689,7 +689,7 @@ bool route_custom_short(const char *train) { "point2", "point1", "point7", "point6", "point5", "point4", "point3" }; if (!testsuite_set_and_check_points(points_normal, 7, NULL, 0)) { - printf("testsuite: route_custom_short - one or more points are not in expected aspect."); + printf("testsuite: route_custom_short - one or more points are not in expected aspect.\n"); return false; } diff --git a/test/physical/test_common.c b/test/physical/test_common.c index 468bccf..5da6564 100644 --- a/test/physical/test_common.c +++ b/test/physical/test_common.c @@ -208,7 +208,7 @@ void testsuite_driveTo_legacy(const char *segment, int speed, const char *train) struct timespec tv; clock_gettime(CLOCK_MONOTONIC, &tv); bidib_free_train_position_query(trainPosition); - printf("testsuite: Drive %s to %s at speed %d - REACHED TARGET - detected at time %ld.%.ld", + printf("testsuite: Drive %s to %s at speed %d - REACHED TARGET - detected at time %ld.%.ld\n", train, segment, speed, tv.tv_sec, tv.tv_nsec); return; } @@ -218,7 +218,7 @@ void testsuite_driveTo_legacy(const char *segment, int speed, const char *train) if (counter++ % 8 == 0) { struct timespec tv; clock_gettime(CLOCK_MONOTONIC, &tv); - printf("testsuite: Drive %s to %s at speed %d - waiting for train to arrive, time %ld.%.ld", + printf("testsuite: Drive %s to %s at speed %d - waiting for train to arrive, time %ld.%.ld\n", train, segment, speed, tv.tv_sec, tv.tv_nsec); } @@ -310,12 +310,12 @@ void testsuite_switch_point(const char *point, const char *aspect) { bool testsuite_check_point_aspect(const char *point, const char *aspect) { if (point == NULL || aspect == NULL) { - printf("testsuite: check point aspect - invalid parameters"); + printf("testsuite: check point aspect - invalid parameters\n"); return false; } t_bidib_unified_accessory_state_query state = bidib_get_point_state(point); - if (state.known) { - printf("testsuite: check point aspect - unknown point"); + if (!state.known) { + printf("testsuite: check point aspect - unknown point %s\n", point); bidib_free_unified_accessory_state_query(state); return false; } @@ -324,7 +324,7 @@ bool testsuite_check_point_aspect(const char *point, const char *aspect) { bidib_free_unified_accessory_state_query(state); return true; } else { - printf("testsuite: check point aspect - point %s is in aspect %s, not in %s", + printf("testsuite: check point aspect - point %s is in aspect %s, not in %s\n", point, state.board_accessory_state.state_id, aspect); } } else { @@ -332,7 +332,7 @@ bool testsuite_check_point_aspect(const char *point, const char *aspect) { bidib_free_unified_accessory_state_query(state); return true; } else { - printf("testsuite: check point aspect - point %s is in aspect %s, not in %s", + printf("testsuite: check point aspect - point %s is in aspect %s, not in %s\n", point, state.dcc_accessory_state.state_id, aspect); } } From a53717c8e7a56d921d981ee1d5507f0c8121199d Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Fri, 6 Dec 2024 16:07:19 +0100 Subject: [PATCH 20/23] fix typo --- test/physical/swtbahn-full/testsuite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index 206c5be..93cbf92 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -410,7 +410,7 @@ static void *route99(void *arg) { obs_i->forbidden_segment = NULL; const char *l_name = "route99"; - if (!wrap_drive_and_observe(obs_i, 50, train1, false, "seg56", "seg60", l_name)) { + if (!wrap_drive_and_observe(obs_i, 50, train1, false, "seg57", "seg60", l_name)) { pthread_exit(NULL); } testsuite_set_signal("signal30", "aspect_stop"); From e97938e94cc9ba454cc92acdc068937617b58fe1 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Fri, 6 Dec 2024 16:17:55 +0100 Subject: [PATCH 21/23] adjust second train end of route --- test/physical/swtbahn-full/testsuite.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index 93cbf92..abac781 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -657,9 +657,7 @@ static void *route100(void *arg) { prep_observer_segment_info(obs1_info, "seg78b"); // seg78a -> *seg78b* pthread_create(&route_observer_thread, NULL, occupancy_observer, (void*) obs1_info); - testsuite_driveTo("seg78a", -50, train2); - sleep(2); - testsuite_driveToStop("seg78a", -20, train2); + testsuite_driveToStop("seg78a", -50, train2); if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { pthread_exit(NULL); } From ffbd7bfdc602408046ee2df4031786e5f0456c65 Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Fri, 6 Dec 2024 16:19:11 +0100 Subject: [PATCH 22/23] add observer heartbeat --- test/physical/swtbahn-full/testsuite.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index abac781..7a1b433 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -93,7 +93,8 @@ static void *occupancy_observer(void *arg) { printf("testsuite: Occ-Observer exit: tr_dcc_addr unknown\n"); pthread_exit(NULL); } - while (!obs_info->stop_requested) { + long counter = 0; + while (!obs_info->stop_requested && bidib_is_running()) { const char *i_segmt = obs_info->forbidden_segment; bool violation = false; if (i_segmt == NULL) { @@ -114,6 +115,9 @@ static void *occupancy_observer(void *arg) { pthread_exit(NULL); } usleep(100000); // 0.1s + if (counter++ % 10 == 0) { + printf("testsuite: Observer heartbeat - observing %s\n", i_segmt); + } } pthread_exit(NULL); } From 6f103ae210bb8ba93b7141f097085fa13ff5c20a Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Fri, 6 Dec 2024 16:40:27 +0100 Subject: [PATCH 23/23] minor sleep and speed test adjustments --- test/physical/swtbahn-full/testsuite.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/physical/swtbahn-full/testsuite.c b/test/physical/swtbahn-full/testsuite.c index 7a1b433..40ff8ed 100644 --- a/test/physical/swtbahn-full/testsuite.c +++ b/test/physical/swtbahn-full/testsuite.c @@ -432,7 +432,7 @@ static void *route99(void *arg) { testsuite_set_signal("signal37", "aspect_stop"); - if (!wrap_drive_and_observe(obs_i, 50, train1, false, "seg46", "seg47", l_name)) { + if (!wrap_drive_and_observe(obs_i, 40, train1, false, "seg46", "seg47", l_name)) { pthread_exit(NULL); } @@ -584,14 +584,14 @@ static void *route100(void *arg) { testsuite_driveTo("seg31b", 60, train2); testsuite_driveTo("seg31b", 40, train2); sleep(1); - testsuite_driveTo("seg31a", 30, train2); + testsuite_driveTo("seg31a", 20, train2); sleep(1); testsuite_driveToStop("seg31a", 20, train2); if (!stop_observer_and_check_still_running(obs1_info, route_observer_thread, "route100")) { pthread_exit(NULL); } - sleep(3); + sleep(1); // train2: backwards