From 9d305fec09df8d20cb38b719d50b138fb3781170 Mon Sep 17 00:00:00 2001 From: Jacqueline Deans Date: Tue, 15 Nov 2022 09:16:08 -0600 Subject: [PATCH] Add a way to disable sim objects (#1364) * Add set_sim_object_jobs_onoff, get_sim_object_on_off, and change set_sim_object_onoff to preserve the on/off status of jobs --- .../Executive-Scheduler.md | 20 +++++- include/trick/Executive.hh | 32 ++++++++- include/trick/SimObject.hh | 15 ++++- trick_source/.gitignore | 3 +- .../sim_services/Executive/Executive.cpp | 10 +++ .../Executive/Executive_c_intf.cpp | 38 +++++++++++ .../Executive_set_simobject_onoff.cpp | 65 +++++++++++++++---- .../Executive/test/Executive_test.cpp | 41 ++++++++++-- .../sim_services/Executive/test/Makefile | 23 ++++++- .../sim_services/SimObject/SimObject.cpp | 16 ++++- 10 files changed, 233 insertions(+), 30 deletions(-) diff --git a/docs/documentation/simulation_capabilities/Executive-Scheduler.md b/docs/documentation/simulation_capabilities/Executive-Scheduler.md index 53434729..48c07af1 100644 --- a/docs/documentation/simulation_capabilities/Executive-Scheduler.md +++ b/docs/documentation/simulation_capabilities/Executive-Scheduler.md @@ -205,10 +205,26 @@ If there is a job tag specified for one of more jobs in the S_define file, you c ``` # Python code -trick.exec_set_sim_object_onoff(char * job_name , int on) ; +trick.exec_set_sim_object_onoff(char * sim_object_name , int on) ; ``` -The exec_set_sim_object_onoff routine allows users to turn individual whole sim_objects on and off. +The exec_set_sim_object_onoff routine allows users to turn individual whole sim_objects on and off. If individiual jobs were disabled before the sim object is disabled, they will retain their disabled status when the sim object is turned back on. + +``` +# Python code +trick.exec_get_sim_object_onoff(char * sim_object_name) ; +``` + +The exec_get_sim_object_onoff routine allows users to determine if the sim_object is currently on or off. + + +``` +# Python code +trick.exec_set_sim_object_jobs_onoff(char * sim_object_name , int on) ; +``` + +The exec_set_sim_object_jobs_onoff allows users to turn all of the jobs in a sim_object on or off, but does not change the overall sim object's disabled status. + #### Job Cycle Time diff --git a/include/trick/Executive.hh b/include/trick/Executive.hh index b7f89b85..71d014e8 100644 --- a/include/trick/Executive.hh +++ b/include/trick/Executive.hh @@ -422,6 +422,13 @@ namespace Trick { */ int get_sim_objects(std::vector & in_sim_objects) ; + /** + Search for a sim object with the given name. + @param sim_object_name - name of desired SimObject + @return Pointer to sim object or NULL if not found + */ + SimObject * get_sim_object_by_name(std::string sim_object_name); + /** @userdesc Command to get the real-time software frame in seconds. @par Python Usage: @@ -807,15 +814,34 @@ namespace Trick { int set_job_cycle(std::string job_name, int instance_num, double in_cycle) ; /** - @userdesc Command to turn on/off all jobs in the sim_object. + @userdesc Command to enable or disable all jobs in a sim object (without setting sim object status). @par Python Usage: @code trick.exec_set_sim_object_onoff("", ) @endcode @param sim_object_name - name of sim_object from S_define file - @param on - 1 to turn job on, 0 to turn job off - @return 0 if successful or -1 if the job cannot be found + @param on - 1 to turn jobs on, 0 to turn jobs off + @return 0 if successful or -1 if the object cannot be found + */ + int set_sim_object_jobs_onoff(std::string sim_object_name, int on) ; + + /** + @userdesc Command to turn on/off the sim_object. + @par Python Usage: + @code trick.exec_set_sim_object_onoff("", ) @endcode + @param sim_object_name - name of sim_object from S_define file + @param on - 1 to turn object on, 0 to turn object off + @return 0 if successful or -1 if the object cannot be found */ int set_sim_object_onoff(std::string sim_object_name, int on) ; + /** + @userdesc Command to get whether the sim object is on or off. + @par Python Usage: + @code trick.exec_get_sim_object_onoff("") @endcode + @param sim_object_name - name of sim_object from S_define file + @return 1 if the object is enabled, 0 if the object is disabled, or -1 if the object cannot be found + */ + int get_sim_object_onoff (std::string sim_object_name) ; + /** @userdesc Trick Version & Date at the time executable was built. @par Python Usage: diff --git a/include/trick/SimObject.hh b/include/trick/SimObject.hh index 7ada230e..30f47344 100644 --- a/include/trick/SimObject.hh +++ b/include/trick/SimObject.hh @@ -11,6 +11,7 @@ PROGRAMMERS: #include #include +#include #include "trick/JobData.hh" @@ -32,11 +33,19 @@ namespace Trick { public: + SimObject () : object_disabled(false) {} + /** Name of SimObject given to object */ std::string name ; /* trick_units(--) */ /** SimObject id assigned by CP */ - int id ; /* trick_units(--) */ + int id ; /* trick_units(--) */ + + /** Indicates if the sim_object is enabled */ + bool object_disabled; /* trick_units(--) */ + + /** Save the job disabled states when the entire sim object is disabled */ + std::map saved_job_states; /* trick_io(**) */ /** Included simobjects -- currently not used */ std::vector pre_component_objects ; /* trick_io(**) */ @@ -97,12 +106,14 @@ namespace Trick { /** * Enables all jobs in the SimObject */ + void enable_all_jobs() ; void enable() ; /** * Disables all jobs in the SimObject */ - void disable() ; + void disable_all_jobs() ; + void disable(); /** * Calls all jobs that are not "dynamic_event" class diff --git a/trick_source/.gitignore b/trick_source/.gitignore index 853fc650..7fb1a4ea 100644 --- a/trick_source/.gitignore +++ b/trick_source/.gitignore @@ -1,2 +1,3 @@ *.gcda -*.gcno \ No newline at end of file +*.gcno +*.info diff --git a/trick_source/sim_services/Executive/Executive.cpp b/trick_source/sim_services/Executive/Executive.cpp index 4c27c4af..5b4759a7 100644 --- a/trick_source/sim_services/Executive/Executive.cpp +++ b/trick_source/sim_services/Executive/Executive.cpp @@ -216,6 +216,16 @@ int Trick::Executive::get_sim_objects(std::vector & in_sim_o return(0) ; } +Trick::SimObject * Trick::Executive::get_sim_object_by_name(std::string sim_object_name) { + for ( int ii = 0 ; ii < sim_objects.size() ; ii++ ) { + if ( ! sim_objects[ii]->name.compare(sim_object_name) ) { + return sim_objects[ii]; + } + } + + return NULL; +} + double Trick::Executive::get_software_frame() { return(software_frame) ; } diff --git a/trick_source/sim_services/Executive/Executive_c_intf.cpp b/trick_source/sim_services/Executive/Executive_c_intf.cpp index f5bc56a0..8e88f0c0 100644 --- a/trick_source/sim_services/Executive/Executive_c_intf.cpp +++ b/trick_source/sim_services/Executive/Executive_c_intf.cpp @@ -665,6 +665,30 @@ extern "C" int exec_set_sim_object_onoff(const char * sim_object_name , int on) return -1 ; } +/** + * @relates Trick::Executive + * @copydoc Trick::Executive::get_sim_object_onoff + * C wrapper for Trick::Executive::get_sim_object_onoff + */ +extern "C" int exec_get_sim_object_onoff(const char * sim_object_name ) { + if ( the_exec != NULL ) { + return the_exec->get_sim_object_onoff( sim_object_name ) ; + } + return -1 ; +} + +/** + * @relates Trick::Executive + * @copydoc Trick::Executive::set_sim_object_jobs_onoff + * C wrapper for Trick::Executive::set_sim_object_jobs_onoff + */ +extern "C" int exec_set_sim_object_jobs_onoff(const char * sim_object_name , int on) { + if ( the_exec != NULL ) { + return the_exec->set_sim_object_jobs_onoff( sim_object_name , on) ; + } + return -1 ; +} + /** * @relates Trick::Executive * @copydoc Trick::Executive::set_version_date_tag @@ -998,6 +1022,20 @@ int exec_get_sim_objects(std::vector& in_sim_objects ) { return -1 ; } + +/** + * @relates Trick::Executive + * @copydoc Trick::Executive::get_sim_objects + * Wrapper for Trick::Executive::get_sim_objects + */ +Trick::SimObject * exec_get_sim_object_by_name(std::string sim_object_name) { + if ( the_exec != NULL ) { + return the_exec->get_sim_object_by_name(sim_object_name) ; + } + return NULL ; +} + + /** * @relates Trick::Executive * @copydoc Trick::Executive::get_job diff --git a/trick_source/sim_services/Executive/Executive_set_simobject_onoff.cpp b/trick_source/sim_services/Executive/Executive_set_simobject_onoff.cpp index 7c4bcaa7..60dd5c15 100644 --- a/trick_source/sim_services/Executive/Executive_set_simobject_onoff.cpp +++ b/trick_source/sim_services/Executive/Executive_set_simobject_onoff.cpp @@ -3,21 +3,60 @@ #include "trick/Executive.hh" -int Trick::Executive::set_sim_object_onoff(std::string sim_object_name, int on) { +int Trick::Executive::set_sim_object_jobs_onoff(std::string sim_object_name, int on) { - SimObject * so ; - unsigned int ii , jj ; - - for ( ii = 0 ; ii < sim_objects.size() ; ii++ ) { - if ( ! sim_objects[ii]->name.compare(sim_object_name) ) { - so = sim_objects[ii] ; - for ( jj = 0 ; jj < so->jobs.size() ; jj++ ) { - so->jobs[jj]->disabled = !on ; - } - return(0) ; - } + SimObject * sim_object = get_sim_object_by_name(sim_object_name); + if (sim_object == NULL) { + return -1; } - return(-1) ; + if (on) { + sim_object->enable_all_jobs(); + } else { + sim_object->disable_all_jobs(); + } + + return 0; +} + + +int Trick::Executive::set_sim_object_onoff(std::string sim_object_name, int on) { + + SimObject * sim_object = get_sim_object_by_name(sim_object_name); + if (sim_object == NULL) { + return -1; + } + + sim_object->object_disabled = !on; + if (on) { + // Apply saved state + for ( int i = 0 ; i < sim_object->jobs.size() ; i++ ) { + std::map::iterator saved_state_it = sim_object->saved_job_states.find(sim_object->jobs[i]); + if (saved_state_it != sim_object->saved_job_states.end()) { + sim_object->jobs[i]->disabled = saved_state_it->second; + } else { + // If job is not in map, turn it on + sim_object->jobs[i]->disabled = false; + } + } + sim_object->saved_job_states.clear(); + } else { + for ( int i = 0 ; i < sim_object->jobs.size() ; i++ ) { + // Save state, turn off + sim_object->saved_job_states[sim_object->jobs[i]] = sim_object->jobs[i]->disabled; + sim_object->jobs[i]->disabled = true ; + } + } + return(0) ; +} + +int Trick::Executive::get_sim_object_onoff (std::string sim_object_name) { + + SimObject * sim_object = get_sim_object_by_name(sim_object_name); + if (sim_object == NULL) { + return -1; + } + + return !(sim_object->object_disabled) ; } diff --git a/trick_source/sim_services/Executive/test/Executive_test.cpp b/trick_source/sim_services/Executive/test/Executive_test.cpp index a4a2e775..92783f4e 100644 --- a/trick_source/sim_services/Executive/test/Executive_test.cpp +++ b/trick_source/sim_services/Executive/test/Executive_test.cpp @@ -845,25 +845,54 @@ TEST_F(ExecutiveTest , JobOnOff) { EXPECT_EQ(exec.set_job_onoff("so1.scheduled_4" , 1 , 0), -1) ; } -TEST_F(ExecutiveTest , SimObjectOnOff) { - //req.add_requirement("3132950280"); - +TEST_F(ExecutiveTest , SimObjectJobsOnOff) { Trick::JobData * curr_job ; exec_add_sim_object(&so1 , "so1") ; - EXPECT_EQ(exec.set_sim_object_onoff("so1" , 0), 0) ; + EXPECT_EQ(exec.set_sim_object_jobs_onoff("so1" , 0), 0) ; curr_job = exec.get_job( std::string("so1.scheduled_1")) ; ASSERT_FALSE( curr_job == NULL ) ; EXPECT_EQ( curr_job->disabled , true) ; + EXPECT_EQ( exec.get_sim_object_onoff("so1"), 1); - EXPECT_EQ(exec.set_sim_object_onoff("so1" , 1), 0) ; + EXPECT_EQ(exec.set_sim_object_jobs_onoff("so1" , 1), 0) ; EXPECT_EQ( curr_job->disabled , false) ; - EXPECT_EQ(exec.set_sim_object_onoff("so2" , 1), -1) ; + EXPECT_EQ(exec.set_sim_object_jobs_onoff("so2" , 1), -1) ; } +TEST_F(ExecutiveTest , SimObjectOnOff) { + + exec_add_sim_object(&so1 , "so1") ; + + // Test that after disabling and enabling sim object, top_of_frame is still disabled + Trick::JobData * curr_job = exec.get_job( std::string("so1.top_of_frame_1")) ; + ASSERT_FALSE( curr_job == NULL ) ; + + curr_job->disable(); + + EXPECT_EQ(exec.set_sim_object_onoff("so1" , 0), 0) ; + EXPECT_EQ(exec.get_sim_object_onoff("so1"), 0); + EXPECT_EQ(curr_job->disabled , true) ; + + // Add an extra job + so1.add_job(1, 100, "scheduled", NULL, 1, "child_job_1", "TRK") ; + exec.add_jobs_to_queue(&so1, false); + + Trick::JobData * new_job = exec.get_job( std::string ("so1.child_job_1")); + ASSERT_FALSE( new_job == NULL ) ; + + EXPECT_EQ(exec.set_sim_object_onoff("so1" , 1), 0) ; + EXPECT_EQ( exec.get_sim_object_onoff("so1"), 1); + EXPECT_EQ( curr_job->disabled , true) ; + EXPECT_EQ( new_job->disabled , false) ; + + EXPECT_EQ(exec.set_sim_object_onoff("so2" , 1), -1) ; + EXPECT_EQ(exec.get_sim_object_onoff("so2"), -1) ; +} + TEST_F(ExecutiveTest , LockMemory) { //req.add_requirement("715042410"); // Requires root to run. Will pass if run as root. diff --git a/trick_source/sim_services/Executive/test/Makefile b/trick_source/sim_services/Executive/test/Makefile index 94cf5cc8..a614e9ea 100644 --- a/trick_source/sim_services/Executive/test/Makefile +++ b/trick_source/sim_services/Executive/test/Makefile @@ -7,11 +7,14 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../../../share/trick/makefiles/Makefile.common +COVERAGE_FLAGS += -fprofile-arcs -ftest-coverage -O0 + # Flags passed to the preprocessor. TRICK_CXXFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra -std=c++11 ${TRICK_SYSTEM_CXXFLAGS} TRICK_LIBS = -L ${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main +TRICK_SYSTEM_LDFLAGS += ${COVERAGE_FLAGS} # All tests produced by this Makefile. Remember to add new tests you # created to the list. @@ -27,8 +30,26 @@ all : $(TESTS) test: $(TESTS) ./Executive_test --gtest_output=xml:${TRICK_HOME}/trick_test/Executive.xml +code-coverage: test + # Give rid of any old code-coverage HTML we may have. + rm -rf lcov_html + # Gather coverage information about the src code. + lcov --capture \ + --directory ../object_${TRICK_HOST_CPU} \ + --base-directory ../ \ + --output-file src_coverage.info + # Filter out information about directories that we don't care about. + lcov --remove src_coverage.info '/Applications/*' '/usr/include/*' \ + --output-file MemoryManager_code_coverage.info + # Generate HTML + genhtml MemoryManager_code_coverage.info \ + --output-directory lcov_html + # Clean up + # rm *.info + clean : - rm -f $(TESTS) *.o + rm -f $(TESTS) *.o *.gcda *.gcno *.info + rm -rf lcov_html Executive_test.o : Executive_test.cpp $(TRICK_CXX) $(TRICK_CXXFLAGS) -c $< diff --git a/trick_source/sim_services/SimObject/SimObject.cpp b/trick_source/sim_services/SimObject/SimObject.cpp index 4f11ff96..f17dc20b 100644 --- a/trick_source/sim_services/SimObject/SimObject.cpp +++ b/trick_source/sim_services/SimObject/SimObject.cpp @@ -2,6 +2,7 @@ #include #include "trick/SimObject.hh" +#include "trick/message_proto.h" Trick::SimObject::~SimObject() { while ( !jobs.empty() ) { @@ -99,17 +100,28 @@ Trick::JobData * Trick::SimObject::get_job( std::string job_name, unsigned int j return NULL ; } -void Trick::SimObject::enable() { +void Trick::SimObject::enable_all_jobs() { std::vector ::iterator it ; for ( it = jobs.begin() ; it != jobs.end() ; it++ ) { (*it)->enable() ; } } -void Trick::SimObject::disable() { +void Trick::SimObject::enable() { + message_publish(MSG_WARNING,"SimObject::enable has been deprecated, use SimObject::enable_all_jobs instead\n") ; + enable_all_jobs(); +} + + +void Trick::SimObject::disable_all_jobs() { std::vector ::iterator it ; for ( it = jobs.begin() ; it != jobs.end() ; it++ ) { (*it)->disable() ; } } +void Trick::SimObject::disable() { + message_publish(MSG_WARNING,"SimObject::disable has been deprecated, use SimObject::disable_all_jobs instead\n") ; + disable_all_jobs(); +} +