From f19ba7df78ef0eb1dd383a27220a07779d84e0a9 Mon Sep 17 00:00:00 2001 From: Jacqueline Deans Date: Fri, 7 Oct 2022 08:37:09 -0500 Subject: [PATCH] Test and Document STL Checkpointing (#1355) * Updates SIM_stl to include checkpoint writing and checkpoint restore, as well as adding more data structures to test * Thoroughly tests supported STL types with MM_stl_checkpoint and MM_stl_restore * Adds an option to enable or disable STL restore in accessible interfaces and changes default to true * Updates documentation on STL checkpointing to clearly state limitations and known bugs --- .../simulation_capabilities/Checkpoints.md | 8 + .../STL-Checkpointing.md | 9 - .../STL-capabilities.md | 130 ++ include/trick/CheckPointRestart.hh | 13 + include/trick/CheckPointRestart_c_intf.hh | 2 + include/trick/MemoryManager.hh | 14 +- include/trick/checkpoint_map.hh | 9 +- include/trick/memorymanager_c_intf.h | 4 +- test/SIM_stls/RUN_test/input.py | 10 - test/SIM_stls/RUN_test/setup.py | 15 + test/SIM_stls/RUN_test/unit_test.py | 18 +- test/SIM_stls/S_define | 9 +- test/SIM_stls/S_overrides.mk | 16 +- test/SIM_stls/models/STLCheckpoint.cpp | 469 ++++++- test/SIM_stls/models/STLCheckpoint.hh | 36 +- test/makefile | 3 + .../CheckPointRestart/CheckPointRestart.cpp | 5 + .../CheckPointRestart_c_intf.cpp | 24 + .../MemoryManager/MemoryManager.cpp | 2 +- .../MemoryManager/MemoryManager_C_Intf.cpp | 15 +- .../MemoryManager/MemoryManager_restore.cpp | 31 +- .../MemoryManager/test/.gitignore | 2 + .../MemoryManager/test/MM_read_checkpoint.cc | 74 +- .../MemoryManager/test/MM_stl_checkpoint.cc | 1121 +++++++++++++++++ .../MemoryManager/test/MM_stl_restore.cc | 1045 +++++++++++++++ .../MemoryManager/test/MM_stl_testbed.hh | 98 ++ .../MemoryManager/test/MM_test.hh | 56 + .../test/MM_user_defined_types.hh | 24 + .../MemoryManager/test/MM_write_checkpoint.cc | 27 + .../MemoryManager/test/MM_write_checkpoint.hh | 20 + .../sim_services/MemoryManager/test/Makefile | 36 +- 31 files changed, 3245 insertions(+), 100 deletions(-) delete mode 100644 docs/documentation/simulation_capabilities/STL-Checkpointing.md create mode 100644 docs/documentation/simulation_capabilities/STL-capabilities.md create mode 100644 test/SIM_stls/RUN_test/setup.py create mode 100644 trick_source/sim_services/MemoryManager/test/MM_stl_checkpoint.cc create mode 100644 trick_source/sim_services/MemoryManager/test/MM_stl_restore.cc create mode 100644 trick_source/sim_services/MemoryManager/test/MM_stl_testbed.hh diff --git a/docs/documentation/simulation_capabilities/Checkpoints.md b/docs/documentation/simulation_capabilities/Checkpoints.md index 541b6013..de7a70ea 100644 --- a/docs/documentation/simulation_capabilities/Checkpoints.md +++ b/docs/documentation/simulation_capabilities/Checkpoints.md @@ -23,6 +23,14 @@ trick.checkpoint_cpu() trick.checkpoint_safestore_set_enabled(True|False) # Set the safestore checkpoint period. default 9x10e18 trick.checkpoint_safestore() + +# Load a checkpoint +trick.load_checkpoint() +# Load a checkpoint without restoring STLs +trick.load_checkpoint(, False) +# Force the load_checkpoint job to run immediately +trick.load_checkpoint_job() + ``` [Continue to Memory Manager](memory_manager/MemoryManager) diff --git a/docs/documentation/simulation_capabilities/STL-Checkpointing.md b/docs/documentation/simulation_capabilities/STL-Checkpointing.md deleted file mode 100644 index 18ee1b34..00000000 --- a/docs/documentation/simulation_capabilities/STL-Checkpointing.md +++ /dev/null @@ -1,9 +0,0 @@ -| [Home](/trick) → [Documentation Home](../Documentation-Home) → [Simulation Capabilities](Simulation-Capabilities) → STL Checkpointing | -|------------------------------------------------------------------| - - -Trick does not currently support checkpointing C++ Standard Template Library (STL) types, although we working on it. - -For those data-structures you intend to checkpoint, you should avoid using STLs. - -[Continue to Threads](Threads) diff --git a/docs/documentation/simulation_capabilities/STL-capabilities.md b/docs/documentation/simulation_capabilities/STL-capabilities.md new file mode 100644 index 00000000..0e99d321 --- /dev/null +++ b/docs/documentation/simulation_capabilities/STL-capabilities.md @@ -0,0 +1,130 @@ +| [Home](/trick) → [Documentation Home](../Documentation-Home) → [Simulation Capabilities](Simulation-Capabilities) → Using STLs in Trick Sims | +|------------------------------------------------------------------| + +# Standard Template Libraries (STL) in Trick + +STLs may be used in models. However, STL variables (currently) are not data recordable, visible in the variable server, nor directly accessible in the input file. Some STLs can be checkpointed: array, vector, list, deque, set, multiset, map, multimap, stack, queue, priority_queue, pair. + +STL classes cannot be directly registered with the memory manager, but they can be processed by the checkpoint agent when nested inside normal C++ classes (including sim objects). + +STL checkpoint restore may slow down the default data jobs of some sims. STL restore is on by default. To turn off STL restore: + +If using memory manager through the C interface: +``` +int TMM_set_stl_restore (int on_off); +``` + +If using the memory manager through the C++ interface, set the default or pass a parameter to your read_checkpoint function of choice: +``` +int set_restore_stls_default (bool on); +int read_checkpoint( std::istream* in_s, bool do_restore_stls = restore_stls_default); +int read_checkpoint_from_string( const char* s, bool do_restore_stls = restore_stls_default ); +int init_from_checkpoint( std::istream* in_s, bool do_restore_stls = restore_stls_default); +``` + +If using the checkpoint restart C interface: +``` +int load_checkpoint_stls( const char * file_name, int with_stls ) ; +``` + + + +## What works: + +To checkpoint an STL, it **must** be a member of a class or struct. +``` +class AnyClass { + std::vector vec; +} +``` +Declare an instance of this class with the memory manager in the usual way: +``` +AnyClass * my_class = tmm->declare_var("AnyClass my_alloc"); +``` + +If it is in a class that is nested in a `sim_object`, it will be registered with the memory manager automatically. + +You can nest an arbitrary amount of STLs, they will all be checkpointed as long as +the base is a member of a class that is registered with the memory manager. There +are a some [**limitations**](#limitations) and exceptions due to [**bugs**](#known_bugs) at the moment (but hopefully not forever!) + +``` +class AnyClass { + std::pair> +} +``` + + + +## Limitations + +The STL checkpointing feature can only handle simple types, pointers, and nested STL types. + +### An STL type within a user defined type within an STL will fail to checkpoint. + +For example: a user defined class with an STL in it: +``` +class VectorWrapper { + int a; + std::vector vec; +} +``` + +An outer class (which is registered with the memory manager, like a member of a sim_object or something that has been explicitly declared) that has an STL container of these objects: +``` +class MyObject { + std::vector vec_user_defined; +} +``` + +If MyObject is populated, it will be able to checkpoint and restore without throwing an error, and all the `VectorWrapper` objects will be present, but `vec` will not be restored (`a` will restore successfully). The contents of `vec` are never written out to the checkpoint file. + + +If `MyObject` instead has a vector of pointers to `VectorWrapper`, and each `VectorWrapper` is registered with the memory manager, `vec` will checkpoint and restore successfully. +``` +class MyObject { + std::vector vec_user_defined_ptr; +} +``` + +### You cannot directly create or register an external stl with the memory manager, you will get a parser error. + +STLs can't register it with the memory manager, so there's no way for the checkpoint to know where the memory is. + +``` +class AnyClass { + std::vector *anything; +} + +class AnyClass { + std::pair[5]; +} + + +memorymanager->declare_var("std::vector my_vector_allocation"); + +std::vector my_vector; +memorymanager->declare_var_extern(&my_vector, "std::vector my_vector_allocation"); + +``` + + + + +## Known bugs + +The types in an std::pair cannot be sequence STL types (vector, queue, stack, etc). +``` + // This will fail to checkpoint + std::pair> +``` + +The types inside an std::set cannot be any STL types (excluding strings). +``` + // This will fail to compile + std::set> +``` + +These bugs are being worked on. + +[Continue to Threads](Threads) diff --git a/include/trick/CheckPointRestart.hh b/include/trick/CheckPointRestart.hh index ca071c20..4201d746 100644 --- a/include/trick/CheckPointRestart.hh +++ b/include/trick/CheckPointRestart.hh @@ -247,6 +247,19 @@ namespace Trick { */ virtual void load_checkpoint(std::string file_name) ; + /** + @brief @userdesc Command to load a checkpoint file. (Calls the preload_checkpoint jobs, calls the MemoryManager restore_managed_memory + method, then calls the restart jobs.) + This is invoked when the user clicks the "Load ASCII Chkpnt" button on the sim control panel. + @par Python Usage: + @code trick.load_checkpoint("") @endcode + @param file_name - file to read checkpoint data from + @param stl_restore_on - toggle whether to restore STLs + @return always 0 + */ + virtual void load_checkpoint(std::string file_name, bool stl_restore_on) ; + + /** @brief @userdesc Command to load a checkpoint file. (Calls the preload_checkpoint jobs, calls the MemoryManager restore_managed_memory method, then calls the restart jobs.) diff --git a/include/trick/CheckPointRestart_c_intf.hh b/include/trick/CheckPointRestart_c_intf.hh index 58ccdf9b..6b33c81c 100644 --- a/include/trick/CheckPointRestart_c_intf.hh +++ b/include/trick/CheckPointRestart_c_intf.hh @@ -51,6 +51,8 @@ int checkpoint_objects( const char * file_name, const char * objects ) ; /* load_checkpoint call accessible from C code */ int load_checkpoint( const char * file_name ) ; +int load_checkpoint_stls( const char * file_name, int with_stls ) ; + int load_checkpoint_job() ; void * get_address( const char * var_name ) ; diff --git a/include/trick/MemoryManager.hh b/include/trick/MemoryManager.hh index 09477362..2ea62e21 100644 --- a/include/trick/MemoryManager.hh +++ b/include/trick/MemoryManager.hh @@ -371,32 +371,32 @@ namespace Trick { Restore a checkpoint from the given stream. @param in_s - input stream. */ - int read_checkpoint( std::istream* in_s, bool do_restore_stls=false); + int read_checkpoint( std::istream* in_s, bool do_restore_stls = restore_stls_default); /** Read a checkpoint from the file of the given name. @param filename - name of the checkpoint file to be read. */ - int read_checkpoint( const char* filename); + int read_checkpoint( const char* filename, bool do_restore_stls = restore_stls_default); /** Read a checkpoint from the given string. @param s - string containing the checkpoint info. */ - int read_checkpoint_from_string( const char* s ); + int read_checkpoint_from_string( const char* s, bool do_restore_stls = restore_stls_default ); /** Delete all TRICK_LOCAL variables and clear all TRICK_EXTERN variables. Then read and restore the checkpoint from the given stream. @param in_s - input stream. */ - int init_from_checkpoint( std::istream* in_s); + int init_from_checkpoint( std::istream* in_s, bool do_restore_stls = restore_stls_default); /** Delete all TRICK_LOCAL variables and clear all TRICK_EXTERN variables. Then read and restore the checkpoint of the given filename. */ - int init_from_checkpoint( const char* filename); + int init_from_checkpoint( const char* filename, bool do_restore_stls = restore_stls_default); /** Deallocate the memory for all TRICK_LOCAL variables and then forget about them. @@ -662,6 +662,10 @@ namespace Trick { void write_JSON_alloc_info( std::ostream& s, ALLOC_INFO *alloc_info) ; void write_JSON_alloc_list( std::ostream& s, int start_ix, int num) ; + int set_restore_stls_default (bool on); + static bool restore_stls_default; /**< -- true = restore STL variables on checkpoint restore if user does not specify option. false = don't */ + + private: static int instance_count; /**< -- Number of instances of MemoryManager. Not allowed to exceed 1.*/ diff --git a/include/trick/checkpoint_map.hh b/include/trick/checkpoint_map.hh index d52939cb..65916c38 100644 --- a/include/trick/checkpoint_map.hh +++ b/include/trick/checkpoint_map.hh @@ -317,17 +317,18 @@ int checkpoint_map_stl_sk_sd(STL & in_map , std::string object_name , std::strin /* copy the contents of the map the 2 arrays */ for ( iter = in_map.begin() , ii = 0 ; iter != in_map.end() ; iter++ , ii++ ) { - std::ostringstream sub_elements ; + std::stringstream sub_elements ; sub_elements << object_name << "_" << var_name << "_keys_" << ii ; keys[ii] = sub_elements.str() ; - std::ostringstream index_string ; + std::stringstream index_string ; index_string << ii ; checkpoint_stl( const_cast(iter->first) , object_name + "_" + var_name + "_keys", index_string.str() ) ; - sub_elements << object_name << "_" << var_name << "_data_" << ii ; - items[ii] = sub_elements.str() ; + std::stringstream sub_elements_data; + sub_elements_data << object_name << "_" << var_name << "_data_" << ii ; + items[ii] = sub_elements_data.str() ; checkpoint_stl( iter->second , object_name + "_" + var_name + "_data", index_string.str() ) ; diff --git a/include/trick/memorymanager_c_intf.h b/include/trick/memorymanager_c_intf.h index 0603dbaa..9c57fb7f 100644 --- a/include/trick/memorymanager_c_intf.h +++ b/include/trick/memorymanager_c_intf.h @@ -50,12 +50,14 @@ void TMM_delete_extern_var_a( void* address); void TMM_delete_extern_var_n( const char* var_name ); void TMM_write_checkpoint( const char* filename) ; + int TMM_read_checkpoint( const char* filename); int TMM_read_checkpoint_from_string( const char* str); - int TMM_init_from_checkpoint( const char* filename); + int TMM_add_shared_library_symbols( const char* filename); +int TMM_set_stl_restore (int on_off); REF2* ref_attributes(const char* name); int ref_var(REF2* R, char* name); diff --git a/test/SIM_stls/RUN_test/input.py b/test/SIM_stls/RUN_test/input.py index 458f7730..40dffd39 100644 --- a/test/SIM_stls/RUN_test/input.py +++ b/test/SIM_stls/RUN_test/input.py @@ -1,17 +1,7 @@ def main(): - #trick.echo_jobs_on() - #trick.sim_control_panel_set_enabled(True) - #trick.real_time_enable() - #trick.itimer_enable() - - trick.checkpoint_pre_init(True) - #trick.checkpoint_post_init(True) - #trick.checkpoint_end(True) - - #trick.freeze(2.0) trick.exec_set_software_frame(0.10) trick.exec_set_freeze_frame(0.10) diff --git a/test/SIM_stls/RUN_test/setup.py b/test/SIM_stls/RUN_test/setup.py new file mode 100644 index 00000000..208d871f --- /dev/null +++ b/test/SIM_stls/RUN_test/setup.py @@ -0,0 +1,15 @@ +import trick + +def main(): + trick.exec_set_job_onoff("the_object.stlc.addData", 1, True) + trick.exec_set_job_onoff("the_object.stlc.test", 1, False) + trick.exec_set_job_onoff("the_object.stlc.print", 1, False) + + trick.add_read( 0.5, 'trick.checkpoint("chkpnt_in")') + + trick.exec_set_freeze_frame(0.10) + trick.stop(1.0) + +if __name__ == "__main__": + main() + diff --git a/test/SIM_stls/RUN_test/unit_test.py b/test/SIM_stls/RUN_test/unit_test.py index 6f11ebd5..16c31069 100644 --- a/test/SIM_stls/RUN_test/unit_test.py +++ b/test/SIM_stls/RUN_test/unit_test.py @@ -1,12 +1,20 @@ +import trick +from trick.unit_test import * def main(): - trick.checkpoint_post_init(True) - trick.checkpoint_end(True) + trick.load_checkpoint("RUN_test/chkpnt_in") + trick.load_checkpoint_job() - # Data recording HDF5 test - trick.exec_set_freeze_frame(0.10) - trick.stop(5.0) + trick.exec_set_job_onoff("the_object.stlc.addData", 1, False) + trick.exec_set_job_onoff("the_object.stlc.test", 1, True) + trick.exec_set_job_onoff("the_object.stlc.print", 1, False) + + trick_utest.unit_tests.enable() + trick_utest.unit_tests.set_file_name( os.getenv("TRICK_HOME") + "/trick_test/SIM_stl.xml" ) + trick_utest.unit_tests.set_test_name( "STLCheckpointTest" ) + + trick.stop(1.0) if __name__ == "__main__": main() diff --git a/test/SIM_stls/S_define b/test/SIM_stls/S_define index 908cbe15..7e377dc6 100644 --- a/test/SIM_stls/S_define +++ b/test/SIM_stls/S_define @@ -8,10 +8,15 @@ class theSimObject : public Trick::SimObject { STLCheckpoint stlc ; /** Constructor to add the jobs */ - theSimObject() : stlc("Petunia") { - (1.0, "scheduled") stlc.speak() ; + theSimObject() : stlc() { + ("initialization") stlc.addData(); + (1.0, "scheduled") stlc.test () ; + (1.0, "scheduled") stlc.print () ; + } + + } ; theSimObject the_object ; diff --git a/test/SIM_stls/S_overrides.mk b/test/SIM_stls/S_overrides.mk index c4c9b818..b05ddfc7 100644 --- a/test/SIM_stls/S_overrides.mk +++ b/test/SIM_stls/S_overrides.mk @@ -2,4 +2,18 @@ TRICK_CFLAGS += -I./models TRICK_CXXFLAGS += -I./models -#TRICK_CXXFLAGS += -std=c++11 +TRICK_CXXFLAGS += -std=c++11 + +test: setup + +# This is a workaround so that the sim runs with RUN_test/setup.py before the actual unit test run. +# setup.py adds hardcoded data to the sim and dumps a checkpoint, and unit_test.py loads that checkpoint and checks all the values. + +setup: T_main_${TRICK_HOST_CPU}.exe + echo "Running Setup Job" + ./T_main_${TRICK_HOST_CPU}.exe RUN_test/setup.py + +clean: checkpoint_clean + +checkpoint_clean: + rm -f RUN_test/chkpnt_in diff --git a/test/SIM_stls/models/STLCheckpoint.cpp b/test/SIM_stls/models/STLCheckpoint.cpp index 1fcca9e9..45cc88f3 100644 --- a/test/SIM_stls/models/STLCheckpoint.cpp +++ b/test/SIM_stls/models/STLCheckpoint.cpp @@ -1,19 +1,34 @@ #include "sim_services/Message/include/message_proto.h" #include "STLCheckpoint.hh" - +#include "trick/memorymanager_c_intf.h" +#include +#include +#include "sim_services/UnitTest/include/trick_tests.h" /* These 2 constructors add different data to an STLCheckpoint. */ STLCheckpoint::STLCheckpoint() { return ; } -STLCheckpoint::STLCheckpoint(std::string in_name) : - vector_vector_double(4, std::vector(3)) , - vector_vector_vector_double(5, std::vector >(4, std::vector(3))) -{ +template +void compare_data_structures_with_top(T a, T b, std::string test_name) { + const char *test_suite = "STLCheckpoint"; - name = in_name ; + TRICK_EXPECT_EQ(a.size(), b.size(), test_suite, test_name.c_str()); + while (!a.empty()) { + TRICK_EXPECT_EQ(a.top(), b.top(), test_suite, test_name.c_str()); + a.pop(); + b.pop(); + } +} + +int STLCheckpoint::addData() { + dataJobRun = true; + vector_vector_double = std::vector< std::vector< double > >(4, std::vector(3)); + vector_vector_vector_double = std::vector< std::vector< std::vector< double > > >(5, std::vector >(4, std::vector(3))); + + std::cout << "Adding hardcoded data to sim" << std::endl; double_map[44.4] = 444.4 ; double_map[55.5] = 555.5 ; @@ -55,15 +70,24 @@ STLCheckpoint::STLCheckpoint(std::string in_name) : v.push_back(60) ; common_multiples.insert(std::pair< std::pair< int, int >, std::vector< int > >(p,v)) ; + p.first = 3 ; + p.second = 7 ; + v.clear() ; + v.push_back(21) ; + v.push_back(42) ; + v.push_back(84) ; + v.push_back(168) ; + common_multiples.insert(std::pair< std::pair< int, int >, std::vector< int > >(p,v)) ; + string_map[std::string("sister")] = std::string("Lisa") ; string_map[std::string("dog")] = std::string("Santa's Little Helper") ; int_multimap.insert(std::pair(44,444)) ; int_multimap.insert(std::pair(55,555)) ; int_multimap.insert(std::pair(66,666)) ; - int_multimap.insert(std::pair(44,444)) ; - int_multimap.insert(std::pair(55,555)) ; - int_multimap.insert(std::pair(66,666)) ; + int_multimap.insert(std::pair(44,4444)) ; + int_multimap.insert(std::pair(55,5555)) ; + int_multimap.insert(std::pair(66,6666)) ; string_key_multimap.insert(std::pair("four", 4)) ; string_key_multimap.insert(std::pair("five", 5)) ; @@ -118,6 +142,23 @@ STLCheckpoint::STLCheckpoint(std::string in_name) : string_set.insert("abc") ; string_set.insert("def") ; + // for (int j = 0; j < 5; j++) { + // std::vector temp; + // for (int i = j; i < 10; i++) { + // temp.push_back(i); + // } + // vector_set.insert(temp); + // } + + for (int j = 0; j < 5; j++) { + std::vector temp; + for (int i = j; i < 10; i++) { + temp.push_back(i); + } + vector_queue.push(temp); + } + + long_multiset.insert(8000) ; long_multiset.insert(4000) ; long_multiset.insert(4000) ; @@ -141,8 +182,10 @@ STLCheckpoint::STLCheckpoint(std::string in_name) : string_stack.push("with the bigger") ; string_stack.push("Gee Bees") ; - stack_vector_int.push(v) ; - stack_vector_int.push(v) ; + std::vector temp_v1 = {1, 2, 3, 4}; + std::vector temp_v2 = {5, 6, 7, 8}; + stack_vector_int.push(temp_v1) ; + stack_vector_int.push(temp_v2) ; int_queue.push(1) ; int_queue.push(2) ; @@ -164,11 +207,11 @@ STLCheckpoint::STLCheckpoint(std::string in_name) : string_priority_queue.push("an") ; string_priority_queue.push("iPhone 4") ; - queue_vector_int.push(v) ; - queue_vector_int.push(v) ; + queue_vector_int.push(temp_v1) ; + queue_vector_int.push(temp_v2) ; - priority_queue_vector_int.push(v) ; - priority_queue_vector_int.push(v) ; + priority_queue_vector_int.push(temp_v1) ; + priority_queue_vector_int.push(temp_v2) ; int_pair.first = 10 ; int_pair.second = 20 ; @@ -197,6 +240,27 @@ STLCheckpoint::STLCheckpoint(std::string in_name) : pair_pair_pair.second.first = 53 ; pair_pair_pair.second.second = 54 ; + int_vec_pair.first = 5; + int_vec_pair.second.push_back(5); + int_vec_pair.second.push_back(10); + int_vec_pair.second.push_back(15); + int_vec_pair.second.push_back(20); + + vec_int_pair.second = 5; + vec_int_pair.first.push_back(5); + vec_int_pair.first.push_back(10); + vec_int_pair.first.push_back(15); + vec_int_pair.first.push_back(20); + + vec_vec_pair.first.push_back(5); + vec_vec_pair.first.push_back(10); + vec_vec_pair.first.push_back(15); + vec_vec_pair.first.push_back(20); + vec_vec_pair.second.push_back(5); + vec_vec_pair.second.push_back(10); + vec_vec_pair.second.push_back(15); + vec_vec_pair.second.push_back(20); + vector_vector_double[0][0] = 100 ; vector_vector_double[0][1] = 101 ; vector_vector_double[0][2] = 102 ; @@ -275,30 +339,363 @@ STLCheckpoint::STLCheckpoint(std::string in_name) : vector_vector_vector_double[4][3][1] = 4010 ; vector_vector_vector_double[4][3][2] = 4011 ; - return ; + for (int i = 0; i < 10; i++) { + UserClass temp; + for (int j = 0; j < 5; j++) { + temp.a[j] = i+j; + } + temp.b = 8888888888; + temp.c = "Here is a test string"; + + // We'll just make a pointer to the same stuff + + UserClass * user_class_ptr = (UserClass *) TMM_declare_var_s("UserClass"); + for (int j = 0; j < 5; j++) { + user_class_ptr->a[j] = i+j; + } + user_class_ptr->b = 8888888888; + user_class_ptr->c = "Here is a test string"; + + temp.d = user_class_ptr; + + vec_user_simple.emplace_back(temp); + } + + for (int i = 0; i < 10; i++) { + SimpleWrapper temp_wrapper; + temp_wrapper.a = 888; + for (int j = i; j < i+10; j++) { + temp_wrapper.vec.push_back(j); + } + vec_user_defined.emplace_back(temp_wrapper); + } + + for (int i = 0; i < 10; i++) { + SimpleWrapper * temp_wrapper = (SimpleWrapper *) TMM_declare_var_s("SimpleWrapper"); + temp_wrapper->a = 888; + for (int j = i; j < i+10; j++) { + temp_wrapper->vec.push_back(j); + } + vec_user_defined_ptr.push_back(temp_wrapper); + } + + + + return 0; } -int STLCheckpoint::speak() { - //message_publish(1,"Quack!\n") ; - //message_publish(1,"double_vector: %f %f %f\n", double_vector[0], double_vector[1], double_vector[2]) ; - //message_publish(1,"vector_vector_double[1]: %f %f %f\n", - // vector_vector_double[1][0], vector_vector_double[1][1], vector_vector_double[1][2]) ; - //message_publish(1,"vector_vector_vector_double[4][2]: %f %f %f\n", - // vector_vector_vector_double[4][2][0], vector_vector_vector_double[4][2][1], vector_vector_vector_double[4][2][2]) ; - //message_publish(1,"string_vector[0]: %s\n", string_vector[0].c_str()) ; - //message_publish(1,"map_int_vector_int[1][1] = %d\n", map_int_vector_int[1][1]) ; - //message_publish(1,"gcd = %d\n", gcd[std::pair(24,30)]) ; - //message_publish(1,"common_multiples = %d\n", common_multiples[std::pair(3,5)][1]) ; - //message_publish(1,"common_multiples = %d\n", common_multiples[std::pair(3,5)][1]) ; - //message_publish(1,"int_pair_int_int.second.second = %d\n", int_pair_int_int.second.second) ; - //message_publish(1,"pair_int_int_int.first.second = %d\n", pair_int_int_int.first.second) ; - //message_publish(1,"pair_pair_pair.second.first = %d\n", pair_pair_pair.second.first) ; - //message_publish(1,"int_queue.front = %d\n", int_queue.front()) ; - //message_publish(1,"int_priority_queue.top = %d\n", int_priority_queue.top()) ; - //message_publish(1,"uint_stack.top = %d\n", uint_stack.top()) ; - //message_publish(1,"queue_vector_int.front()[3] = %d\n", queue_vector_int.front()[3]) ; - //message_publish(1,"priority_queue_vector_int.top()[2] = %d\n", priority_queue_vector_int.top()[2]) ; +int STLCheckpoint::print() { + message_publish(1,"Quack!\n") ; + message_publish(1, "Double vector size: %d", double_vector.size() ); + message_publish(1,"double_vector: %f %f %f\n", double_vector[0], double_vector[1], double_vector[2]) ; + message_publish(1,"vector_vector_double[1]: %f %f %f\n", + vector_vector_double[1][0], vector_vector_double[1][1], vector_vector_double[1][2]) ; + message_publish(1,"vector_vector_vector_double[4][2]: %f %f %f\n", + vector_vector_vector_double[4][2][0], vector_vector_vector_double[4][2][1], vector_vector_vector_double[4][2][2]) ; + message_publish(1,"string_vector[0]: %s\n", string_vector[0].c_str()) ; + message_publish(1,"map_int_vector_int[1][1] = %d\n", map_int_vector_int[1][1]) ; + message_publish(1,"gcd = %d\n", gcd[std::pair(24,30)]) ; + message_publish(1,"common_multiples = %d\n", common_multiples[std::pair(3,5)][1]) ; + message_publish(1,"common_multiples = %d\n", common_multiples[std::pair(3,5)][1]) ; + message_publish(1,"int_pair_int_int.second.second = %d\n", int_pair_int_int.second.second) ; + message_publish(1,"pair_int_int_int.first.second = %d\n", pair_int_int_int.first.second) ; + message_publish(1,"pair_pair_pair.second.first = %d\n", pair_pair_pair.second.first) ; + message_publish(1,"int_queue.front = %d\n", int_queue.front()) ; + message_publish(1,"int_priority_queue.top = %d\n", int_priority_queue.top()) ; + message_publish(1,"uint_stack.top = %d\n", uint_stack.top()) ; + message_publish(1,"queue_vector_int.front()[3] = %d\n", queue_vector_int.front()[3]) ; + message_publish(1,"priority_queue_vector_int.top()[2] = %d\n", priority_queue_vector_int.top()[2]) ; message_publish(1,"stack_vector_int.top()[1] = %d\n", stack_vector_int.top()[1]) ; return 0 ; } +int STLCheckpoint::test() { + std::cout << "Running test jobs" << std::endl; + const char *test_suite = "STLCheckpoint"; + + TRICK_EXPECT_EQ( double_vector.size(), 3, test_suite, "double_vector size"); + TRICK_EXPECT_EQ( double_vector[0], 4, test_suite, "double_vector[0]"); + TRICK_EXPECT_EQ( double_vector[1], 5, test_suite, "double_vector[1]"); + TRICK_EXPECT_EQ( double_vector[2], 6, test_suite, "double_vector[2]"); + TRICK_EXPECT_EQ( vector_vector_double[1][0], 103, test_suite, "vector_vector_double[1][0]"); + TRICK_EXPECT_EQ( vector_vector_double[1][1], 104, test_suite, "vector_vector_double[1][1]"); + TRICK_EXPECT_EQ( vector_vector_double[1][2], 105, test_suite, "vector_vector_double[1][2]"); + TRICK_EXPECT_EQ( vector_vector_vector_double[4][2][0], 4006, test_suite, "vector_vector_vector_double[4][2][0]"); + TRICK_EXPECT_EQ( vector_vector_vector_double[4][2][1], 4007, test_suite, "vector_vector_vector_double[4][2][1]"); + TRICK_EXPECT_EQ( vector_vector_vector_double[4][2][2], 4008, test_suite, "vector_vector_vector_double[4][2][2]"); + TRICK_EXPECT_EQ( string_vector[0], std::string("It"), test_suite, "string_vector"); + + TRICK_EXPECT_EQ( double_map[44.4], 444.4, test_suite, "double_map[44.4]" ); + + TRICK_EXPECT_EQ( string_data_map[7], std::string("seiben"), test_suite, "string_data_map[7]" ); + TRICK_EXPECT_EQ( string_data_map[9], std::string("neun") , test_suite, "string_data_map[9]"); + + std::vector< int > v ; + v.push_back(2) ; + v.push_back(4) ; + v.push_back(6) ; + v.push_back(8) ; + TRICK_EXPECT_EQ( map_int_vector_int[1], v, test_suite, "map_int_vector_int[1]"); + + std::pair< int , int > p ; + p.first = 24 ; + p.second = 30 ; + TRICK_EXPECT_EQ(gcd[p], 6, test_suite, "gcd[p]" ); + + p.first = 50 ; + p.second = 60 ; + std::pair< int , int > q ; + q.first = 70 ; + q.second = 80 ; + TRICK_EXPECT_EQ( map_pair_pair[p], q, test_suite, "map_pair_pair[p]" ); + + p.first = 3 ; + p.second = 5 ; + v.clear() ; + v.push_back(15) ; + v.push_back(30) ; + v.push_back(45) ; + v.push_back(60) ; + TRICK_EXPECT_EQ( common_multiples[p], v, test_suite, "common_multiples" ); + + p.first = 3 ; + p.second = 7 ; + v.clear() ; + v.push_back(21) ; + v.push_back(42) ; + v.push_back(84) ; + v.push_back(168) ; + TRICK_EXPECT_EQ( common_multiples[p], v, test_suite, "common_multiples" ); + + + TRICK_EXPECT_EQ( string_map["sister"], "Lisa", test_suite, "string_map[sister]" ); + TRICK_EXPECT_EQ( string_map["dog"], "Santa's Little Helper", test_suite, "string_map[dog]" ); + + + // The easiest way to test the multimaps is to just rebuild copies and compare + std::multimap int_multimap_copy; + int_multimap_copy.insert(std::pair(44,444)) ; + int_multimap_copy.insert(std::pair(55,555)) ; + int_multimap_copy.insert(std::pair(66,666)) ; + int_multimap_copy.insert(std::pair(44,4444)) ; + int_multimap_copy.insert(std::pair(55,5555)) ; + int_multimap_copy.insert(std::pair(66,6666)) ; + TRICK_EXPECT_EQ(int_multimap, int_multimap_copy , test_suite, "int_multimap"); + + int_multimap_copy.insert(std::pair(66,66666)) ; + TRICK_EXPECT_NE(int_multimap, int_multimap_copy , test_suite, "int_multimap_fail"); + + std::multimap string_key_multimap_copy; + string_key_multimap_copy.insert(std::pair("four", 4)) ; + string_key_multimap_copy.insert(std::pair("five", 5)) ; + string_key_multimap_copy.insert(std::pair("six", 6)) ; + string_key_multimap_copy.insert(std::pair("four", 44)) ; + string_key_multimap_copy.insert(std::pair("five", 55)) ; + string_key_multimap_copy.insert(std::pair("six", 66)) ; + TRICK_EXPECT_EQ(string_key_multimap, string_key_multimap_copy , test_suite, "string_key_multimap"); + + std::multimap string_data_multimap_copy; + string_data_multimap_copy.insert(std::pair(7, "seiben")) ; + string_data_multimap_copy.insert(std::pair(8, "acht")) ; + string_data_multimap_copy.insert(std::pair(9, "neun")) ; + string_data_multimap_copy.insert(std::pair(7, "seven")) ; + string_data_multimap_copy.insert(std::pair(8, "eight")) ; + string_data_multimap_copy.insert(std::pair(9, "nine")) ; + TRICK_EXPECT_EQ(string_data_multimap, string_data_multimap_copy , test_suite, "string_data_multimap"); + + std::multimap string_multimap_copy; + string_multimap_copy.insert(std::pair("sister","Lisa")) ; + string_multimap_copy.insert(std::pair("dog","Santa's Little Helper")) ; + string_multimap_copy.insert(std::pair("sister","Meg")) ; + string_multimap_copy.insert(std::pair("dog","Brian")) ; + TRICK_EXPECT_EQ(string_multimap, string_multimap_copy , test_suite, "string_multimap"); + + + // TODO: fix this case + // TRICK_EXPECT_EQ(vec_user_defined.size(), 10, test_suite, "vec_user_defined"); + // for (int i = 0; i < vec_user_defined.size(); i++) { + // TRICK_EXPECT_EQ(vec_user_defined[i].vec.size(), 10, test_suite, "vec_user_defined"); + // TRICK_EXPECT_EQ(vec_user_defined[i].a, 888, test_suite, "vec_user_defined"); + // for (int j = i; j < i+vec_user_defined[i].vec.size(); j++) { + // TRICK_EXPECT_EQ(vec_user_defined[i].vec[j-i], j, test_suite, "vec_user_defined"); + // } + // } + + TRICK_EXPECT_EQ(vec_user_defined_ptr.size(), 10, test_suite, "vec_user_defined_ptr"); + for (int i = 0; i < vec_user_defined_ptr.size(); i++) { + TRICK_EXPECT_EQ(vec_user_defined_ptr[i]->vec.size(), 10, test_suite, "vec_user_defined_ptr"); + TRICK_EXPECT_EQ(vec_user_defined_ptr[i]->a, 888, test_suite, "vec_user_defined_ptr"); + std::vector test_vec; + for (int j = i; j < i+vec_user_defined_ptr[i]->vec.size(); j++) { + test_vec.push_back(j); + } + TRICK_EXPECT_EQ(vec_user_defined_ptr[i]->vec, test_vec, test_suite, "vec_user_defined_ptr"); + } + + + std::vector string_vector_copy = {"It", "has", "the", "Wi-Fies"}; + TRICK_EXPECT_EQ(string_vector, string_vector_copy, test_suite, "string_vector"); + + std::list short_list_copy = {400, 401, 402}; + int list_index = 0; + TRICK_EXPECT_EQ(short_list, short_list_copy, test_suite, "short_list"); + + std::list string_list_copy = {"I", "don't", "care"}; + TRICK_EXPECT_EQ(string_list, string_list_copy, test_suite, "string_list"); + + std::deque float_deque_copy = {98.7, 65.4, 32.1}; + TRICK_EXPECT_EQ(float_deque, float_deque_copy, test_suite, "float_deque"); + + std::deque string_deque_copy = {"Welcome", "to", "PhoneMart"}; + TRICK_EXPECT_EQ(string_deque, string_deque_copy, test_suite, "string_deque"); + + std::set int_set_copy = {8000, 4000, 2000, 1000}; + TRICK_EXPECT_EQ(int_set, int_set_copy, test_suite, "int_set"); + + std::set string_set_copy = {"efg", "abc", "def"}; + TRICK_EXPECT_EQ(string_set, string_set_copy, test_suite, "string_set"); + + std::queue> vector_queue_copy; + for (int j = 0; j < 5; j++) { + std::vector temp; + for (int i = j; i < 10; i++) { + temp.push_back(i); + } + vector_queue_copy.push(temp); + } + TRICK_EXPECT_EQ(vector_queue, vector_queue_copy, test_suite, "vector_queue"); + + std::multiset long_multiset_copy = {8000, 4000, 4000, 2000, 1000}; + TRICK_EXPECT_EQ(long_multiset, long_multiset_copy, test_suite, "long_multiset"); + + std::multiset string_multiset_copy = {"efg", "abc", "def", "efg", "abc", "def"}; + TRICK_EXPECT_EQ(string_multiset, string_multiset_copy, test_suite, "string_multiset"); + + std::stack uint_stack_copy; + uint_stack_copy.push(1) ; + uint_stack_copy.push(2) ; + uint_stack_copy.push(3) ; + uint_stack_copy.push(4) ; + TRICK_EXPECT_EQ(uint_stack, uint_stack_copy, test_suite, "uint_stack"); + + std::stack string_stack_copy; + string_stack_copy.push("I") ; + string_stack_copy.push("want the one") ; + string_stack_copy.push("with the bigger") ; + string_stack_copy.push("Gee Bees") ; + TRICK_EXPECT_EQ(string_stack, string_stack_copy, test_suite, "string_stack"); + + std::stack> stack_vector_int_copy; + std::vector temp_v1 = {1, 2, 3, 4}; + std::vector temp_v2 = {5, 6, 7, 8}; + stack_vector_int_copy.emplace(temp_v1) ; + stack_vector_int_copy.emplace(temp_v2) ; + TRICK_EXPECT_EQ(stack_vector_int, stack_vector_int_copy, test_suite, "stack_vector_int"); + + std::queue int_queue_copy; + int_queue_copy.push(1) ; + int_queue_copy.push(2) ; + int_queue_copy.push(3) ; + int_queue_copy.push(4) ; + TRICK_EXPECT_EQ(int_queue, int_queue_copy, test_suite, "int_queue"); + + std::queue string_queue_copy; + string_queue_copy.push("I") ; + string_queue_copy.push("want") ; + string_queue_copy.push("an") ; + string_queue_copy.push("iPhone 4") ; + TRICK_EXPECT_EQ(string_queue, string_queue_copy, test_suite, "string_queue"); + + // Why doesn't priority_queue have the == operator but literally everything else does >:( + std::priority_queue int_priority_queue_copy; + int_priority_queue_copy.push(3) ; + int_priority_queue_copy.push(2) ; + int_priority_queue_copy.push(4) ; + int_priority_queue_copy.push(1) ; + compare_data_structures_with_top(int_priority_queue_copy, int_priority_queue, "int_priority_queue"); + + std::priority_queue string_priority_queue_copy; + string_priority_queue_copy.push("I") ; + string_priority_queue_copy.push("want") ; + string_priority_queue_copy.push("an") ; + string_priority_queue_copy.push("iPhone 4") ; + compare_data_structures_with_top(string_priority_queue_copy, string_priority_queue, "string_priority_queue"); + + std::queue> queue_vector_int_copy; + queue_vector_int_copy.emplace(temp_v1) ; + queue_vector_int_copy.emplace(temp_v2) ; + TRICK_EXPECT_EQ(queue_vector_int, queue_vector_int_copy, test_suite, "queue_vector_int"); + + std::priority_queue> priority_queue_vector_int_copy; + priority_queue_vector_int_copy.emplace(temp_v1) ; + priority_queue_vector_int_copy.emplace(temp_v2) ; + compare_data_structures_with_top(priority_queue_vector_int_copy, priority_queue_vector_int, "priority_queue_vector_int"); + + std::pair int_pair_copy(10,20); + TRICK_EXPECT_EQ(int_pair, int_pair_copy, test_suite, "int_pair"); + + std::pair< std::string , int > string_first_pair_copy ("string first", 25); + TRICK_EXPECT_EQ(string_first_pair, string_first_pair_copy, test_suite, "string_first_pair"); + + std::pair< int , std::string > string_second_pair_copy (25, "string second"); + TRICK_EXPECT_EQ(string_second_pair_copy, string_second_pair, test_suite, "string_second_pair"); + + std::pair< std::string , std::string > string_pair_copy ("pair first string", "pair second string"); + TRICK_EXPECT_EQ(string_pair_copy, string_pair, test_suite, "string_pair"); + + + std::pair< int , std::pair< int, int > > int_pair_int_int_copy; + int_pair_int_int_copy.first = 200 ; + p.first = 10 ; + p.second = 20 ; + int_pair_int_int_copy.second = p ; + TRICK_EXPECT_EQ(int_pair_int_int_copy, int_pair_int_int, test_suite, "int_pair_int_int"); + + std::pair< std::pair< int, int > , int > pair_int_int_int_copy; + p.first = 15 ; + p.second = 12 ; + pair_int_int_int_copy.first = p ; + pair_int_int_int_copy.second = 180 ; + TRICK_EXPECT_EQ(pair_int_int_int_copy, pair_int_int_int, test_suite, "pair_int_int_int"); + + std::pair< std::pair< int, int > , std::pair< int, int > > pair_pair_pair_copy ; + pair_pair_pair_copy.first.first = 51 ; + pair_pair_pair_copy.first.second = 52 ; + pair_pair_pair_copy.second.first = 53 ; + pair_pair_pair_copy.second.second = 54 ; + TRICK_EXPECT_EQ(pair_pair_pair_copy, pair_pair_pair, test_suite, "pair_pair_pair"); + + // TODO: fix this case + // Check all the int/vec combo pairs together, for laziness + // TRICK_EXPECT_EQ(int_vec_pair.first, 5, test_suite, "int_vec_pair.first"); + // TRICK_EXPECT_EQ(vec_int_pair.second, 5, test_suite, "vec_int_pair.second"); + + // TRICK_EXPECT_EQ(int_vec_pair.second.size(), 4, test_suite, "int_vec_pair.second.size"); + // TRICK_EXPECT_EQ(vec_int_pair.first.size(), 4, test_suite, "vec_int_pair.first.size"); + // TRICK_EXPECT_EQ(vec_vec_pair.first.size(), 4, test_suite, "vec_vec_pair.first.size"); + // TRICK_EXPECT_EQ(vec_vec_pair.second.size(), 4, test_suite, "vec_vec_pair.second.size"); + + // for (int i = 0; i < int_vec_pair.second.size(); i++) { + // TRICK_EXPECT_EQ(int_vec_pair.second[i], (i+1)*5, test_suite, "int_vec_pair.second elems"); + // TRICK_EXPECT_EQ(vec_int_pair.first[i], (i+1)*5, test_suite, "vec_int_pair.first elems"); + // TRICK_EXPECT_EQ(vec_vec_pair.first[i], (i+1)*5, test_suite, "vec_vec_pair.first elems"); + // TRICK_EXPECT_EQ(vec_vec_pair.second[i], (i+1)*5, test_suite, "vec_vec_pair.second elems"); + + // } + + TRICK_EXPECT_EQ(vec_user_simple.size(), 10, test_suite, "vec_user_simple") + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 5; j++) { + TRICK_EXPECT_EQ(vec_user_simple[i].a[j], i+j, test_suite, "vec_user_simple"); + TRICK_EXPECT_EQ(vec_user_simple[i].d->a[j], i+j, test_suite, "vec_user_simple"); + } + + TRICK_EXPECT_EQ(vec_user_simple[i].b, 8888888888, test_suite, "vec_user_simple"); + TRICK_EXPECT_EQ(vec_user_simple[i].d->b, 8888888888, test_suite, "vec_user_simple"); + + TRICK_EXPECT_EQ(vec_user_simple[i].c, "Here is a test string", test_suite, "vec_user_simple"); + TRICK_EXPECT_EQ(vec_user_simple[i].d->c, "Here is a test string", test_suite, "vec_user_simple"); + } + + +} diff --git a/test/SIM_stls/models/STLCheckpoint.hh b/test/SIM_stls/models/STLCheckpoint.hh index aca8de93..328615fe 100644 --- a/test/SIM_stls/models/STLCheckpoint.hh +++ b/test/SIM_stls/models/STLCheckpoint.hh @@ -18,13 +18,31 @@ #include #include + +class SimpleWrapper { + public: + int a; + std::vector vec; +}; + +class UserClass { + public: + int a[5]; + long long b; + std::string c; + UserClass * d; +}; + class STLCheckpoint { public: STLCheckpoint() ; - STLCheckpoint(std::string in_name) ; - int speak() ; + int addData() ; + int print() ; + int test() ; + + bool dataJobRun; std::string name ; @@ -54,6 +72,10 @@ class STLCheckpoint { std::set< int > int_set ; std::set< std::string > string_set ; + // std::set< std::vector > vector_set; + + std::queue< std::vector > vector_queue; + std::multiset< long > long_multiset ; std::multiset< std::string > string_multiset ; @@ -76,6 +98,10 @@ class STLCheckpoint { std::pair< int , std::string > string_second_pair ; std::pair< std::string , std::string > string_pair ; + std::pair< int, std::vector > int_vec_pair; + std::pair< std::vector, int > vec_int_pair; + std::pair< std::vector, std::vector > vec_vec_pair; + std::pair< int , std::pair< int, int > > int_pair_int_int ; std::pair< std::pair< int, int > , int > pair_int_int_int ; @@ -84,6 +110,12 @@ class STLCheckpoint { std::vector< std::vector< double > > vector_vector_double ; std::vector< std::vector< std::vector< double > > > vector_vector_vector_double ; //std::vector< std::list< double > > vector_list_double ; + + std::vector vec_user_simple; + std::vector vec_user_defined; + std::vector vec_user_defined_ptr; + + } ; #endif diff --git a/test/makefile b/test/makefile index 5ef52f11..f68e4f08 100644 --- a/test/makefile +++ b/test/makefile @@ -38,6 +38,9 @@ SIMS_TO_COMPILE_AND_RUN = \ SIM_threads \ SIM_trickified +# SIM_stls will run twice. First run is RUN_test/setup.py, which is added as a dependency to test in its S_overrides.mk file +# The second run is the normal RUN_test/unit_test.py which is run through this makefile. + # Sims with problems, no purpose, or maybe shouldn't be a test # SIM_leaks ( should be deleted ) # SIM_dynamic_sim_object ( not running, class won't instantiate ) diff --git a/trick_source/sim_services/CheckPointRestart/CheckPointRestart.cpp b/trick_source/sim_services/CheckPointRestart/CheckPointRestart.cpp index 4cf37280..002f1289 100644 --- a/trick_source/sim_services/CheckPointRestart/CheckPointRestart.cpp +++ b/trick_source/sim_services/CheckPointRestart/CheckPointRestart.cpp @@ -296,6 +296,11 @@ void Trick::CheckPointRestart::load_checkpoint(std::string file_name) { load_checkpoint_file_name = file_name ; } +void Trick::CheckPointRestart::load_checkpoint(std::string file_name, bool stls_on) { + trick_MM->set_restore_stls_default(stls_on); + load_checkpoint(file_name); +} + int Trick::CheckPointRestart::load_checkpoint_job() { JobData * curr_job ; diff --git a/trick_source/sim_services/CheckPointRestart/CheckPointRestart_c_intf.cpp b/trick_source/sim_services/CheckPointRestart/CheckPointRestart_c_intf.cpp index 20127bcc..71215aef 100644 --- a/trick_source/sim_services/CheckPointRestart/CheckPointRestart_c_intf.cpp +++ b/trick_source/sim_services/CheckPointRestart/CheckPointRestart_c_intf.cpp @@ -158,6 +158,30 @@ extern "C" int load_checkpoint( const char * file_name ) { } +/** + * @relates Trick::CheckPointRestart + * @copydoc Trick::CheckPointRestart::load_checkpoint + */ +extern "C" int load_checkpoint_stls( const char * file_name, int on_off ) { + + the_cpr->load_checkpoint(std::string(file_name), (bool) on_off) ; + + return(0) ; + +} + +/** + * @relates Trick::CheckPointRestart + * @copydoc Trick::CheckPointRestart::load_checkpoint + */ +extern "C" int load_checkpoint_objects( const char * file_name ) { + + the_cpr->load_checkpoint(std::string(file_name)) ; + + return(0) ; + +} + /** * @relates Trick::CheckPointRestart * @copydoc Trick::CheckPointRestart::load_checkpoint_job diff --git a/trick_source/sim_services/MemoryManager/MemoryManager.cpp b/trick_source/sim_services/MemoryManager/MemoryManager.cpp index a4dc37df..f6c5c497 100644 --- a/trick_source/sim_services/MemoryManager/MemoryManager.cpp +++ b/trick_source/sim_services/MemoryManager/MemoryManager.cpp @@ -7,7 +7,7 @@ Trick::MemoryManager * trick_MM = NULL; // CLASS VARIABLE INITIALIZATION int Trick::MemoryManager::instance_count = 0; - +bool Trick::MemoryManager::restore_stls_default = true; // CONSTRUCTOR Trick::MemoryManager::MemoryManager() diff --git a/trick_source/sim_services/MemoryManager/MemoryManager_C_Intf.cpp b/trick_source/sim_services/MemoryManager/MemoryManager_C_Intf.cpp index 48511468..527ded9e 100644 --- a/trick_source/sim_services/MemoryManager/MemoryManager_C_Intf.cpp +++ b/trick_source/sim_services/MemoryManager/MemoryManager_C_Intf.cpp @@ -364,7 +364,7 @@ extern "C" void TMM_write_checkpoint(const char* filename) { */ extern "C" int TMM_read_checkpoint(const char* filename) { if (trick_MM != NULL) { - return ( trick_MM->read_checkpoint( filename)); + return ( trick_MM->read_checkpoint( filename )); } else { Trick::MemoryManager::emitError("TMM_read_checkpoint() called before MemoryManager instantiation.\n") ; return(1); @@ -377,7 +377,7 @@ extern "C" int TMM_read_checkpoint(const char* filename) { */ extern "C" int TMM_read_checkpoint_from_string(const char* str) { if (trick_MM != NULL) { - return ( trick_MM->read_checkpoint_from_string( str)); + return ( trick_MM->read_checkpoint_from_string( str )); } else { Trick::MemoryManager::emitError("TMM_read_checkpoint_from_string() called before MemoryManager instantiation.\n") ; return(1); @@ -390,13 +390,22 @@ extern "C" int TMM_read_checkpoint_from_string(const char* str) { */ extern "C" int TMM_init_from_checkpoint(const char* filename) { if (trick_MM != NULL) { - return ( trick_MM->init_from_checkpoint( filename)); + return ( trick_MM->init_from_checkpoint( filename )); } else { Trick::MemoryManager::emitError("TMM_init_from_checkpoint() called before MemoryManager instantiation.\n") ; return(1); } } +extern "C" int TMM_set_stl_restore (int on_off) { + if (trick_MM != NULL) { + return ( trick_MM->set_restore_stls_default( (bool) on_off )); + } else { + Trick::MemoryManager::emitError("TMM_set_stl_restore() called before MemoryManager instantiation.\n") ; + return(1); + } +} + /** @relates Trick::MemoryManager This is the C Language version of Trick::MemoryManager::add_shared_library_symbols( filename). diff --git a/trick_source/sim_services/MemoryManager/MemoryManager_restore.cpp b/trick_source/sim_services/MemoryManager/MemoryManager_restore.cpp index afdced79..51f7106b 100644 --- a/trick_source/sim_services/MemoryManager/MemoryManager_restore.cpp +++ b/trick_source/sim_services/MemoryManager/MemoryManager_restore.cpp @@ -7,7 +7,12 @@ #include "trick/MemoryManager.hh" #include "trick/ClassicCheckPointAgent.hh" -int Trick::MemoryManager::read_checkpoint( std::istream *is, bool do_restore_stls /* default is false */) { +int Trick::MemoryManager::set_restore_stls_default (bool on_off) { + restore_stls_default = on_off; + return 0; +} + +int Trick::MemoryManager::read_checkpoint( std::istream *is, bool do_restore_stl) { ALLOC_INFO_MAP::iterator pos; ALLOC_INFO* alloc_info; @@ -23,7 +28,7 @@ int Trick::MemoryManager::read_checkpoint( std::istream *is, bool do_restore_stl // Search for stls and restore them - if(do_restore_stls) { + if(do_restore_stl) { for ( pos=alloc_info_map.begin() ; pos!=alloc_info_map.end() ; pos++ ) { restore_stls(pos->second) ; } @@ -59,12 +64,12 @@ int Trick::MemoryManager::read_checkpoint( std::istream *is, bool do_restore_stl return(0); } -int Trick::MemoryManager::read_checkpoint(const char* filename ) { +int Trick::MemoryManager::read_checkpoint( const char* filename, bool restore_stls ) { // Create a stream from the named file. std::ifstream infile(filename , std::ios::in); if (infile.is_open()) { - return ( read_checkpoint( &infile, true )) ; + return ( read_checkpoint( &infile, restore_stls )) ; } else { std::stringstream message; message << "Couldn't open \"" << filename << "\"." ; @@ -73,7 +78,7 @@ int Trick::MemoryManager::read_checkpoint(const char* filename ) { return 1; } -int Trick::MemoryManager::read_checkpoint_from_string(const char* s ) { +int Trick::MemoryManager::read_checkpoint_from_string(const char* s, bool restore_stls ) { // Create a stream from the string argument. std::stringstream ss; @@ -86,14 +91,14 @@ int Trick::MemoryManager::read_checkpoint_from_string(const char* s ) { */ ss << ";" ; } - return ( read_checkpoint( &ss )); + return ( read_checkpoint( &ss, restore_stls)); } else { emitError("Checkpoint string is NULL.") ; } return 1; } -int Trick::MemoryManager::init_from_checkpoint( std::istream *is) { +int Trick::MemoryManager::init_from_checkpoint(const char* filename, bool restore_stls ) { if (debug_level) { std::cout << std::endl << "Initializing from checkpoint" << std::endl; @@ -108,7 +113,8 @@ int Trick::MemoryManager::init_from_checkpoint( std::istream *is) { std::cout.flush(); } - read_checkpoint( is); + read_checkpoint( filename, restore_stls); + if (debug_level) { std::cout << std::endl << "Initialization from checkpoint finished." << std::endl; @@ -118,7 +124,7 @@ int Trick::MemoryManager::init_from_checkpoint( std::istream *is) { return 0 ; } -int Trick::MemoryManager::init_from_checkpoint(const char* filename ) { +int Trick::MemoryManager::init_from_checkpoint( std::istream *is, bool restore_stls) { if (debug_level) { std::cout << std::endl << "Initializing from checkpoint" << std::endl; @@ -128,12 +134,7 @@ int Trick::MemoryManager::init_from_checkpoint(const char* filename ) { reset_memory(); - if (debug_level) { - std::cout << std::endl << "- Reading checkpoint." << std::endl; - std::cout.flush(); - } - - read_checkpoint( filename); + read_checkpoint( is, restore_stls ); if (debug_level) { std::cout << std::endl << "Initialization from checkpoint finished." << std::endl; diff --git a/trick_source/sim_services/MemoryManager/test/.gitignore b/trick_source/sim_services/MemoryManager/test/.gitignore index 0495036d..ac11cb7b 100644 --- a/trick_source/sim_services/MemoryManager/test/.gitignore +++ b/trick_source/sim_services/MemoryManager/test/.gitignore @@ -18,3 +18,5 @@ MM_strdup_unittest MM_write_checkpoint MM_write_checkpoint_hexfloat MM_write_var_unittest +MM_stl_checkpoint +MM_stl_restore \ No newline at end of file diff --git a/trick_source/sim_services/MemoryManager/test/MM_read_checkpoint.cc b/trick_source/sim_services/MemoryManager/test/MM_read_checkpoint.cc index fc251cc4..8d1a0619 100644 --- a/trick_source/sim_services/MemoryManager/test/MM_read_checkpoint.cc +++ b/trick_source/sim_services/MemoryManager/test/MM_read_checkpoint.cc @@ -262,8 +262,74 @@ TEST_F(MM_read_checkpoint, 2D_char_array) { EXPECT_EQ(result, 0); } - - - - +} + +TEST_F(MM_read_checkpoint, WrappedStl) { + memmgr->read_checkpoint_from_string( + "VectorWrapper my_vec;" + "int my_vec_vec[4];" + "clear_all_vars();" + "my_vec_vec = " + "{10, 20, 30, 40};"); + + VectorWrapper * vector = (VectorWrapper *) memmgr->ref_attributes("my_vec")->address; + + ASSERT_EQ(vector->vec.size(), 4); + for (int i = 0; i < 4; i++) { + EXPECT_EQ(vector->vec[i], (i+1)*10); + } +} + +TEST_F(MM_read_checkpoint, WrappedStlPreDeclared) { + VectorWrapper * vector = (VectorWrapper *) memmgr->declare_var("VectorWrapper my_vec"); + + memmgr->read_checkpoint_from_string( + "int my_vec_vec[4];" + "clear_all_vars();" + "my_vec_vec = " + "{10, 20, 30, 40};"); + + ASSERT_EQ(vector->vec.size(), 4); + for (int i = 0; i < 4; i++) { + EXPECT_EQ(vector->vec[i], (i+1)*10); + } +} + +TEST_F(MM_read_checkpoint, encapsulated_stl_test) { + + // std::vector my_vector; + Foo * my_foo_ptr = (Foo *) memmgr->declare_var("Foo my_foo"); + + memmgr->read_checkpoint_from_string( + "int my_foo_c[3];" + "my_foo.a = 5;" + "my_foo.b = 5.5;" + "my_foo_c = {1, 2, 3, 4};" + ); + + EXPECT_EQ(my_foo_ptr->a, 5); + EXPECT_EQ(my_foo_ptr->b, 5.5); + + ASSERT_EQ(my_foo_ptr->c.size(), 3); + EXPECT_EQ(my_foo_ptr->c[0], 1); + EXPECT_EQ(my_foo_ptr->c[1], 2); + EXPECT_EQ(my_foo_ptr->c[2], 3); +} + +TEST_F(MM_read_checkpoint, encapsulated_stl_test_stl_disabled) { + + // std::vector my_vector; + Foo * my_foo_ptr = (Foo *) memmgr->declare_var("Foo my_foo"); + + memmgr->read_checkpoint_from_string( + "int my_foo_c[3];" + "my_foo.a = 5;" + "my_foo.b = 5.5;" + "my_foo_c = {1, 2, 3, 4};", false); + + EXPECT_EQ(my_foo_ptr->a, 5); + EXPECT_EQ(my_foo_ptr->b, 5.5); + + // c should not be restored + ASSERT_EQ(my_foo_ptr->c.size(), 0); } diff --git a/trick_source/sim_services/MemoryManager/test/MM_stl_checkpoint.cc b/trick_source/sim_services/MemoryManager/test/MM_stl_checkpoint.cc new file mode 100644 index 00000000..2640e63f --- /dev/null +++ b/trick_source/sim_services/MemoryManager/test/MM_stl_checkpoint.cc @@ -0,0 +1,1121 @@ +#include "gtest/gtest.h" +#define private public + +#include "trick/MemoryManager.hh" +#include "trick/memorymanager_c_intf.h" +#include "MM_test.hh" +#include "MM_stl_testbed.hh" + +/* + This tests the implementations of checkpoint_stl + */ +class MM_stl_checkpoint : public ::testing::Test { + +protected: + Trick::MemoryManager *memmgr; + + MM_stl_checkpoint() { + try { + memmgr = new Trick::MemoryManager; + } catch (std::logic_error e) { + memmgr = NULL; + } + } + ~MM_stl_checkpoint() { + delete memmgr; + } + void SetUp() {} + void TearDown() {} +}; + +template +void validate_single (Trick::MemoryManager * memmgr, std::string object_name, std::string var_name, T expected_data) { + std::string temp_name = object_name + "_" + var_name; + ASSERT_TRUE(memmgr->var_exists(temp_name) == 1); + + REF2 * data_ref = memmgr->ref_attributes(temp_name.c_str()); + T * data = (T *) data_ref->address; + + ASSERT_TRUE(data != NULL); + + EXPECT_EQ(*data, expected_data); + + free (data_ref); +} + +template +void validate_temp_sequence (Trick::MemoryManager * memmgr, std::string object_name, std::string var_name, std::vector expected_data) { + std::string temp_name = object_name + "_" + var_name; + ASSERT_TRUE(memmgr->var_exists(temp_name) == 1); + + REF2 * data_ref = memmgr->ref_attributes(temp_name.c_str()); + T * data = (T *) data_ref->address; + + ASSERT_TRUE(data != NULL); + EXPECT_EQ(data_ref->attr->num_index, 1); + ASSERT_EQ(data_ref->attr->index[0].size, expected_data.size()); + + for (int i = 0; i < expected_data.size(); i++) { + EXPECT_EQ(data[i], expected_data[i]); + } + + free (data_ref); + +} + +void validate_links (Trick::MemoryManager * memmgr, std::string object_name, std::string top_level_name, std::vector lengths) { + std::string temp_name = object_name + "_" + top_level_name; + ASSERT_TRUE(memmgr->var_exists(temp_name) == 1); + + REF2 * data_ref = memmgr->ref_attributes(temp_name.c_str()); + std::string * data = (std::string *) data_ref->address; + ASSERT_EQ(data_ref->attr->index[0].size, lengths.size()); + + for (int i = 0; i < lengths.size(); i++) { + std::string inner_name = temp_name + "_" + std::to_string(i); + EXPECT_EQ(inner_name, data[i]); + REF2 * ref = memmgr->ref_attributes(inner_name.c_str()); + ASSERT_EQ(ref->attr->index[0].size, lengths[i]); + } +} + +void validate_links_pairs (Trick::MemoryManager * memmgr, std::string object_name, std::string top_level_name, int num_pairs) { + std::string temp_name = object_name + "_" + top_level_name; + ASSERT_TRUE(memmgr->var_exists(temp_name) == 1); + + REF2 * data_ref = memmgr->ref_attributes(temp_name.c_str()); + std::string * data = (std::string *) data_ref->address; + ASSERT_EQ(data_ref->attr->index[0].size, num_pairs); + + for (int i = 0; i < num_pairs; i++) { + std::string inner_name = temp_name + "_" + std::to_string(i); + EXPECT_EQ(inner_name, data[i]); + std::string first_name = inner_name + "_first"; + std::string second_name = inner_name + "_second"; + + ASSERT_TRUE(memmgr->var_exists(first_name) == 1); + ASSERT_TRUE(memmgr->var_exists(second_name) == 1); + } +} + +template +void validate_temp_set (Trick::MemoryManager * memmgr, std::string object_name, std::string var_name, std::set expected_data) { + std::string temp_name = object_name + "_" + var_name; + ASSERT_TRUE(memmgr->var_exists(temp_name) == 1); + + REF2 * data_ref = memmgr->ref_attributes(temp_name.c_str()); + T * data = (T *) data_ref->address; + + ASSERT_TRUE(data != NULL); + EXPECT_EQ(data_ref->attr->num_index, 1); + ASSERT_EQ(data_ref->attr->index[0].size, expected_data.size()); + + std::set reconstructed; + for (int i = 0; i < expected_data.size(); i++) { + reconstructed.insert(data[i]); + } + + EXPECT_EQ(reconstructed, expected_data); + + free (data_ref); + +} + + +template +void validate_temp_pair (Trick::MemoryManager * memmgr, std::string object_name, std::string var_name, std::pair expected_data) { + std::string temp_name = object_name + "_" + var_name; + std::string first_name = temp_name + "_first"; + std::string second_name = temp_name + "_second"; + + ASSERT_TRUE(memmgr->var_exists(first_name) == 1); + ASSERT_TRUE(memmgr->var_exists(second_name) == 1); + + REF2 * first_data_ref = memmgr->ref_attributes(first_name.c_str()); + First * first_data = (First *) first_data_ref->address; + + REF2 * second_data_ref = memmgr->ref_attributes(second_name.c_str()); + Second * second_data = (Second *) second_data_ref->address; + + ASSERT_TRUE(first_data != NULL); + ASSERT_TRUE(second_data != NULL); + + EXPECT_EQ(expected_data.first, *first_data); + EXPECT_EQ(expected_data.second, *second_data); + + free (first_data_ref); + free (second_data_ref); +} + + +template +void validate_temp_map (Trick::MemoryManager * memmgr, std::string object_name, std::string var_name, std::map expected_data) { + std::string temp_name = object_name + "_" + var_name; + std::string keys_name = temp_name + "_keys"; + std::string vals_name = temp_name + "_data"; + + ASSERT_TRUE(memmgr->var_exists(keys_name) == 1); + ASSERT_TRUE(memmgr->var_exists(vals_name) == 1); + + REF2 * keys_data_ref = memmgr->ref_attributes(keys_name.c_str()); + Key * keys_data = (Key *) keys_data_ref->address; + + REF2 * vals_data_ref = memmgr->ref_attributes(vals_name.c_str()); + Val * vals_data = (Val *) vals_data_ref->address; + + ASSERT_TRUE(keys_data != NULL); + ASSERT_TRUE(vals_data != NULL); + + EXPECT_EQ(keys_data_ref->attr->num_index, 1); + EXPECT_EQ(vals_data_ref->attr->num_index, 1); + + ASSERT_EQ(keys_data_ref->attr->index[0].size, expected_data.size()); + ASSERT_EQ(vals_data_ref->attr->index[0].size, expected_data.size()); + + // This is a little tricky - i don't think we can rely on the order being + // the same, but want to check that the data is exactly the same. + // Lazy way - make a set of all the keys that were accessed in our expected + // map, and make sure that the size is the same. + std::set keySet; + for (int i = 0; i < expected_data.size(); i++) { + Key k = keys_data[i]; + Val v = vals_data[i]; + + // To check for completeness, like if we accidentally wrote out duplicate keys but the size was the same + keySet.insert(k); + + // These should be a pair in the expected map + auto result = expected_data.find(k); + ASSERT_TRUE(result != expected_data.end()); + EXPECT_EQ(result->second, v); + } + + ASSERT_EQ(keySet.size(), expected_data.size()); + + free (keys_data_ref); + free (vals_data_ref); +} + +// Vectors + +TEST_F(MM_stl_checkpoint, i_vec ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(10); + + // Prepare the STL to be tested + for (int i = 0; i < test_data.size(); i++) { + testbed->i_vec.push_back(test_data[i]); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.i_vec")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->i_vec, "my_alloc", vec_attr->name) ; + + // ASSERT + validate_temp_sequence(memmgr, std::string("my_alloc"), std::string("i_vec"), test_data); +} + +TEST_F(MM_stl_checkpoint, i_s_vec ) { + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector> test_data; + for (int i = 0; i < 10; i++) { + std::vector test_data_inner = get_test_data(10); + testbed->i_s_vec.emplace_back(test_data_inner); + test_data.emplace_back(test_data_inner); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.i_s_vec")->attr; + + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->i_s_vec, "my_alloc", vec_attr->name) ; + + for (int i = 0; i < test_data.size(); i++) { + std::string var_name = "i_s_vec_" + std::to_string(i); + validate_temp_sequence(memmgr, std::string("my_alloc"), var_name, test_data[i]); + } + + validate_links(memmgr, std::string("my_alloc"), std::string("i_s_vec"), std::vector(10, 10)); +} + +TEST_F(MM_stl_checkpoint, string_vec ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(20); + for (int i = 0; i < test_data.size(); i++) { + testbed->string_vec.emplace_back(test_data[i]); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.string_vec")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->string_vec, "my_alloc", vec_attr->name) ; + std::string var_name = "string_vec"; + + // ASSERT + validate_temp_sequence(memmgr, std::string("my_alloc"), std::string("string_vec"), test_data); +} + +TEST_F(MM_stl_checkpoint, s_vec ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(20); + for (int i = 0; i < test_data.size(); i+=2) { + testbed->s_vec.emplace_back(test_data[i], test_data[i+1]); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.s_vec")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->s_vec, "my_alloc", vec_attr->name) ; + + // ASSERT + for (int i = 0; i < test_data.size()/2; i++) { + std::string var_name = "s_vec_" + std::to_string(i); + validate_temp_pair(memmgr, std::string("my_alloc"), var_name, std::pair(test_data[i*2], test_data[i*2+1])); + } + + validate_links_pairs(memmgr, std::string("my_alloc"), std::string("s_vec"), test_data.size()/2); +} + + +// Pairs +// TODO: Nested sequences do not work + +TEST_F(MM_stl_checkpoint, i_i_pair ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(2); + testbed->i_i_pair.first = test_data[0]; + testbed->i_i_pair.second = (float) test_data[1]; + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.i_i_pair")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->i_i_pair, "my_alloc", vec_attr->name) ; + + // ASSERT + validate_temp_pair(memmgr, std::string("my_alloc"), vec_attr->name, std::pair(test_data[0], test_data[1])); +} + +TEST_F(MM_stl_checkpoint, DISABLED_i_s_pair ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_key = get_test_data(1); + std::vector test_val = get_test_data(20); + + testbed->i_s_pair.first = test_key[0]; + for (bool val : test_val) { + testbed->i_s_pair.second.push(val); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.i_s_pair")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->i_s_pair, "my_alloc", vec_attr->name) ; + + // ASSERT + validate_links(memmgr, std::string("my_alloc"), std::string("i_s_pair_second"), std::vector(1, test_val.size())); + validate_temp_sequence(memmgr, std::string("my_alloc"), std::string("i_s_pair_second_inner"), test_val); + // Oh boy this one actually doesn't work!!!!! + // TODO: fix i_s_pair +} + +TEST_F(MM_stl_checkpoint, DISABLED_s_i_pair ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_val = get_test_data(1); + std::vector test_key = get_test_data(20); + + testbed->s_i_pair.second = test_val[0]; + for (bool val : test_key) { + testbed->s_i_pair.first.push(val); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.s_i_pair")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->s_i_pair, "my_alloc", vec_attr->name) ; + + // ASSERT + validate_temp_sequence(memmgr, std::string("my_alloc"), std::string("s_i_pair_first_inner"), test_key); + + // Oh boy this one actually doesn't work!!!!! + // Same as the other one + // TODO: fix s_i_pair +} + + + +TEST_F(MM_stl_checkpoint, DISABLED_i_v_pair ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_key = get_test_data(1); + std::vector test_val = get_test_data(20); + + testbed->i_v_pair.first = test_key[0]; + for (bool val : test_val) { + testbed->i_v_pair.second.push_back(val); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.i_v_pair")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->i_v_pair, "my_alloc", vec_attr->name) ; + + // ASSERT + validate_temp_sequence(memmgr, std::string("my_alloc"), std::string("i_v_pair_second"), test_val); + + // Oh boy this one actually doesn't work!!!!! + // TODO: fix i_s_pair +} + + +TEST_F(MM_stl_checkpoint, pair_pair ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + testbed->pair_pair.first.first = 1; + testbed->pair_pair.first.second = 2; + + testbed->pair_pair.second = 3; + + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.pair_pair")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->pair_pair, "my_alloc", vec_attr->name) ; + + // ASSERT + validate_single(memmgr, std::string("my_alloc"), std::string("pair_pair_second"), 3); + validate_temp_pair(memmgr, std::string("my_alloc"), std::string("pair_pair_first"), std::pair(1, 2)); +} + + + +// Maps + +TEST_F(MM_stl_checkpoint, i_i_map ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_keys = get_test_data(20); + std::vector test_vals = get_test_data(20); + std::map test_map; + + for (int i = 0; i < test_keys.size(); i++) { + test_map[test_keys[i]] = test_vals[i]; + testbed->i_i_map[test_keys[i]] = test_vals[i]; + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.i_i_map")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->i_i_map, "my_alloc", vec_attr->name) ; + + // ASSERT + validate_temp_map(memmgr, std::string("my_alloc"), std::string("i_i_map"), test_map); +} + +TEST_F(MM_stl_checkpoint, i_s_map ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_keys = get_test_data(3); + std::vector test_strings = get_test_data(20); + std::map> test_map; + + int start_index = 0; + std::vector lengths = {7, 1, 12}; + for (int i = 0; i < lengths.size(); i++) { + for (int j = 0; j < lengths[i]; j++) { + testbed->i_s_map[test_keys[i]].push(test_strings[start_index + j]); + test_map[test_keys[i]].push(test_strings[start_index + j]); + } + start_index += lengths[i]; + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.i_s_map")->attr; + std::set keyset (test_keys.begin(), test_keys.end()); + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->i_s_map, "my_alloc", vec_attr->name) ; + + // ASSERT + validate_temp_set(memmgr, std::string("my_alloc"), std::string("i_s_map_keys"), keyset); + + std::vector sorted_lengths; + int i = 0; + for (auto it : test_map) { + std::vector expected_data; + while (!it.second.empty()) { + expected_data.push_back(it.second.top()); + it.second.pop(); + } + std::string var_name = "i_s_map_data_" + std::to_string(i++); + validate_temp_sequence(memmgr, std::string("my_alloc"), var_name, expected_data); + sorted_lengths.push_back(expected_data.size()); + } + + validate_links(memmgr, std::string("my_alloc"), std::string("i_s_map_data"), sorted_lengths); +} + + +TEST_F(MM_stl_checkpoint, s_i_map ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_keys = get_test_data(20); + std::vector test_vals = get_test_data(3); + + std::map, std::string> test_map; + + std::vector lengths = {7, 1, 12}; + + int start_index = 0; + for (int i = 0; i < lengths.size(); i++) { + test_map[std::set(test_keys.begin()+start_index, test_keys.begin()+start_index+lengths[i])] = test_vals[i]; + testbed->s_i_map[std::set(test_keys.begin()+start_index, test_keys.begin()+start_index+lengths[i])] = test_vals[i]; + start_index += lengths[i]; + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.s_i_map")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->s_i_map, "my_alloc", vec_attr->name) ; + + + // the ordering of the map is making life hard + // ASSERT + int i = 0; + std::vector values_in_the_right_order; + std::vector lengths_in_the_right_order; + + for (auto it : test_map) { + std::string var_name = "s_i_map_keys_" + std::to_string(i++); + validate_temp_set(memmgr, std::string("my_alloc"), var_name, it.first); + values_in_the_right_order.push_back(it.second); + lengths_in_the_right_order.push_back(it.first.size()); + } + validate_links(memmgr, std::string("my_alloc"), std::string("s_i_map_keys"), lengths_in_the_right_order); + validate_temp_sequence(memmgr, std::string("my_alloc"), std::string("s_i_map_data"), values_in_the_right_order); +} + +TEST_F(MM_stl_checkpoint, s_s_map ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_keys = get_test_data(20); + std::vector test_vals = get_test_data(40); + + std::map, std::vector> test_map; + + for (int i = 0; i < 10; i++) { + testbed->s_s_map[std::pair(test_keys[i*2], test_keys[(i*2)+1])] = std::vector(test_vals.begin() + (i*4), test_vals.begin() + (i+1)*4); + test_map[std::pair(test_keys[i*2], test_keys[(i*2)+1])] = std::vector(test_vals.begin() + (i*4), test_vals.begin() + (i+1)*4); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.s_s_map")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->s_s_map, "my_alloc", vec_attr->name) ; + + // the ordering of the map is making life hard + // ASSERT + int i = 0; + std::vector data_lengths; + for (auto it : test_map) { + std::pair expected_key = it.first; + std::string key_name = "s_s_map_keys_" + std::to_string(i); + validate_temp_pair(memmgr, std::string("my_alloc"), key_name, expected_key); + + std::vector expected_data = it.second; + std::string data_name = "s_s_map_data_" + std::to_string(i); + validate_temp_sequence(memmgr, std::string("my_alloc"), data_name, expected_data); + + data_lengths.push_back(expected_data.size()); + i++; + } + + validate_links_pairs(memmgr, std::string("my_alloc"), std::string("s_s_map_keys"), test_map.size()); + validate_links(memmgr, std::string("my_alloc"), std::string("s_s_map_data"), data_lengths); +} + + +// Queue + + +TEST_F(MM_stl_checkpoint, i_queue ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(10); + + // Prepare the STL to be tested + for (int i = 0; i < test_data.size(); i++) { + testbed->i_queue.push(test_data[i]); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.i_queue")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->i_queue, "my_alloc", vec_attr->name) ; + + // ASSERT + validate_temp_sequence(memmgr, std::string("my_alloc"), std::string("i_queue"), test_data); +} + +TEST_F(MM_stl_checkpoint, s_queue ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_first = get_test_data(10); + std::vector test_second = get_test_data(10); + + // Prepare the STL to be tested + for (int i = 0; i < test_first.size(); i++) { + testbed->s_queue.push(std::pair(test_first[i], test_second[i])); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.s_queue")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->s_queue, "my_alloc", vec_attr->name) ; + + // ASSERT + for (int i = 0; i < test_first.size(); i++) { + std::string var_name = "s_queue_" + std::to_string(i); + validate_temp_pair(memmgr, std::string("my_alloc"), var_name, std::pair(test_first[i], test_second[i])); + } + validate_links_pairs(memmgr, std::string("my_alloc"), std::string("s_queue"), test_first.size()); +} + + +TEST_F(MM_stl_checkpoint, nested_list_queue ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(10); + std::vector list_sizes = {2, 7, 1}; + // Prepare the STL to be tested + + int data_index = 0; + for (int i = 0; i < list_sizes.size(); i++) { + testbed->nested_list_queue.push(std::list(test_data.begin() + data_index, test_data.begin() + data_index + list_sizes[i])); + data_index += list_sizes[i]; + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.nested_list_queue")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->nested_list_queue, "my_alloc", vec_attr->name) ; + + // ASSERT + data_index = 0; + for (int i = 0; i < list_sizes.size(); i++) { + std::string var_name = "nested_list_queue_" + std::to_string(i); + validate_temp_sequence(memmgr, std::string("my_alloc"), var_name, std::vector(test_data.begin() + data_index, test_data.begin() + data_index + list_sizes[i])); + data_index += list_sizes[i]; + } + + validate_links(memmgr, std::string("my_alloc"), std::string("nested_list_queue"), list_sizes); +} + + + +// Stacks + +TEST_F(MM_stl_checkpoint, i_stack ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(10); + + // Prepare the STL to be tested + for (int i = 0; i < test_data.size(); i++) { + testbed->i_stack.push(test_data[i]); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.i_stack")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->i_stack, "my_alloc", vec_attr->name) ; + + // ASSERT + // Have the pass the test data in reverse order + validate_temp_sequence(memmgr, std::string("my_alloc"), std::string("i_stack"), std::vector (test_data.rbegin(), test_data.rend())); +} + +TEST_F(MM_stl_checkpoint, s_stack ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_first = get_test_data(10); + std::vector test_second = get_test_data(10); + + // Prepare the STL to be tested + for (int i = 0; i < test_first.size(); i++) { + testbed->s_stack.push(std::pair(test_first[i], test_second[i])); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.s_stack")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->s_stack, "my_alloc", vec_attr->name) ; + + // ASSERT + for (int i = 0; i < test_first.size(); i++) { + std::string var_name = "s_stack_" + std::to_string(i); + // data in reverse order + validate_temp_pair(memmgr, std::string("my_alloc"), var_name, std::pair(test_first[test_first.size()-1-i], test_second[test_first.size()-1-i])); + } + + validate_links_pairs(memmgr, std::string("my_alloc"), std::string("s_stack"), test_first.size()); +} + + +TEST_F(MM_stl_checkpoint, nested_list_stack ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(10); + std::vector list_sizes = {2, 7, 1}; + // Prepare the STL to be tested + + int data_index = 0; + for (int i = 0; i < list_sizes.size(); i++) { + testbed->nested_list_stack.push(std::list(test_data.begin() + data_index, test_data.begin() + data_index + list_sizes[i])); + data_index += list_sizes[i]; + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.nested_list_stack")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->nested_list_stack, "my_alloc", vec_attr->name) ; + + // ASSERT + data_index = 0; + for (int i = 0; i < list_sizes.size(); i++) { + // reverse data - just go through the lists backwards + std::string var_name = "nested_list_stack_" + std::to_string(list_sizes.size()-1-i); + validate_temp_sequence(memmgr, std::string("my_alloc"), var_name, std::vector(test_data.begin() + data_index, test_data.begin() + data_index + list_sizes[i])); + data_index += list_sizes[i]; + } + + validate_links(memmgr, std::string("my_alloc"), std::string("nested_list_stack"), std::vector(list_sizes.rbegin(), list_sizes.rend())); +} + + + +// Sets TODO: No support for nested STLs in sets. +// These will fail to compile + + +TEST_F(MM_stl_checkpoint, DISABLED_i_set ) { + // ARRANGE + // Make a testbed + // STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + // // Likely to be some repeats in here + // std::vector test_data = get_test_data(1000); + + // // Prepare the STL to be tested + // for (int i = 0; i < test_data.size(); i++) { + // testbed->i_set.insert(test_data[i]); + // } + + // ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.i_set")->attr; + + // // ACT + // // Call the checkpoint function that is being tested + // (vec_attr->checkpoint_stl)((void *) &testbed->i_set, "my_alloc", vec_attr->name) ; + + // // ASSERT + // validate_temp_set(memmgr, std::string("my_alloc"), std::string("i_set"), std::set (test_data.begin(), test_data.end())); +} + +TEST_F(MM_stl_checkpoint, DISABLED_s_set ) { + // ARRANGE + // Make a testbed + // STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + // std::vector test_first = get_test_data(10); + // std::vector test_second = get_test_data(10); + + // // Prepare the STL to be tested + // for (int i = 0; i < test_first.size(); i++) { + // testbed->s_set.insert(std::pair(test_first[i], test_second[i])); + // } + + // ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.s_set")->attr; + + // // ACT + // // Call the checkpoint function that is being tested + // (vec_attr->checkpoint_stl)((void *) &testbed->s_set, "my_alloc", vec_attr->name) ; + + // // ASSERT + // for (int i = 0; i < test_first.size(); i++) { + // std::string var_name = "s_set_" + std::to_string(i); + // validate_temp_pair(memmgr, std::string("my_alloc"), var_name, std::pair(test_first[i], test_second[i])); + // } +} + + +TEST_F(MM_stl_checkpoint, DISABLED_nested_list_set ) { + // // ARRANGE + // // Make a testbed + // STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + // std::vector test_data = get_test_data(10); + // std::vector list_sizes = {2, 7, 1}; + // // Prepare the STL to be tested + + // int data_index = 0; + // for (int i = 0; i < list_sizes.size(); i++) { + // testbed->nested_list_stack.push(std::list(test_data.begin() + data_index, test_data.begin() + data_index + list_sizes[i])); + // data_index += list_sizes[i]; + // } + + // ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.nested_list_stack")->attr; + + // // ACT + // // Call the checkpoint function that is being tested + // (vec_attr->checkpoint_stl)((void *) &testbed->nested_list_stack, "my_alloc", vec_attr->name) ; + + // // ASSERT + // data_index = 0; + // for (int i = 0; i < list_sizes.size(); i++) { + // // reverse data - just go through the lists backwards + // std::string var_name = "nested_list_stack_" + std::to_string(list_sizes.size()-1-i); + // validate_temp_sequence(memmgr, std::string("my_alloc"), var_name, std::vector(test_data.begin() + data_index, test_data.begin() + data_index + list_sizes[i])); + // data_index += list_sizes[i]; + // } +} + + + +// Arrays + + +TEST_F(MM_stl_checkpoint, i_array ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(10); + + // Prepare the STL to be tested + for (int i = 0; i < test_data.size(); i++) { + testbed->i_array[i] = test_data[i]; + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.i_array")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->i_array, "my_alloc", vec_attr->name) ; + + // ASSERT + validate_temp_sequence(memmgr, std::string("my_alloc"), std::string("i_array"), test_data); +} + + +TEST_F(MM_stl_checkpoint, pair_array ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(20); + + // Prepare the STL to be tested + for (int i = 0; i < test_data.size(); i+=2) { + testbed->pair_array[i/2] = std::pair(test_data[i],test_data[i+1]); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.pair_array")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->pair_array, "my_alloc", vec_attr->name) ; + + // ASSERT + for (int i = 0; i < test_data.size(); i+=2) { + std::string var_name = "pair_array_" + std::to_string(i/2); + validate_temp_pair(memmgr, std::string("my_alloc"), var_name, std::pair(test_data[i],test_data[i+1])); + } + + validate_links_pairs(memmgr, std::string("my_alloc"), std::string("pair_array"), test_data.size()/2); +} + + +TEST_F(MM_stl_checkpoint, string_array ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(10); + + // Prepare the STL to be tested + for (int i = 0; i < test_data.size(); i++) { + testbed->string_array[i] = test_data[i]; + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.string_array")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->string_array, "my_alloc", vec_attr->name) ; + + // ASSERT + validate_temp_sequence(memmgr, std::string("my_alloc"), std::string("string_array"), test_data); +} + + +TEST_F(MM_stl_checkpoint, vec_array ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(100); + + // Prepare the STL to be tested + for (int i = 0; i < 10; i++) { + // testbed->vec_array[i] = std::vector(test_data.begin() + (i*10), test_data.begin()+(i+1)*10); + testbed->vec_array[i].insert(testbed->vec_array[i].end(), test_data.begin() + (i*10), test_data.begin() +((i+1)*10)); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.vec_array")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->vec_array, "my_alloc", vec_attr->name) ; + + // ASSERT + for (int i = 0; i < 10; i++) { + std::string var_name = "vec_array_" + std::to_string(i); + validate_temp_sequence(memmgr, std::string("my_alloc"), var_name, std::vector(test_data.begin() + (i*10), test_data.begin() +((i+1)*10))); + } + + validate_links(memmgr, std::string("my_alloc"), std::string("vec_array"), std::vector(10, 10)); +} + +TEST_F(MM_stl_checkpoint, vec_user_defined ) { + // Make a testbed + // ARRANGE + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.vec_user_defined")->attr; + + int numObj = 10; + std::vector test_ints = get_test_data(5 * numObj); + std::vector test_longs = get_test_data(numObj); + std::vector test_strings = get_test_data(numObj); + + for (int i = 0; i < numObj; i++) { + UserClass temp; + for (int j = 0; j < 5; j++) { + temp.a[j] = test_ints[i*5+j]; + } + temp.b = test_longs[i]; + temp.c = test_strings[i]; + + // just make a pointer to another one with the same data + std::string var_decl = "UserClass ptr_" + std::to_string(i); + UserClass * user_class_ptr = (UserClass *) memmgr->declare_var(var_decl.c_str()); + for (int j = 0; j < 5; j++) { + user_class_ptr->a[j] = test_ints[i*5+j]; + } + user_class_ptr->b = test_longs[i]; + user_class_ptr->c = test_strings[i]; + + temp.d = user_class_ptr; + + testbed->vec_user_defined.emplace_back(temp); + } + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->vec_user_defined, "my_alloc", vec_attr->name) ; + + // ASSERT + ASSERT_TRUE(memmgr->var_exists("my_alloc_vec_user_defined") == 1); + + REF2 * data_ref = memmgr->ref_attributes("my_alloc_vec_user_defined"); + UserClass * data = (UserClass *) data_ref->address; + + ASSERT_TRUE(data != NULL); + EXPECT_EQ(data_ref->attr->num_index, 1); + ASSERT_EQ(data_ref->attr->index[0].size, numObj); + + for (int i = 0; i < numObj; i++) { + std::string var_name = "ptr_" + std::to_string(i); + ASSERT_TRUE(memmgr->var_exists(var_name)); + REF2 * ptr_ref = memmgr->ref_attributes(var_name.c_str()); + UserClass * ptr_data = (UserClass *) ptr_ref->address; + + for (int j = 0; j < 5; j++) { + EXPECT_EQ(data[i].a[j], test_ints[i*5+j]); + EXPECT_EQ(ptr_data->a[j], test_ints[i*5+j]); + } + + EXPECT_EQ(data[i].b, test_longs[i]); + EXPECT_EQ(ptr_data->b, test_longs[i]); + + EXPECT_EQ(data[i].c, test_strings[i]); + EXPECT_EQ(ptr_data->c, test_strings[i]); + } +} + +TEST_F(MM_stl_checkpoint, DISABLED_vec_user_defined_stl ) { + // Make a testbed + // ARRANGE + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector> test_data; + for (int i = 0; i < 10; i++) { + std::vector test_data_inner = get_test_data(10); + UserClassStl temp_wrapper; + temp_wrapper.vec = std::vector(test_data_inner); + testbed->vec_user_defined_stl.emplace_back(temp_wrapper); + test_data.emplace_back(test_data_inner); + } + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.vec_user_defined_stl")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->vec_user_defined_stl, "my_alloc", vec_attr->name) ; + + // ASSERT + +} + + +// If this ridiculous data structure can be checkpointed, then I will +// have faith that any arbitrary nesting of STLs can be checkpointed +TEST_F(MM_stl_checkpoint, recursive_nightmare ) { + // ARRANGE + // Make a testbed + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(50); + std::vector test_strings = get_test_data(100); + + // Just build another one alongside and check the data inside? + // TODO: still need to figure out how to check the links between the datastructures in checkpointed form + std::array,std::vector>>, 5> recursive_nightmare_copy; + + // Prepare the STL to be tested + for (int i = 0; i < 5; i++) { + // iterate through array + + std::vector> keys; + // Make pairs as keys + for (int j = i*10; j < (i+1)*10; j+=2) { + keys.emplace_back(test_data[i], test_data[i+1]); + } + + std::vector>> vals; + + // Make vectors of stacks of strings as values + for (int j = i * 20; j < (i+1) * 20; j+=4) { + std::vector> val; + std::stack inner1; + std::stack inner2; + + inner1.push(test_strings[j]); + inner1.push(test_strings[j+1]); + inner2.push(test_strings[j+2]); + inner2.push(test_strings[j+3]); + + val.emplace_back(inner1); + val.emplace_back(inner2); + + vals.emplace_back(val); + } + + // Make the map + for (int m = 0; m < keys.size(); m++) { + testbed->recursive_nightmare[i].insert(std::pair,std::vector>>(keys[m], vals[m])); + recursive_nightmare_copy[i].insert(std::pair,std::vector>>(keys[m], vals[m])); + } + + } + + + ATTRIBUTES* vec_attr = memmgr->ref_attributes("my_alloc.recursive_nightmare")->attr; + + // ACT + // Call the checkpoint function that is being tested + (vec_attr->checkpoint_stl)((void *) &testbed->recursive_nightmare, "my_alloc", vec_attr->name) ; + + // ASSERT + for (int i = 0; i < 5; i++) { + + int j = 0; + for (auto it = recursive_nightmare_copy[i].begin(); it != recursive_nightmare_copy[i].end(); it++, j++) { + std::pair key = it->first; + std::vector> val = it->second; + + // keys first + std::string key_var_name = "recursive_nightmare_" + std::to_string(i) + "_keys_" + std::to_string(j); + validate_temp_pair(memmgr, std::string("my_alloc"), key_var_name, key); + + for (int k = 0; k < val.size(); k++) { + std::string val_var_name = "recursive_nightmare_" + std::to_string(i) + "_data_" + std::to_string(j) + "_" + std::to_string(k); + std::vector val_expected; + while (!val[k].empty()) { + val_expected.push_back(val[k].top()); + val[k].pop(); + } + validate_temp_sequence(memmgr, std::string("my_alloc"), val_var_name, val_expected); + } + } + } +} diff --git a/trick_source/sim_services/MemoryManager/test/MM_stl_restore.cc b/trick_source/sim_services/MemoryManager/test/MM_stl_restore.cc new file mode 100644 index 00000000..fcc7ca3b --- /dev/null +++ b/trick_source/sim_services/MemoryManager/test/MM_stl_restore.cc @@ -0,0 +1,1045 @@ +#include "gtest/gtest.h" +#define private public + +#include "trick/MemoryManager.hh" +#include "trick/memorymanager_c_intf.h" +#include "MM_stl_testbed.hh" +#include "MM_test.hh" + +/* + This tests the allocation of user-defined types using MemoryManager::declare_var(). + */ +class MM_stl_restore : public ::testing::Test { + + protected: + Trick::MemoryManager *memmgr; + + MM_stl_restore() { + try { + memmgr = new Trick::MemoryManager; + } catch (std::logic_error e) { + memmgr = NULL; + } + } + ~MM_stl_restore() { + delete memmgr; + } + void SetUp() {} + void TearDown() {} +}; + + + +TEST_F(MM_stl_restore, i_vec ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.i_vec")->attr; + + + std::vector test_data = get_test_data(20); + // Register the expected temporary variables with the memory manager + int * temp_data = (int *) memmgr->declare_var("int my_alloc_i_vec[20]"); + for (int i = 0; i < 20; i++) { + temp_data[i] = test_data[i]; + } + + // ACT + (attr->restore_stl)((void *) &testbed->i_vec, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->i_vec, test_data); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_i_vec"), 0); +} + +TEST_F(MM_stl_restore, i_s_vec ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.i_s_vec")->attr; + + + std::vector test_data = get_test_data(50); + std::vector lengths = {20, 4, 1, 1, 14, 10}; + + // Register the expected temporary variables with the memory manager + std::string my_alloc_i_s_vec[6]; + int start_index = 0; + memmgr->declare_extern_var(&my_alloc_i_s_vec, "std::string my_alloc_i_s_vec[6]"); + for (int i = 0; i < lengths.size(); i++) { + // std::string var_name = + my_alloc_i_s_vec[i] = "my_alloc_i_s_vec_" + std::to_string(i); + + std::string temp_var_name = "int my_alloc_i_s_vec_" + std::to_string(i) + "[" + std::to_string(lengths[i]) + "]"; + int * temp_arr = (int *)memmgr->declare_var(temp_var_name.c_str()); + for (int j = 0; j < lengths[i]; j++) { + temp_arr[j] = test_data[start_index + j]; + } + + start_index += lengths[i]; + } + + // ACT + (attr->restore_stl)((void *) &testbed->i_s_vec, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + ASSERT_EQ(testbed->i_s_vec.size(), lengths.size()); + start_index = 0; + for (int i = 0; i < lengths.size(); i++) { + ASSERT_EQ(testbed->i_s_vec[i].size(), lengths[i]); + EXPECT_EQ(testbed->i_s_vec[i], std::vector(test_data.begin()+start_index, test_data.begin()+start_index+lengths[i])); + start_index += lengths[i]; + } + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_i_s_vec"), 0); + for (int i = 0; i < test_data.size()/2; i++) { + EXPECT_EQ(memmgr->var_exists("my_alloc_i_s_vec_" + std::to_string(i)), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_i_s_vec_" + std::to_string(i)), 0); + } +} + +TEST_F(MM_stl_restore, s_vec ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(40); + + // Register the expected temporary variables with the memory manager + std::string my_alloc_s_vec[20]; + memmgr->declare_extern_var(&my_alloc_s_vec, "std::string my_alloc_s_vec[20]"); + for (int i = 0; i < test_data.size()/2; i++) { + my_alloc_s_vec[i] = "my_alloc_s_vec_" + std::to_string(i); + + std::string first_var_name = "int my_alloc_s_vec_" + std::to_string(i) + "_first"; + std::string second_var_name = "int my_alloc_s_vec_" + std::to_string(i) + "_second"; + + int * temp_first = (int *)memmgr->declare_var(first_var_name.c_str()); + *temp_first = test_data[i*2]; + int * temp_second = (int *)memmgr->declare_var(second_var_name.c_str()); + *temp_second = test_data[i*2+1]; + } + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.s_vec")->attr; + + // ACT + (attr->restore_stl)((void *) &testbed->s_vec, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + ASSERT_EQ(testbed->s_vec.size(), test_data.size()/2); + for (int i = 0; i < test_data.size()/2; i++) { + EXPECT_EQ(testbed->s_vec[i].first, test_data[i*2]); + EXPECT_EQ(testbed->s_vec[i].second, test_data[i*2+1]); + } + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_s_vec"), 0); + for (int i = 0; i < test_data.size()/2; i++) { + EXPECT_EQ(memmgr->var_exists("my_alloc_s_vec_" + std::to_string(i) + "_first"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_s_vec_" + std::to_string(i) + "_second"), 0); + } +} + +TEST_F(MM_stl_restore, string_vec ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_data = get_test_data(20); + + // Register the expected temporary variables with the memory manager + std::string * temp_data = (std::string *) memmgr->declare_var("std::string my_alloc_string_vec[20]"); + for (int i = 0; i < 20; i++) { + temp_data[i] = std::string(test_data[i]); + } + + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.string_vec")->attr; + + // ACT + (attr->restore_stl)((void *) &testbed->string_vec, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->string_vec, test_data); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_string_vec"), 0); +} + +TEST_F(MM_stl_restore, i_i_pair ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + double test_first = random(); + float test_second = random (); + + // Register the expected temporary variables with the memory manager + double * first_data = (double *) memmgr->declare_var("double my_alloc_i_i_pair_first"); + float * second_data = (float *) memmgr->declare_var("float my_alloc_i_i_pair_second"); + + *first_data = test_first; + *second_data = test_second; + + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.i_i_pair")->attr; + + // ACT + (attr->restore_stl)((void *) &testbed->i_i_pair, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->i_i_pair.first, test_first); + EXPECT_EQ(testbed->i_i_pair.second, test_second); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_i_i_pair_first"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_i_i_pair_second"), 0); +} + +TEST_F(MM_stl_restore, DISABLED_i_s_pair ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + double test_first = random(); + std::vector test_second = get_test_data(20); + + // Register the expected temporary variables with the memory manager + double * first_data = (double *) memmgr->declare_var("double my_alloc_i_s_pair_first"); + bool * second_data = (bool *) memmgr->declare_var("bool my_alloc_i_s_pair_second[20]"); + + *first_data = test_first; + for (int i = 0; i < test_second.size(); i++) { + second_data[i] = test_second[i]; + } + + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.i_s_pair")->attr; + + // ACT + (attr->restore_stl)((void *) &testbed->i_s_pair, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->i_s_pair.first, test_first); + EXPECT_EQ(testbed->i_s_pair.second.size(), test_second.size()); + for (int i = 0; i < test_second.size(); i++) { + EXPECT_EQ(testbed->i_s_pair.second.front(), test_second[i]); + testbed->i_s_pair.second.pop(); + } + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_i_s_pair_first"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_i_s_pair_second"), 0); +} + +TEST_F(MM_stl_restore, DISABLED_s_i_pair ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_first = get_test_data(20); + double test_second = random(); + + // Register the expected temporary variables with the memory manager + bool * first_data = (bool *) memmgr->declare_var("bool my_alloc_s_i_pair_first[20]"); + double * second_data = (double *) memmgr->declare_var("double my_alloc_s_i_pair_second"); + + for (int i = 0; i < test_first.size(); i++) { + first_data[i] = test_first[i]; + } + *second_data = test_second; + + + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.s_i_pair")->attr; + + // ACT + (attr->restore_stl)((void *) &testbed->s_i_pair, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->s_i_pair.second, test_second); + EXPECT_EQ(testbed->s_i_pair.first.size(), test_first.size()); + for (int i = 0; i < test_first.size(); i++) { + EXPECT_EQ(testbed->s_i_pair.first.front(), test_first[i]); + testbed->s_i_pair.first.pop(); + } + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_s_i_pair_first"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_s_i_pair_second"), 0); +} + +TEST_F(MM_stl_restore, DISABLED_s_s_pair ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_first = get_test_data(20); + std::vector test_second = get_test_data(20); + + // Register the expected temporary variables with the memory manager + bool * first_data = (bool *) memmgr->declare_var("bool my_alloc_s_s_pair_first[20]"); + double * second_data = (double *) memmgr->declare_var("double my_alloc_s_s_pair_second"); + + for (int i = 0; i < test_first.size(); i++) { + first_data[i] = test_first[i]; + } + for (int i = 0; i < test_second.size(); i++) { + second_data[i] = test_second[i]; + } + + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.s_s_pair")->attr; + + // ACT + (attr->restore_stl)((void *) &testbed->s_s_pair, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->s_s_pair.first.size(), test_first.size()); + EXPECT_EQ(testbed->s_s_pair.second.size(), test_second.size()); + for (int i = 0; i < test_first.size(); i++) { + EXPECT_EQ(testbed->s_s_pair.first[i], test_first[i]); + EXPECT_EQ(testbed->s_s_pair.second.top(), test_second[test_second.size()-1-i]); + testbed->s_s_pair.second.pop(); + } + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_s_s_pair_first"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_s_s_pair_second"), 0); +} + +TEST_F(MM_stl_restore, pair_pair ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + int test_first_first = random(); + int test_first_second = random(); + int test_second = random(); + + // Register the expected temporary variables with the memory manager + int * first_first_data = (int *) memmgr->declare_var("int my_alloc_pair_pair_first_first"); + int * first_second_data = (int *) memmgr->declare_var("int my_alloc_pair_pair_first_second"); + int * second_data = (int *) memmgr->declare_var("int my_alloc_pair_pair_second"); + + (void) memmgr->declare_var("std::string my_alloc_pair_pair_first[1]"); + + *first_first_data = test_first_first; + *first_second_data = test_first_second; + *second_data = test_second; + + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.pair_pair")->attr; + + // ACT + (attr->restore_stl)((void *) &testbed->pair_pair, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->pair_pair.first.first, test_first_first); + EXPECT_EQ(testbed->pair_pair.first.second, test_first_second); + EXPECT_EQ(testbed->pair_pair.second, test_second); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_pair_pair_first"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_pair_pair_first_first"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_pair_pair_first_second"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_pair_pair_second"), 0); +} + +TEST_F(MM_stl_restore, i_i_map ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_keys = get_test_data(20); + std::vector test_data = get_test_data(20); + std::map test_map; + + int * key_data = (int *) memmgr->declare_var("int my_alloc_i_i_map_keys[20]"); + double * val_data = (double *) memmgr->declare_var("double my_alloc_i_i_map_data[20]"); + for (int i = 0; i < test_keys.size(); i++) { + key_data[i] = test_keys[i]; + val_data[i] = test_data[i]; + + // Create a map of expected data along side so that we don't have to deal with ordering stuff + test_map[test_keys[i]] = test_data[i]; + } + + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.i_i_map")->attr; + + // ACT + (attr->restore_stl)((void *) &testbed->i_i_map, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->i_i_map, test_map); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_i_i_map_keys"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_i_i_map_data"), 0); +} + +TEST_F(MM_stl_restore, i_s_map ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_keys = get_test_data(10); + std::vector test_data = get_test_data(60); + std::map> test_map; + + int * key_data = (int *) memmgr->declare_var("int my_alloc_i_s_map_keys[10]"); + std::string * val_data = (std::string *) memmgr->declare_var("std::string my_alloc_i_s_map_data[10]"); + for (int i = 0; i < test_keys.size(); i++) { + key_data[i] = test_keys[i]; + val_data[i] = std::string("my_alloc_i_s_map_data_" + std::to_string(i)); + + std::string var_name = "std::string my_alloc_i_s_map_data_" + std::to_string(i) + "[" + std::to_string(6) + "]"; + std::string * val_temp = (std::string *) memmgr->declare_var(var_name.c_str()); + + for (int j = 0; j < 6; j++) { + val_temp[j] = test_data[(i*6) + j]; + + // Create a map of expected data along side so that we don't have to deal with ordering stuff + // Reverse order of the data since it's a stack + test_map[test_keys[i]].push(test_data[((i+1)*6)-1-j]); + } + } + + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.i_s_map")->attr; + + // ACT + (attr->restore_stl)((void *) &testbed->i_s_map, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->i_s_map, test_map); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_i_s_map_keys"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_i_s_map_data"), 0); + for (int i = 0; i < testbed->i_s_map.size(); i++) { + std::string var_name_test = "my_alloc_i_s_map_data_" + std::to_string(i); + EXPECT_EQ(memmgr->var_exists(var_name_test.c_str()), 0); + } +} + +TEST_F(MM_stl_restore, s_i_map ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + std::vector test_keys = get_test_data(30); + std::vector test_data = get_test_data(10); + std::map, std::string> test_map; + + std::string * key_data = (std::string *) memmgr->declare_var("std::string my_alloc_s_i_map_keys[10]"); + std::string * val_data = (std::string *) memmgr->declare_var("std::string my_alloc_s_i_map_data[10]"); + for (int i = 0; i < test_data.size(); i++) { + key_data[i] = std::string("my_alloc_s_i_map_keys_" + std::to_string(i)); + + std::string var_name = "int my_alloc_s_i_map_keys_" + std::to_string(i) + "[" + std::to_string(3) + "]"; + int * val_temp = (int *) memmgr->declare_var(var_name.c_str()); + + std::set temp_set; + for (int j = 0; j < 3; j++) { + val_temp[j] = test_keys[(i*3) + j]; + + // Create a map of expected data along side so that we don't have to deal with ordering stuff + temp_set.insert(test_keys[(i*3) + j]); + } + + val_data[i] = test_data[i]; + + // insert into the test map + test_map[temp_set] = test_data[i]; + } + + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.s_i_map")->attr; + + // ACT + (attr->restore_stl)((void *) &testbed->s_i_map, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->s_i_map, test_map); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_s_i_map_keys"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_s_i_map_data"), 0); + for (int i = 0; i < testbed->i_s_map.size(); i++) { + std::string var_name_test = "my_alloc_s_i_map_keys_" + std::to_string(i); + EXPECT_EQ(memmgr->var_exists(var_name_test.c_str()), 0); + } +} + + +TEST_F(MM_stl_restore, s_s_map ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + + int map_size = 10; + std::vector test_keys = get_test_data(20); + std::vector test_data = get_test_data(40); + std::map, std::vector> test_map; + + // Make the top level key and data structures + // These will just have strings that point to where the actual data is + std::string * key_data = (std::string *) memmgr->declare_var("std::string my_alloc_s_s_map_keys[10]"); + std::string * val_data = (std::string *) memmgr->declare_var("std::string my_alloc_s_s_map_data[10]"); + for (int i = 0; i < map_size; i++) { + // This is the string that lives in the my_alloc_s_s_map_keys structure + key_data[i] = std::string("my_alloc_s_s_map_keys_" + std::to_string(i)); + + // These first and second variables hold the actual data for index i + std::string first_name = "int my_alloc_s_s_map_keys_" + std::to_string(i) + "_first"; + int * val_first = (int *) memmgr->declare_var(first_name.c_str()); + *val_first = test_keys[i*2]; + + std::string second_name = "int my_alloc_s_s_map_keys_" + std::to_string(i) + "_second"; + int * val_second = (int *) memmgr->declare_var(second_name.c_str()); + *val_second = test_keys[i*2+1]; + + // This is the string that lives in the my_alloc_s_s_map_data structure + val_data[i] = std::string("my_alloc_s_s_map_data_" + std::to_string(i)); + + // This is the array that holds the actual data for index i + std::string data_name = "int my_alloc_s_s_map_data_" + std::to_string(i) + "[" + std::to_string(4) + "]"; + int * data_values = (int *) memmgr->declare_var(data_name.c_str()); + + for (int j = 0; j < 4; j++) { + data_values[j] = test_data[(i*4) + j]; + + // Create a map of expected data along side so that we don't have to deal with ordering stuff + test_map[std::pair(test_keys[i*2], test_keys[i*2+1])].push_back(test_data[(i*4) + j]); + } + } + + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.s_s_map")->attr; + + + + // ACT + (attr->restore_stl)((void *) &testbed->s_s_map, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->s_s_map, test_map); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_s_s_map_keys"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_s_s_map_data"), 0); + for (int i = 0; i < map_size; i++) { + std::string var_name_test = "my_alloc_s_s_map_keys_" + std::to_string(i) + "_first"; + EXPECT_EQ(memmgr->var_exists(var_name_test.c_str()), 0); + var_name_test = "my_alloc_s_s_map_keys_" + std::to_string(i) + "_second"; + EXPECT_EQ(memmgr->var_exists(var_name_test.c_str()), 0); + var_name_test = "my_alloc_s_s_map_data_" + std::to_string(i); + EXPECT_EQ(memmgr->var_exists(var_name_test.c_str()), 0); + } +} + + +TEST_F(MM_stl_restore, i_queue ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.i_queue")->attr; + + + std::vector test_data = get_test_data(20); + std::queue expected_data; + // Register the expected temporary variables with the memory manager + int * temp_data = (int *) memmgr->declare_var("int my_alloc_i_queue[20]"); + for (int i = 0; i < 20; i++) { + temp_data[i] = test_data[i]; + expected_data.push(test_data[i]); + } + + // ACT + (attr->restore_stl)((void *) &testbed->i_queue, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->i_queue, expected_data); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_i_queue"), 0); +} + + +TEST_F(MM_stl_restore, s_queue ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES * attr = memmgr->ref_attributes("my_alloc.s_queue")->attr; + + std::vector test_first= get_test_data(20); + std::vector test_second = get_test_data(20); + + std::queue> expected; + + std::string * data_links = (std::string *) memmgr->declare_var("std::string my_alloc_s_queue[20]"); + + for (int i = 0; i < test_first.size(); i++) { + data_links[i] = "my_alloc_s_queue_" + std::to_string(i); + + std::string first_var_name = "int my_alloc_s_queue_" + std::to_string(i) + "_first"; + std::string second_var_name = "double my_alloc_s_queue_" + std::to_string(i) + "_second"; + + int * temp_first = (int *)memmgr->declare_var(first_var_name.c_str()); + *temp_first = test_first[i]; + double * temp_second = (double *)memmgr->declare_var(second_var_name.c_str()); + *temp_second = test_second[i]; + + // Build a copy of the expected data + expected.push(std::pair(test_first[i], test_second[i])); + } + + // ACT + (attr->restore_stl)((void *) &testbed->s_queue, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->s_queue, expected); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_s_queue"), 0); + for (int i = 0; i < test_first.size(); i++) { + EXPECT_EQ(memmgr->var_exists("my_alloc_s_queue_" + std::to_string(i) + "_first"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_s_queue_" + std::to_string(i) + "_second"), 0); + } +} + +TEST_F(MM_stl_restore, nested_list_queue ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.nested_list_queue")->attr; + + std::vector test_data = get_test_data(50); + // Make sure we can handle lists of different sizes + std::vector lengths = {20, 4, 1, 1, 14, 10}; + + // Register the expected temporary variables with the memory manager + std::queue> expected; + + int start_index = 0; + std::string * nested_list_links = (std::string *) memmgr->declare_var( "std::string my_alloc_nested_list_queue[6]"); + for (int i = 0; i < lengths.size(); i++) { + nested_list_links[i] = "my_alloc_nested_list_queue_" + std::to_string(i); + + std::string temp_var_name = "float my_alloc_nested_list_queue_" + std::to_string(i) + "[" + std::to_string(lengths[i]) + "]"; + std::list temp_expected; + float * temp_arr = (float *)memmgr->declare_var(temp_var_name.c_str()); + for (int j = 0; j < lengths[i]; j++) { + temp_arr[j] = test_data[start_index + j]; + temp_expected.push_back(test_data[start_index + j]); + } + + expected.push(temp_expected); + + start_index += lengths[i]; + } + + // ACT + (attr->restore_stl)((void *) &testbed->nested_list_queue, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + ASSERT_EQ(testbed->nested_list_queue, expected); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_nested_list_queue"), 0); + for (int i = 0; i < test_data.size()/2; i++) { + EXPECT_EQ(memmgr->var_exists("my_alloc_nested_list_queue_" + std::to_string(i)), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_nested_list_queue_" + std::to_string(i)), 0); + } +} + +TEST_F(MM_stl_restore, i_stack ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.i_stack")->attr; + + + std::vector test_data = get_test_data(20); + std::stack expected_data; + // Register the expected temporary variables with the memory manager + long long * temp_data = (long long *) memmgr->declare_var("long long my_alloc_i_stack[20]"); + for (int i = 0; i < test_data.size(); i++) { + temp_data[i] = test_data[i]; + + // push backwards bc stack + expected_data.push(test_data[test_data.size()-1-i]); + } + + // ACT + (attr->restore_stl)((void *) &testbed->i_stack, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->i_stack, expected_data); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_i_stack"), 0); +} + +TEST_F(MM_stl_restore, s_stack ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES * attr = memmgr->ref_attributes("my_alloc.s_stack")->attr; + + std::vector test_first= get_test_data(20); + std::vector test_second = get_test_data(20); + + std::stack> expected; + + std::string * data_links = (std::string *) memmgr->declare_var("std::string my_alloc_s_stack[20]"); + + for (int i = 0; i < test_first.size(); i++) { + data_links[i] = "my_alloc_s_stack_" + std::to_string(i); + + std::string first_var_name = "short my_alloc_s_stack_" + std::to_string(i) + "_first"; + std::string second_var_name = "double my_alloc_s_stack_" + std::to_string(i) + "_second"; + + short * temp_first = (short *)memmgr->declare_var(first_var_name.c_str()); + *temp_first = test_first[i]; + double * temp_second = (double *)memmgr->declare_var(second_var_name.c_str()); + *temp_second = test_second[i]; + + // Build a copy of the expected data + // Backwards because stack + expected.push(std::pair(test_first[test_first.size()-1-i], test_second[test_first.size()-1-i])); + } + + // ACT + (attr->restore_stl)((void *) &testbed->s_stack, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->s_stack, expected); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_s_stack"), 0); + for (int i = 0; i < test_first.size(); i++) { + EXPECT_EQ(memmgr->var_exists("my_alloc_s_stack_" + std::to_string(i) + "_first"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_s_stack_" + std::to_string(i) + "_second"), 0); + } +} + +TEST_F(MM_stl_restore, nested_list_stack ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.nested_list_stack")->attr; + + std::vector test_data = get_test_data(50); + // Make sure we can handle lists of different sizes + std::vector lengths = {20, 4, 1, 1, 14, 10}; + + // Just build the stack backwards and flip it + std::stack> expected; + std::stack> reverse_expected; + + // Register the expected temporary variables with the memory manager + int start_index = 0; + std::string * nested_list_links = (std::string *) memmgr->declare_var( "std::string my_alloc_nested_list_stack[6]"); + for (int i = 0; i < lengths.size(); i++) { + nested_list_links[i] = "my_alloc_nested_list_stack_" + std::to_string(i); + + std::string temp_var_name = "float my_alloc_nested_list_stack_" + std::to_string(i) + "[" + std::to_string(lengths[i]) + "]"; + std::list temp_expected; + float * temp_arr = (float *)memmgr->declare_var(temp_var_name.c_str()); + for (int j = 0; j < lengths[i]; j++) { + temp_arr[j] = test_data[start_index + j]; + temp_expected.push_back(test_data[start_index + j]); + } + + reverse_expected.push(temp_expected); + + start_index += lengths[i]; + } + + // flip the stack so we have expected in the right order + while (!reverse_expected.empty()) { + expected.push(reverse_expected.top()); + reverse_expected.pop(); + } + + // ACT + (attr->restore_stl)((void *) &testbed->nested_list_stack, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + ASSERT_EQ(testbed->nested_list_stack, expected); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_nested_list_stack"), 0); + for (int i = 0; i < test_data.size()/2; i++) { + EXPECT_EQ(memmgr->var_exists("my_alloc_nested_list_stack_" + std::to_string(i)), 0); + } +} + +TEST_F(MM_stl_restore, i_set ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.i_set")->attr; + + + std::vector test_data = get_test_data(100); + std::set expected; + + // Make the expected structure first + for (char val : test_data) { + expected.insert(val); + } + + // Register the expected temporary variables with the memory manager + std::string var_name = "char my_alloc_i_set[" + std::to_string(expected.size()) + "]"; + char * temp_data = (char *) memmgr->declare_var(var_name.c_str()); + int index = 0; + for (const char val : expected) { + temp_data[index++] = val; + } + + // ACT + (attr->restore_stl)((void *) &testbed->i_set, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->i_set, expected); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_i_set"), 0); +} + +// These can't be written yet since the data structures will fail at compile time + +TEST_F(MM_stl_restore, DISABLED_s_set ) { } + +TEST_F(MM_stl_restore, DISABLED_nested_map_set ) { } + +TEST_F(MM_stl_restore, DISABLED_i_multiset ) { } + + +TEST_F(MM_stl_restore, i_array ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.i_array")->attr; + + std::vector test_data = get_test_data(10); + std::array expected; + + // Register the expected temporary variables with the memory manager + char * temp_data = (char *) memmgr->declare_var("char my_alloc_i_array[10]"); + for (int i = 0; i < test_data.size(); i++) { + temp_data[i] = test_data[i]; + expected[i] = test_data[i]; + } + + // ACT + (attr->restore_stl)((void *) &testbed->i_array, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->i_array, expected); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_i_array"), 0); +} + +TEST_F(MM_stl_restore, pair_array ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES * attr = memmgr->ref_attributes("my_alloc.pair_array")->attr; + + std::vector test_first= get_test_data(10); + std::vector test_second = get_test_data(10); + + std::array, 10> expected; + + std::string * data_links = (std::string *) memmgr->declare_var("std::string my_alloc_pair_array[10]"); + + for (int i = 0; i < test_first.size(); i++) { + data_links[i] = "my_alloc_pair_array_" + std::to_string(i); + + std::string first_var_name = "int my_alloc_pair_array_" + std::to_string(i) + "_first"; + std::string second_var_name = "int my_alloc_pair_array_" + std::to_string(i) + "_second"; + + int * temp_first = (int *)memmgr->declare_var(first_var_name.c_str()); + *temp_first = test_first[i]; + int * temp_second = (int *)memmgr->declare_var(second_var_name.c_str()); + *temp_second = test_second[i]; + + // Build a copy of the expected data + expected[i] = std::pair(test_first[i], test_second[i]); + } + + // ACT + (attr->restore_stl)((void *) &testbed->pair_array, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->pair_array, expected); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_pair_array"), 0); + for (int i = 0; i < test_first.size(); i++) { + EXPECT_EQ(memmgr->var_exists("my_alloc_pair_array_" + std::to_string(i) + "_first"), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_pair_array_" + std::to_string(i) + "_second"), 0); + } +} + +TEST_F(MM_stl_restore, string_array ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.string_array")->attr; + + std::vector test_data = get_test_data(10); + std::array expected; + + // Register the expected temporary variables with the memory manager + std::string * temp_data = (std::string *) memmgr->declare_var("std::string my_alloc_string_array[10]"); + for (int i = 0; i < test_data.size(); i++) { + temp_data[i] = std::string(test_data[i]); + expected[i] = std::string(test_data[i]); + } + + // ACT + (attr->restore_stl)((void *) &testbed->string_array, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->string_array, expected); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_string_array"), 0); +} + +TEST_F(MM_stl_restore, vec_array ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.vec_array")->attr; + + + std::vector test_data = get_test_data(50); + std::vector lengths = {12, 4, 1, 1, 14, 10, 2, 2, 2, 2}; + + // Register the expected temporary variables with the memory manager + std::string my_alloc_vec_array[10]; + int start_index = 0; + memmgr->declare_extern_var(&my_alloc_vec_array, "std::string my_alloc_vec_array[10]"); + for (int i = 0; i < lengths.size(); i++) { + // std::string var_name = + my_alloc_vec_array[i] = "my_alloc_vec_array_" + std::to_string(i); + + std::string temp_var_name = "int my_alloc_vec_array_" + std::to_string(i) + "[" + std::to_string(lengths[i]) + "]"; + int * temp_arr = (int *)memmgr->declare_var(temp_var_name.c_str()); + for (int j = 0; j < lengths[i]; j++) { + temp_arr[j] = test_data[start_index + j]; + } + + start_index += lengths[i]; + } + + // ACT + (attr->restore_stl)((void *) &testbed->vec_array, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + ASSERT_EQ(testbed->vec_array.size(), lengths.size()); + start_index = 0; + for (int i = 0; i < lengths.size(); i++) { + ASSERT_EQ(testbed->vec_array[i].size(), lengths[i]); + EXPECT_EQ(testbed->vec_array[i], std::vector(test_data.begin()+start_index, test_data.begin()+start_index+lengths[i])); + start_index += lengths[i]; + } + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_vec_array"), 0); + for (int i = 0; i < test_data.size()/2; i++) { + EXPECT_EQ(memmgr->var_exists("my_alloc_vec_array_" + std::to_string(i)), 0); + EXPECT_EQ(memmgr->var_exists("my_alloc_vec_array_" + std::to_string(i)), 0); + } +} + +TEST_F(MM_stl_restore, vec_user_defined ) { + // ARRANGE + // make a testbed object + STLTestbed * testbed = (STLTestbed *) memmgr->declare_var("STLTestbed my_alloc"); + ATTRIBUTES* attr = memmgr->ref_attributes("my_alloc.vec_user_defined")->attr; + + int numObj = 10; + std::vector test_ints = get_test_data(5 * numObj); + std::vector test_longs = get_test_data(numObj); + std::vector test_strings = get_test_data(numObj); + + // Register the expected temporary variables with the memory manager + UserClass * data = (UserClass *) memmgr->declare_var("UserClass my_alloc_vec_user_defined[10]"); + + // Create an structure holding the expected final container + std::vector expected; + + for (int i = 0; i < numObj; i++) { + UserClass temp; + for (int j = 0; j < 5; j++) { + temp.a[j] = test_ints[i*5+j]; + data[i].a[j] = test_ints[i*5+j]; + } + data[i].b = test_longs[i]; + data[i].c = test_strings[i]; + + temp.b = test_longs[i]; + temp.c = test_strings[i]; + + // just make a pointer to another one with the same data + std::string var_decl = "UserClass ptr_" + std::to_string(i); + UserClass * user_class_ptr = (UserClass *) memmgr->declare_var(var_decl.c_str()); + UserClass * expected_ptr = new UserClass(); + + for (int j = 0; j < 5; j++) { + user_class_ptr->a[j] = test_ints[i*5+j]; + expected_ptr->a[j] = test_ints[i*5+j]; + + } + user_class_ptr->b = test_longs[i]; + user_class_ptr->c = test_strings[i]; + + expected_ptr->b = test_longs[i]; + expected_ptr->c = test_strings[i]; + + data[i].d = user_class_ptr; + temp.d = expected_ptr; + + expected.emplace_back(temp); + } + + + // ACT + (attr->restore_stl)((void *) &testbed->vec_user_defined, "my_alloc", attr->name) ; + + // ASSERT + // Make sure the STL has been populated + EXPECT_EQ(testbed->vec_user_defined, expected); + + // Check that all the temporary variables have been deleted + EXPECT_EQ(memmgr->var_exists("my_alloc_vec_user_defined"), 0); +} + + +TEST_F(MM_stl_restore, recursive_nightmare ) { +} diff --git a/trick_source/sim_services/MemoryManager/test/MM_stl_testbed.hh b/trick_source/sim_services/MemoryManager/test/MM_stl_testbed.hh new file mode 100644 index 00000000..5e87785f --- /dev/null +++ b/trick_source/sim_services/MemoryManager/test/MM_stl_testbed.hh @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class UserClassStl { + public: + int a; + std::vector vec; +}; + +class UserClass { + public: + UserClass () : d(NULL) {} + int a[5]; + long long b; + std::string c; + UserClass * d = NULL; + + bool operator== (const UserClass& other) const { + for (int i = 0; i < 5; i++) { + if (a[i] != other.a[i]) + return false; + } + + if (d == NULL ^ other.d == NULL) return false; + return b == other.b && c == other.c && (d == NULL || *d == *(other.d)); + } + + bool operator != (const UserClass& other) const { + return !(*this == other); + } + +}; + +class STLTestbed { +public: + // This class is intended to test the checkpoint, restore, and delete functions for each of the supported STL types. + // These live in the include/trick directory in checkpoint_.hh + // Each STL type has its own implementation of each function, so they must be tested separately. + // In addition, if the template argument is another STL container, a separate implementation is enabled to + // support recursion. (intrinsic:i vs stl:s in var names here) + // Therefore, each of the 11 supported types presents 3 * 2^(num template args) implementations to test, + // plus strings and pairs are sometimes handled strangely so those should probably be included here too + + std::vector i_vec; + std::vector> i_s_vec; + std::vector> s_vec; + std::vector string_vec; + + std::pair i_i_pair; + std::pair> i_s_pair; + std::pair,double> s_i_pair; + std::pair,std::stack> s_s_pair; + std::pair> i_v_pair; + std::pair, int> pair_pair; + + std::map i_i_map; + std::map> i_s_map; + std::map, std::string> s_i_map; + std::map, std::vector> s_s_map; + + std::queue i_queue; + std::queue> s_queue; + std::queue> nested_list_queue; + + std::stack i_stack; + std::stack> s_stack; + std::stack> nested_list_stack; + + std::set i_set; + // These fail in CP right now + // std::set > s_set; + // std::set> nested_map_set; + + // this one will as well, if we put any STL containers in there + std::multiset i_multiset; + + std::array i_array; + std::array, 10> pair_array; + std::array string_array; + std::array, 10> vec_array; + + std::vector vec_user_defined; + + // This does not currently work in the unit tests + std::vector vec_user_defined_stl; + + + std::array,std::vector>>, 5> recursive_nightmare; +}; diff --git a/trick_source/sim_services/MemoryManager/test/MM_test.hh b/trick_source/sim_services/MemoryManager/test/MM_test.hh index 7f8f5031..a62c9770 100644 --- a/trick_source/sim_services/MemoryManager/test/MM_test.hh +++ b/trick_source/sim_services/MemoryManager/test/MM_test.hh @@ -95,4 +95,60 @@ void validate_alloc_info(Trick::MemoryManager *memmgr, validate_alloc_info(alloc_info, test_var, trick_type, type_name, var_name, num, num_index, extent); } + + + +// This one is for anything integral +// char, short, int, long, long long +template ::value>::type* = nullptr> +T random() { + return (T) (rand() % 1000); +} + +// This should just catch bools +// Template specialization! +template<> +bool random () { + return (bool) (rand() & 1); +} + +// This is for floats and doubles +template ::value>::type* = nullptr> +T random() { + T divisor = (T) rand(); + + // for this one in 2 billion chance + if (divisor == 0) { + divisor += 1; + } + + return ((T) rand()) / divisor; +} + +// This should just catch strings +// Template specialization! +template<> +std::string random () { + static const char characters[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz .,-=_+/?!@#$%^&*()<>\\\"\'\n\t\r"; + static const int max_string_len = 32; + + std::string random_str;; + int len = rand() % max_string_len; + for (int j = 0; j < len; j++) { + random_str += characters[rand() % sizeof(characters)]; + } + + return random_str; +} + +// generate some random data +template +std::vector get_test_data(int num) { + std::vector ret; + for (int i = 0; i < num; i++) { + ret.push_back(random()); + } + return ret; +} + #endif diff --git a/trick_source/sim_services/MemoryManager/test/MM_user_defined_types.hh b/trick_source/sim_services/MemoryManager/test/MM_user_defined_types.hh index 54a3aab8..b5d723e7 100644 --- a/trick_source/sim_services/MemoryManager/test/MM_user_defined_types.hh +++ b/trick_source/sim_services/MemoryManager/test/MM_user_defined_types.hh @@ -2,6 +2,7 @@ PURPOSE: (Testing) */ #include +#include typedef struct { unsigned int a :3; @@ -93,3 +94,26 @@ class UDT7 { char B[32][4]; }; +class Foo { + public: + int a; + double b; + std::vector c; +}; + +class VectorWrapper { + public: + int operator[] (int index) { + return vec[index]; + } + + void push_back(int val) { + vec.push_back(val); + } + + int size() { + return vec.size(); + } + std::vector vec; + +}; diff --git a/trick_source/sim_services/MemoryManager/test/MM_write_checkpoint.cc b/trick_source/sim_services/MemoryManager/test/MM_write_checkpoint.cc index 5cec4ffc..5f0a1c9c 100644 --- a/trick_source/sim_services/MemoryManager/test/MM_write_checkpoint.cc +++ b/trick_source/sim_services/MemoryManager/test/MM_write_checkpoint.cc @@ -1104,3 +1104,30 @@ TEST_F(MM_write_checkpoint, ptr_to_array_of_ptrs_to_objects ) { EXPECT_EQ( udt7_p->udt3pp[2]->b , 8); } +TEST_F(MM_write_checkpoint, WrappedStl ) { + VectorWrapper * vector = (VectorWrapper *) memmgr->declare_var("VectorWrapper vec_allocation"); + vector->push_back(10); + vector->push_back(20); + vector->push_back(30); + vector->push_back(40); + + std::stringstream ss; + memmgr->write_checkpoint(ss, "vec_allocation"); + + std::string result= ss.str(); + ASSERT_NE (result.size(), 0); + + EXPECT_EQ( strcmp_IgnoringWhiteSpace( + "// Variable Declarations." + "VectorWrapper vec_allocation;" + "int vec_allocation_vec[4];" + "// Clear all allocations to 0." + "clear_all_vars();" + "// Variable Assignments." + "// STL: vec_allocation.vec" + "vec_allocation_vec = " + "{10, 20, 30, 40};", result.c_str()), 0); +} + + + diff --git a/trick_source/sim_services/MemoryManager/test/MM_write_checkpoint.hh b/trick_source/sim_services/MemoryManager/test/MM_write_checkpoint.hh index 8a21cec2..d1cf6567 100644 --- a/trick_source/sim_services/MemoryManager/test/MM_write_checkpoint.hh +++ b/trick_source/sim_services/MemoryManager/test/MM_write_checkpoint.hh @@ -1,6 +1,8 @@ /* PURPOSE: (Testing) */ +#include +#include typedef enum { JANUARY = 1, FEBRUARY = 2, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER @@ -42,3 +44,21 @@ class UDT7 { double A; UDT3** udt3pp; }; + +class VectorWrapper { + public: + int operator[] (int index) { + return vec[index]; + } + + void push_back(int val) { + vec.push_back(val); + } + + int size() { + return vec.size(); + } + + private: + std::vector vec; +}; diff --git a/trick_source/sim_services/MemoryManager/test/Makefile b/trick_source/sim_services/MemoryManager/test/Makefile index 6ffd6553..f9b5df08 100644 --- a/trick_source/sim_services/MemoryManager/test/Makefile +++ b/trick_source/sim_services/MemoryManager/test/Makefile @@ -14,10 +14,21 @@ TRICK_SYSTEM_CXXFLAGS := $(subst -isystem,-I,$(TRICK_SYSTEM_CXXFLAGS)) #TRICK_SYSTEM_LDFLAGS += ${COVERAGE_FLAGS} # Flags passed to the preprocessor. -TRICK_CPPFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra ${COVERAGE_FLAGS} -std=c++11 ${TRICK_SYSTEM_CXXFLAGS} +TRICK_CPPFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra -Wno-sign-compare ${COVERAGE_FLAGS} -std=c++11 ${TRICK_SYSTEM_CXXFLAGS} TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick -ltrick_mm -ltrick_units -ltrick TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main -lpthread +# This is supposed to be a development hack so that I don't have to clean rebuild Trick every time I change the stl_checkpoint files. +# This should be deleted before it is merged into master. +STL_CHECKPOINT_FILES = checkpoint_pair.hh \ + checkpoint_sequence_stl.hh \ + checkpoint_map.hh \ + checkpoint_queue.hh \ + checkpoint_stack.hh + +STL_CHECKPOINT_DEPS = $(addprefix $(TRICK_HOME)/include/trick/, $(STL_CHECKPOINT_FILES)) + + # All tests produced by this Makefile. Remember to add new tests you # created to the list. TESTS = MM_creation_unittest \ @@ -37,7 +48,9 @@ TESTS = MM_creation_unittest \ MM_write_checkpoint_hexfloat \ MM_get_enumerated\ MM_ref_name_from_address \ - Bitfield_tests + Bitfield_tests \ + MM_stl_checkpoint \ + MM_stl_restore #OTHER_OBJECTS = ../../include/object_${TRICK_HOST_CPU}/io_JobData.o \ # ../../include/object_${TRICK_HOST_CPU}/io_SimObject.o @@ -65,6 +78,9 @@ test: $(TESTS) ./MM_get_enumerated --gtest_output=xml:${TRICK_HOME}/trick_test/MM_get_enumerated.xml ./MM_ref_name_from_address --gtest_output=xml:${TRICK_HOME}/trick_test/MM_ref_name_from_address.xml ./Bitfield_tests --gtest_output=xml:${TRICK_HOME}/trick_test/Bitfield_tests.xml + ./MM_stl_checkpoint --gtest_output=xml:${TRICK_HOME}/trick_test/MM_stl_checkpoint.xml + ./MM_stl_restore --gtest_output=xml:${TRICK_HOME}/trick_test/MM_stl_restore.xml + code-coverage: test # Give rid of any old code-coverage HTML we may have. @@ -112,6 +128,10 @@ io_MM_ref_name_from_address.o : MM_ref_name_from_address.hh ${TRICK_HOME}/bin/trick-ICG -sim_services -o ./io_src $(TRICK_CPPFLAGS) $< $(TRICK_CXX) $(TRICK_CPPFLAGS) -c io_src/io_MM_ref_name_from_address.cpp +io_MM_stl_testbed.o : MM_stl_testbed.hh + ${TRICK_HOME}/bin/trick-ICG -sim_services -o ./io_src $(TRICK_CPPFLAGS) $< + $(TRICK_CXX) $(TRICK_CPPFLAGS) -c io_src/io_MM_stl_testbed.cpp + MM_creation_unittest.o : MM_creation_unittest.cc $(TRICK_CXX) $(TRICK_CPPFLAGS) -c $< @@ -166,6 +186,12 @@ MM_write_checkpoint_hexfloat.o : MM_write_checkpoint_hexfloat.cc Bitfield_tests.o : Bitfield_tests.cpp $(TRICK_CXX) $(TRICK_CPPFLAGS) -c $< +MM_stl_restore.o : MM_stl_restore.cc MM_stl_testbed.hh MM_test.hh $(STL_CHECKPOINT_DEPS) + $(TRICK_CXX) $(TRICK_CPPFLAGS) -c $< + +MM_stl_checkpoint.o : MM_stl_checkpoint.cc MM_stl_testbed.hh MM_test.hh $(STL_CHECKPOINT_DEPS) + $(TRICK_CXX) $(TRICK_CPPFLAGS) -c $< + MM_creation_unittest : MM_creation_unittest.o $(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS) @@ -219,3 +245,9 @@ MM_write_checkpoint_hexfloat : MM_write_checkpoint_hexfloat.o io_MM_write_checkp Bitfield_tests : Bitfield_tests.o $(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS) + +MM_stl_restore : MM_stl_restore.o io_MM_stl_testbed.o + $(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS) + +MM_stl_checkpoint : MM_stl_checkpoint.o io_MM_stl_testbed.o + $(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS)