Quellcode durchsuchen

Added SerializableJSONStateMachine class

- added SerializableJSONStateMachine class to provide functionality to serialize StateMachine class
- added tests for SerializableJSONStateMachine class
Patrick-Laptop vor 3 Jahren
Ursprung
Commit
1145101134

+ 3 - 3
CMakeLists.txt

@@ -103,8 +103,8 @@ set(SOURCE_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONStateConnection.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONState.hpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONState.cpp
-#        ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONStateMachine.hpp
-#        ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONStateMachine.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONStateMachine.hpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONStateMachine.cpp
         )
 
 set(TEST_FILES
@@ -137,7 +137,7 @@ set(TEST_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/logic/StateConnectionTest.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/json/logic/SerializableJSONStateConnectionTest.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/json/logic/SerializableJSONStateTest.cpp
-#        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/json/logic/SerializableJSONStateMachineTest.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/json/logic/SerializableJSONStateMachineTest.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/TestDataFactory.hpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/TestDataFactory.cpp)
 

+ 73 - 0
source/serialization/json/logic/SerializableJSONStateMachine.cpp

@@ -0,0 +1,73 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-09-17
+ * Changed:         2020-09-17
+ *
+ * */
+
+#include "SerializableJSONStateMachine.hpp"
+#include "SerializableJSONState.hpp"
+
+ls_std::SerializableJSONStateMachine::SerializableJSONStateMachine(std::shared_ptr<StateMachine> _value) :
+Class("SerializableJSONStateMachine"),
+value(std::move(_value))
+{}
+
+ls_std::byte_field ls_std::SerializableJSONStateMachine::marshal()
+{
+  this->_update();
+  return this->jsonObject.dump();
+}
+
+void ls_std::SerializableJSONStateMachine::unmarshal(const ls_std::byte_field &_data)
+{
+  this->jsonObject = nlohmann::json::parse(_data);
+
+  this->_unmarshalStates();
+  this->_unmarshalCurrentState();
+  this->value->setMemory(this->jsonObject["memory"]);
+  this->value->setName(this->jsonObject["name"]);
+}
+
+void ls_std::SerializableJSONStateMachine::_unmarshalCurrentState()
+{
+  if(this->jsonObject.contains("currentState")) {
+    this->value->setStartState(this->jsonObject["currentState"]);
+  }
+}
+
+void ls_std::SerializableJSONStateMachine::_unmarshalStates()
+{
+  for(const auto& serializedState : this->jsonObject["states"]) {
+    std::shared_ptr<ls_std::State> state = std::make_shared<ls_std::State>("");
+    ls_std::SerializableJSONState{state}.unmarshal(serializedState.dump());
+    this->value->addState(state);
+  }
+}
+
+void ls_std::SerializableJSONStateMachine::_update()
+{
+  this->_updateCurrentState();
+  this->jsonObject["memory"] = this->value->getMemory();
+  this->jsonObject["name"] = this->value->getName();
+  this->_updateStates();
+}
+
+void ls_std::SerializableJSONStateMachine::_updateCurrentState()
+{
+  if(this->value->getCurrentState() != nullptr) {
+    this->jsonObject["currentState"] = this->value->getCurrentState()->getId();
+  }
+}
+
+void ls_std::SerializableJSONStateMachine::_updateStates()
+{
+  std::string jsonString {};
+
+  for(const auto& state : this->value->getStates()) {
+    jsonString = ls_std::SerializableJSONState{state.second}.marshal();
+    this->jsonObject["states"][state.first] = nlohmann::json::parse(jsonString);
+  }
+}

+ 42 - 0
source/serialization/json/logic/SerializableJSONStateMachine.hpp

@@ -0,0 +1,42 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-09-17
+ * Changed:         2020-09-17
+ *
+ * */
+
+#ifndef LS_STD_SERIALIZABLE_JSON_STATE_MACHINE_HPP
+#define LS_STD_SERIALIZABLE_JSON_STATE_MACHINE_HPP
+
+#include "../../../base/Class.hpp"
+#include "../../ISerializable.hpp"
+#include "../../../logic/StateMachine.hpp"
+#include <memory>
+#include <json.hpp>
+
+namespace ls_std {
+  class SerializableJSONStateMachine : public Class, public ISerializable {
+    public:
+
+      explicit SerializableJSONStateMachine(std::shared_ptr<StateMachine> _value);
+      ~SerializableJSONStateMachine() = default;
+
+      ls_std::byte_field marshal() override;
+      void unmarshal(const ls_std::byte_field& _data) override;
+
+    private:
+
+      nlohmann::json jsonObject {};
+      std::shared_ptr<ls_std::StateMachine> value {};
+
+      void _unmarshalCurrentState();
+      void _unmarshalStates();
+      void _update();
+      void _updateCurrentState();
+      void _updateStates();
+  };
+}
+
+#endif

+ 104 - 0
test/cases/serialization/json/logic/SerializableJSONStateMachineTest.cpp

@@ -0,0 +1,104 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-09-17
+ * Changed:         2020-09-17
+ *
+ * */
+
+#include <gtest/gtest.h>
+#include "../../../../../source/boxing/String.hpp"
+#include "../../../../../source/logic/StateMachine.hpp"
+#include "../../../../../source/serialization/json/logic/SerializableJSONStateMachine.hpp"
+#include "../../../../TestDataFactory.hpp"
+#include "../../../../../source/io/File.hpp"
+#include "../../../../TestHelper.hpp"
+#include "../../../../../source/io/FileReader.hpp"
+
+namespace {
+  class SerializableJSONStateMachineTest : public ::testing::Test {
+    protected:
+
+      SerializableJSONStateMachineTest() = default;
+      ~SerializableJSONStateMachineTest() override = default;
+
+      void SetUp() override {}
+      void TearDown() override {}
+  };
+
+  // implementation
+
+  TEST_F(SerializableJSONStateMachineTest, marshal)
+  {
+    ls_std::StateMachine stateMachine = ls_std_test::TestDataFactory::createStateMachine();
+    stateMachine.setStartState("A");
+    stateMachine.setMemory({"A", "B", "C"});
+    ls_std::SerializableJSONStateMachine serializable {std::make_shared<ls_std::StateMachine>(stateMachine)};
+
+    std::string jsonString = serializable.marshal();
+    ASSERT_TRUE(!jsonString.empty());
+
+    ls_std::File file {TestHelper::getResourcesFolderLocation() + "/state_machine_test.json"};
+    ls_std::FileReader reader {file};
+    ls_std::String data {reader.read()};
+
+    ASSERT_TRUE(data.contains(jsonString));
+  }
+
+  TEST_F(SerializableJSONStateMachineTest, unmarshal)
+  {
+    ls_std::File file {TestHelper::getResourcesFolderLocation() + "/state_machine_test.json"};
+    ls_std::FileReader reader {file};
+    std::shared_ptr<ls_std::StateMachine> x = std::make_shared<ls_std::StateMachine>("bla");
+    ls_std::SerializableJSONStateMachine serializable {x};
+
+    serializable.unmarshal(reader.read());
+
+    ASSERT_STREQ("test_machine", x->getName().c_str());
+
+    // check memory
+
+    ASSERT_FALSE(x->getMemory().empty());
+    ASSERT_EQ(3, x->getMemory().size());
+    ASSERT_STREQ("A", x->getMemory().at(0).c_str());
+    ASSERT_STREQ("B", x->getMemory().at(1).c_str());
+    ASSERT_STREQ("C", x->getMemory().at(2).c_str());
+
+    // check current state
+
+    ASSERT_TRUE(x->getCurrentState() != nullptr);
+    ASSERT_STREQ("A", x->getCurrentState()->getId().c_str());
+
+    // check states
+
+    ASSERT_TRUE(!x->getStates().empty());
+    ASSERT_EQ(5, x->getStates().size());
+
+    std::shared_ptr<ls_std::State> state = x->getStates().at("A");
+    ASSERT_STREQ("A", state->getId().c_str());
+    ASSERT_EQ(1, state->getConnectedStates().size());
+    ASSERT_STREQ("AB", state->getConnectedStates().at("AB")->getConnectionId().c_str());
+
+    state = x->getStates().at("B");
+    ASSERT_STREQ("B", state->getId().c_str());
+    ASSERT_EQ(2, state->getConnectedStates().size());
+    ASSERT_STREQ("BC", state->getConnectedStates().at("BC")->getConnectionId().c_str());
+    ASSERT_STREQ("BD", state->getConnectedStates().at("BD")->getConnectionId().c_str());
+
+    state = x->getStates().at("C");
+    ASSERT_STREQ("C", state->getId().c_str());
+    ASSERT_EQ(2, state->getConnectedStates().size());
+    ASSERT_STREQ("CB", state->getConnectedStates().at("CB")->getConnectionId().c_str());
+    ASSERT_STREQ("CE", state->getConnectedStates().at("CE")->getConnectionId().c_str());
+
+    state = x->getStates().at("D");
+    ASSERT_STREQ("D", state->getId().c_str());
+    ASSERT_EQ(1, state->getConnectedStates().size());
+    ASSERT_STREQ("DE", state->getConnectedStates().at("DE")->getConnectionId().c_str());
+
+    state = x->getStates().at("E");
+    ASSERT_STREQ("E", state->getId().c_str());
+    ASSERT_TRUE(state->getConnectedStates().empty());
+  }
+}

+ 1 - 0
test/resources/state_machine_test.json

@@ -0,0 +1 @@
+{"currentState":"A","memory":["A","B","C"],"name":"test_machine","states":{"A":{"connectedStates":{"AB":{"condition":false,"connectionId":"AB","stateId":"B"}},"id":"A"},"B":{"connectedStates":{"BC":{"condition":false,"connectionId":"BC","stateId":"C"},"BD":{"condition":false,"connectionId":"BD","stateId":"D"}},"id":"B"},"C":{"connectedStates":{"CB":{"condition":false,"connectionId":"CB","stateId":"B"},"CE":{"condition":false,"connectionId":"CE","stateId":"E"}},"id":"C"},"D":{"connectedStates":{"DE":{"condition":false,"connectionId":"DE","stateId":"E"}},"id":"D"},"E":{"id":"E"}}}