Skip to content

Commit

Permalink
Added comments
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhjp01 committed Jan 15, 2025
1 parent 2724325 commit b925f8d
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 20 deletions.
12 changes: 7 additions & 5 deletions include/cosim/serialization.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,16 @@ struct node_data_translator

}} // namespace cosim::serialization


/**
* Serializes `data` into CBOR format and writes it to the output stream `out`.
*/
std::ostream& operator<<(std::ostream& out, const cosim::serialization::node& data);

/**
* Reads CBOR stream from `in` and converts it to `data`.
*/
std::istream& operator>>(std::istream& in, cosim::serialization::node& data);

// Ordinarily, the following function would be in the `cosim::serialization`
// namespace and found by the compiler via ADL. This doesn't work here,
// because `cosim::serialization::node` is just an alias for a type in the
// `boost::property_tree` namespace.
/**
* Writes the contents of `data` to the output stream `out` in a human-readable
* format.
Expand All @@ -119,6 +120,7 @@ std::istream& operator>>(std::istream& in, cosim::serialization::node& data);
*/
void print_ptree(std::ostream& out, const cosim::serialization::node& data);


// Make node_translator the default translator for property trees whose data
// type is node_data.
namespace boost
Expand Down
8 changes: 4 additions & 4 deletions src/cosim/serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ namespace
std::fill_n(std::ostream_iterator<char>(out), n, ' ');
}

