diff --git a/core/Communication.cc b/core/Communication.cc index f96b36ee2dfc3d2bc9279d18decf52174a1b9cd1..5f644222342f28da494d5c709648f230d66dc399 100644 --- a/core/Communication.cc +++ b/core/Communication.cc @@ -1115,16 +1115,21 @@ void TTCN_Communication::send_ptc_created(component component_reference) } void TTCN_Communication::prepare_stopped(Text_Buf& text_buf, - const char *return_type) + verdicttype final_verdict, const char *return_type, const char* reason) { text_buf.push_int(MSG_STOPPED); + text_buf.push_int(final_verdict); + text_buf.push_string(reason); text_buf.push_string(return_type); } -void TTCN_Communication::send_stopped() +void TTCN_Communication::send_stopped(verdicttype final_verdict, + const char* reason) { Text_Buf text_buf; text_buf.push_int(MSG_STOPPED); + text_buf.push_int(final_verdict); + text_buf.push_string(reason); // add an empty return type text_buf.push_string(NULL); send_message(text_buf); diff --git a/core/Communication.hh b/core/Communication.hh index 752617509b7ddc002285c584d034d4ee49960750..1a1e47055cce1f6fc595005474ba3eb3ad06d1c4 100644 --- a/core/Communication.hh +++ b/core/Communication.hh @@ -138,9 +138,9 @@ public: static void send_mtc_ready(); static void send_ptc_created(component component_reference); - static void prepare_stopped(Text_Buf& text_buf, - const char *return_type); - static void send_stopped(); + static void prepare_stopped(Text_Buf& text_buf, verdicttype final_verdict, + const char *return_type, const char* reason = ""); + static void send_stopped(verdicttype final_verdict, const char* reason = ""); static void prepare_stopped_killed(Text_Buf& text_buf, verdicttype final_verdict, const char *return_type, const char* reason = ""); diff --git a/core/Runtime.cc b/core/Runtime.cc index fd750ca2ca280ffe98e6570cf128c16acfae8c7d..d059d969661fd67ca5e51aa70bc6c17422897b8d 100644 --- a/core/Runtime.cc +++ b/core/Runtime.cc @@ -783,7 +783,7 @@ void TTCN_Runtime::start_function(const char *module_name, "Function %s was stopped. PTC remains alive and is waiting for next start.", function_name); // send a STOPPED message without return value - TTCN_Communication::send_stopped(); + TTCN_Communication::send_stopped(local_verdict, verdict_reason); // return and do nothing else return; case PTC_EXIT: @@ -825,8 +825,10 @@ void TTCN_Runtime::prepare_function_finished(const char *return_type, TTCN_error("Internal error: PTC behaviour function finished in invalid " "state."); if (is_alive) { - // Prepare a STOPPED message with the possible return value. - TTCN_Communication::prepare_stopped(text_buf, return_type); + // Prepare a STOPPED message with the current verdict and + // possible return value. + TTCN_Communication::prepare_stopped(text_buf, local_verdict, return_type, + verdict_reason); } else { // First the ports and timers must be stopped and deactivated. The // user_unmap and user_stop functions of Test Ports may detect errors diff --git a/mctr2/mctr/MainController.cc b/mctr2/mctr/MainController.cc index 55c9d6e10b7804862c1e20e0212df622b0453871..ba5602ccf70b3a094755438ed697f749efb541da 100644 --- a/mctr2/mctr/MainController.cc +++ b/mctr2/mctr/MainController.cc @@ -5863,6 +5863,9 @@ void MainController::process_stopped(component_struct *tc, int message_end) return; } Text_Buf& text_buf = *tc->text_buf; + tc->local_verdict = (verdicttype)text_buf.pull_int().get_val(); + delete [] tc->verdict_reason; + tc->verdict_reason = text_buf.pull_string(); delete [] tc->return_type; tc->return_type = text_buf.pull_string(); tc->return_value_len = message_end - text_buf.get_pos(); diff --git a/regression_test/done/DoneTest.ttcn b/regression_test/done/DoneTest.ttcn index c05886688fa2a1f9421f3de261f0deb3c37b740c..9719300ed81b230655b5b638f27b41616368b427 100644 --- a/regression_test/done/DoneTest.ttcn +++ b/regression_test/done/DoneTest.ttcn @@ -35,6 +35,27 @@ function f_behavior_pass() runs on CT { setverdict(pass); } +// Testing 'done' statement on an 'alive' component +function f_behavior_test_alive() runs on CT { + var CT ct := CT.create alive; + var verdicttype vt1; + ct.start(f_behavior_pass()); + ct.done -> value vt1; + if (vt1 != pass) { + setverdict(fail, "Test #1 failed. Verdict: ", vt1); + } + else { + // do the test again, without setting the verdict to 'pass'; + // the verdict on the component should still be the one set by the previous behavior function + var verdicttype vt2; + ct.start(f_behavior_none()); + ct.done -> value vt2; + if (vt2 != pass) { + setverdict(fail, "Test #2 failed. Verdict: ", vt2); + } + } +} + /*************** Test cases ***************/ // Testing 'done' statement on single component with no value redirect @@ -125,6 +146,20 @@ testcase tc_any_from_done_verdict_redirect() runs on CT { setverdict(pass); } +// Testing 'done' statement on an 'alive' component +testcase tc_done_verdict_redirect_alive_mtc() runs on CT { + // calling the function normally runs the test on the MTC + f_behavior_test_alive(); +} + +// Testing 'done' statement on an 'alive' component +testcase tc_done_verdict_redirect_alive_ptc() runs on CT { + // create a component variable to run the test on a PTC + var CT ct := CT.create; + ct.start(f_behavior_test_alive()); + ct.done; +} + /************** Control part **************/ control { execute(tc_done_single()); @@ -133,6 +168,8 @@ control { execute(tc_done_retval_redirect()); execute(tc_done_verdict_redirect()); execute(tc_any_from_done_verdict_redirect()); + execute(tc_done_verdict_redirect_alive_mtc()); + execute(tc_done_verdict_redirect_alive_ptc()); } }