void print_tree(
void _print_ptree(
std::ostream& out,
const cosim::serialization::node& tree,
int indent,
Expand All @@ -86,13 +86,13 @@ namespace
out << "{\n";
print_n_spaces(out, indent + indentStep);
out << child->first << " = ";
print_tree(out, child->second, indent + indentStep, indentStep);
_print_ptree(out, child->second, indent + indentStep, indentStep);
++child;
for (; child != tree.end(); ++child) {
out << ",\n";
print_n_spaces(out, indent + indentStep);
out << child->first << " = ";
print_tree(out, child->second, indent + indentStep, indentStep);
_print_ptree(out, child->second, indent + indentStep, indentStep);
}
out << '\n';
print_n_spaces(out, indent);
Expand Down Expand Up @@ -588,5 +588,5 @@ std::istream& operator>>(std::istream& in, cosim::serialization::node& root)
void print_ptree(std::ostream& out, const cosim::serialization::node& data)
{
constexpr int indentStep = 2;
print_tree(out, data, 0, indentStep);
_print_ptree(out, data, 0, indentStep);
}
1 change: 0 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ set(tests
"scenario_manager_test"
"synchronized_xy_series_test"
"config_end_time_test"
"state_serialization_test"
)

set(unittests
Expand Down
118 changes: 108 additions & 10 deletions tests/save_state_test.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
#include "mock_slave.hpp"

#include <cosim/algorithm.hpp>
#include <cosim/execution.hpp>
#include <cosim/osp_config_parser.hpp>
#include <cosim/log/simple.hpp>
#include <cosim/observer/last_value_observer.hpp>
#include <cosim/observer/time_series_observer.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <cosim/serialization.hpp>

#include <exception>
#include <limits>
#include <memory>
#include <stdexcept>
#include <iostream>
#include <chrono>
#include <sstream>


// A helper macro to test various assertions
Expand All @@ -33,21 +38,82 @@ std::vector<double> get_reals(
return values;
}


int main()
{
try {
cosim::log::setup_simple_console_logging();
cosim::log::set_global_output_level(cosim::log::debug);

// ================================================================
// == Reference FMU test - BouncingBall (for byte vectors)
// ================================================================
constexpr cosim::duration stepSize = cosim::to_duration(0.05);

const auto testDataDir = std::getenv("TEST_DATA_DIR");
REQUIRE(testDataDir);
auto configPath = cosim::filesystem::path(testDataDir) / "msmi" / "OspSystemStructure_BouncingBall.xml";

auto resolver = cosim::default_model_uri_resolver();
const auto config = cosim::load_osp_config(configPath, *resolver);
auto execution = cosim::execution(
config.start_time,
std::make_shared<cosim::fixed_step_algorithm>(config.step_size));

const auto entityMaps = cosim::inject_system_structure(
execution, config.system_structure, config.initial_values);

auto obs = std::make_shared<cosim::last_value_observer>();
execution.add_observer(obs);

const auto timeRef = 0;
const auto heightRef = 1;
const auto velocityRef = 3;

execution.simulate_until(cosim::to_time_point(0.5));
auto timeValues = get_reals(*obs, {0}, timeRef);
auto heightValues = get_reals(*obs, {0}, heightRef);
auto velocityValues = get_reals(*obs, {0}, velocityRef);

const auto state_bb = execution.export_current_state();

// Export state
std::ofstream outFile("state_bb.bin", std::ios::binary);
outFile << state_bb;
outFile.close();

execution.simulate_until(cosim::to_time_point(0.5));

// import state
std::ifstream inFile("state_bb.bin", std::ios::binary);
cosim::serialization::node state_bb_imported;
inFile >> state_bb_imported;
inFile.close();

execution.import_state(state_bb_imported);
auto state_bb_2 = execution.export_current_state();

auto timeValues2 = get_reals(*obs, {0}, timeRef);
auto heightValues2 = get_reals(*obs, {0}, heightRef);
auto velocityValues2 = get_reals(*obs, {0}, velocityRef);

REQUIRE(timeValues == timeValues2);
REQUIRE(heightValues == heightValues2);
REQUIRE(velocityValues == velocityValues2);

REQUIRE(state_bb_2 == state_bb_imported);
REQUIRE(state_bb == state_bb_imported);


// ================================================================
// == Mockup tests
// ================================================================
constexpr int simulatorCount = 10;
constexpr cosim::time_point time0;
constexpr cosim::time_point time1 = cosim::to_time_point(0.6);
constexpr cosim::time_point time2 = cosim::to_time_point(1.0);
constexpr cosim::duration stepSize = cosim::to_duration(0.05);

// Set up execution
auto execution = cosim::execution(
execution = cosim::execution(
time0,
std::make_unique<cosim::fixed_step_algorithm>(stepSize, 1));

Expand All @@ -57,7 +123,6 @@ int main()
const cosim::value_reference realOutRef = mock_slave::real_out_reference;
const cosim::value_reference realInRef = mock_slave::real_in_reference;


// Add and connect subsimulators
std::vector<cosim::simulator_index> simulators;
simulators.push_back(
Expand All @@ -83,35 +148,68 @@ int main()
auto state0Values = get_reals(*observer, simulators, realOutRef);
const auto state0 = execution.export_current_state();

// Write state0 to a file
outFile = std::ofstream("state0.bin", std::ios::binary);
outFile << state0;
outFile.close();

// Advance to time1 and save state again
execution.simulate_until(time1);
auto state1Values = get_reals(*observer, simulators, realOutRef);
const auto state1 = execution.export_current_state();

// Write state1 to a file
outFile = std::ofstream("state1.bin", std::ios::binary);
outFile << state1;
outFile.close();
REQUIRE(state1Values > state0Values);

// Advance to time2 and save state again
execution.simulate_until(time2);
auto state2Values = get_reals(*observer, simulators, realOutRef);
const auto state2 = execution.export_current_state();

// Write state2 to a file
outFile = std::ofstream("state2.bin", std::ios::binary);
outFile << state2;
outFile.close();
REQUIRE(state2Values > state1Values);

// Restore state0 and compare values
execution.import_state(state0);
// Restore state0 from file and compare values
cosim::serialization::node state0_a;
inFile = std::ifstream("state0.bin", std::ios::binary);
inFile >> state0_a;
inFile.close();
REQUIRE(state0_a == state0);

execution.import_state(state0_a);

REQUIRE(execution.current_time() == time0);
auto state0ValuesAgain = get_reals(*observer, simulators, realOutRef);
REQUIRE(state0ValuesAgain == state0Values);

// Advance to time1 again and compare values
cosim::serialization::node state1_a;
inFile = std::ifstream("state1.bin", std::ios::binary);
inFile >> state1_a;
inFile.close();
REQUIRE(state1_a == state1);

execution.simulate_until(time1);
auto state1ValuesAgain = get_reals(*observer, simulators, realOutRef);
REQUIRE(state1ValuesAgain == state1Values);

// Restore state2 and compare values
execution.import_state(state2);
// Restore state2 from file and compare values
cosim::serialization::node state2_a;
inFile = std::ifstream("state2.bin", std::ios::binary);
inFile >> state2_a;
inFile.close();
REQUIRE(state2_a == state2);

execution.import_state(state2_a);
REQUIRE(execution.current_time() == time2);
auto state2ValuesAgain = get_reals(*observer, simulators, realOutRef);
REQUIRE(state2ValuesAgain == state2Values);

} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
Expand Down

0 comments on commit b925f8d

Please sign in to comment.