Parcourir la source

Add new unit tests for new formalism fddevs

Eric Ramat il y a 4 ans
Parent
commit
73d8e08c51

+ 1 - 0
src/tests/CMakeLists.txt

@@ -1,6 +1,7 @@
 ADD_SUBDIRECTORY(common)
 ADD_SUBDIRECTORY(dsde)
 ADD_SUBDIRECTORY(dtss)
+ADD_SUBDIRECTORY(fddevs)
 ADD_SUBDIRECTORY(mixed)
 ADD_SUBDIRECTORY(mpi)
 ADD_SUBDIRECTORY(multithreading)

+ 14 - 0
src/tests/fddevs/CMakeLists.txt

@@ -0,0 +1,14 @@
+add_definitions(-DWITH_TRACE)
+
+INCLUDE_DIRECTORIES(
+        ${CMAKE_SOURCE_DIR}/src
+        ${ARTIS_INCLUDE_DIRS}
+        ${Boost_INCLUDE_DIRS})
+
+LINK_DIRECTORIES()
+
+ADD_EXECUTABLE(fddevs-tests graph_manager.hpp models.hpp tests.cpp)
+
+TARGET_LINK_LIBRARIES(fddevs-tests
+        ${Boost_SYSTEM_LIBRARY}
+        ${Boost_TIMER_LIBRARY})

+ 75 - 0
src/tests/fddevs/graph_manager.hpp

@@ -0,0 +1,75 @@
+/**
+ * @file tests/fddevs/graph_manager.cpp
+ * @author The ARTIS Development Team
+ * See the AUTHORS or Authors.txt file
+ */
+
+/*
+ * ARTIS - the multimodeling and simulation environment
+ * This file is a part of the ARTIS environment
+ *
+ * Copyright (C) 2013-2019 ULCO http://www.univ-littoral.fr
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TESTS_FDDEVS_GRAPH_MANAGER_HPP
+#define TESTS_FDDEVS_GRAPH_MANAGER_HPP
+
+#include <tests/fddevs/models.hpp>
+
+#include <artis-star/kernel/fddevs/Coordinator.hpp>
+#include <artis-star/kernel/fddevs/GraphManager.hpp>
+#include <artis-star/kernel/fddevs/Simulator.hpp>
+
+namespace artis {
+    namespace tests {
+        namespace fddevs {
+
+            class FlatGraphManager :
+                    public artis::fddevs::GraphManager<common::DoubleTime> {
+            public:
+                enum submodels {
+                    M_BEEP, M_CRC, M_MXR,
+                };
+
+                FlatGraphManager(common::Coordinator<common::DoubleTime>* coordinator,
+                        const artis::common::NoParameters& parameters,
+                        const artis::common::NoParameters& graph_parameters)
+                        :
+                        artis::fddevs::GraphManager<common::DoubleTime>(coordinator, parameters, graph_parameters),
+                        _beep("beep", parameters), _crc("crc", parameters), _mxr("mxr", parameters)
+                {
+                    add_child(M_BEEP, &_beep);
+                    add_child(M_CRC, &_crc);
+                    add_child(M_MXR, &_mxr);
+
+                    out({&_beep, Beep::OUT_P}) >> in({&_crc, CRC::IN_P});
+                    out({&_crc, CRC::OUT_G}) >> in({&_mxr, MXR::IN_A});
+                    out({&_crc, CRC::OUT_W}) >> in({&_mxr, MXR::IN_B});
+                }
+
+                ~FlatGraphManager() override = default;
+
+            private:
+                artis::fddevs::Simulator<common::DoubleTime, Beep> _beep;
+                artis::fddevs::Simulator<common::DoubleTime, CRC> _crc;
+                artis::fddevs::Simulator<common::DoubleTime, MXR> _mxr;
+            };
+
+        }
+    }
+} // namespace artis tests fddevs
+
+#endif

+ 352 - 0
src/tests/fddevs/models.hpp

@@ -0,0 +1,352 @@
+/**
+ * @file tests/fddevs/models.hpp
+ * @author The ARTIS Development Team
+ * See the AUTHORS or Authors.txt file
+ */
+
+/*
+ * ARTIS - the multimodeling and simulation environment
+ * This file is a part of the ARTIS environment
+ *
+ * Copyright (C) 2013-2019 ULCO http://www.univ-littoral.fr
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TESTS_FDDEVS_MODELS_HPP
+#define TESTS_FDDEVS_MODELS_HPP
+
+#include <artis-star/common/time/DoubleTime.hpp>
+#include <artis-star/common/utils/Trace.hpp>
+
+#include <artis-star/kernel/fddevs/Dynamics.hpp>
+
+namespace artis {
+    namespace tests {
+        namespace fddevs {
+
+            enum CRC_state_values {
+                I0 = 0, I1, G, GR, WW, W, DW
+            };
+
+            class CRC : public artis::fddevs::Dynamics<common::DoubleTime, CRC, CRC_state_values> {
+            public:
+                enum inputs {
+                    IN_P
+                };
+                enum outputs {
+                    OUT_G, OUT_W
+                };
+
+                CRC(const std::string& name,
+                        const artis::fddevs::Context<common::DoubleTime, CRC, artis::common::NoParameters>& context)
+                        :
+                        artis::fddevs::Dynamics<common::DoubleTime, CRC, CRC_state_values>(name,
+                                context)
+                {
+                    input_ports({{IN_P, "p"}});
+                    output_ports({{OUT_G, "g"},
+                                  {OUT_W, "w"}});
+
+                    initial_state(I0);
+                }
+
+                ~CRC() override = default;
+
+                void delta_tau(typename common::DoubleTime::type /* t */) override
+                {
+                    switch (state()) {
+                    case I0: {
+                        state(I1);
+                        break;
+                    }
+                    case I1: {
+                        state(G);
+                        break;
+                    }
+                    case G: {
+                        state(G);
+                        break;
+                    }
+                    case GR: {
+                        state(WW);
+                        break;
+                    }
+                    case WW: {
+                        state(W);
+                        break;
+                    }
+                    case W: {
+                        state(DW);
+                        break;
+                    }
+                    case DW: {
+                        state(G);
+                        break;
+                    }
+                    }
+                }
+
+                void
+                delta_x(typename common::DoubleTime::type /* t */,
+                        typename common::DoubleTime::type /* e */,
+                        const common::Bag<common::DoubleTime>& bag) override
+                {
+                    assert(bag.size() == 1);
+
+                    if (bag.at(0).on_port(IN_P) and state() == G) {
+                        state(GR);
+                    }
+                }
+
+                common::Bag<common::DoubleTime>
+                lambda(typename common::DoubleTime::type /* t */) const override
+                {
+                    common::Bag<common::DoubleTime> msgs;
+
+                    switch (state()) {
+                    case I0:
+                        msgs.push_back(
+                                artis::common::ExternalEvent<common::DoubleTime>(OUT_W, 0));
+                        break;
+                    case I1:
+                        msgs.push_back(
+                                artis::common::ExternalEvent<common::DoubleTime>(OUT_G, 1));
+                        break;
+                    case G:
+                        break;
+                    case GR:
+                        msgs.push_back(
+                                artis::common::ExternalEvent<common::DoubleTime>(OUT_G, 0));
+                        break;
+                    case WW:
+                        msgs.push_back(
+                                artis::common::ExternalEvent<common::DoubleTime>(OUT_W, 1));
+                        break;
+                    case W:
+                        msgs.push_back(
+                                artis::common::ExternalEvent<common::DoubleTime>(OUT_W, 0));
+                        break;
+                    case DW:
+                        msgs.push_back(
+                                artis::common::ExternalEvent<common::DoubleTime>(OUT_G, 1));
+                        break;
+                    }
+                    return msgs;
+                }
+
+                bool rho(typename common::DoubleTime::type /* time */,
+                        const common::Bag<common::DoubleTime>& bag) const override
+                {
+                    return state() == G and bag.at(0).on_port(IN_P);
+                }
+
+                typename common::DoubleTime::type
+                tau(typename common::DoubleTime::type /* t */) const override
+                {
+                    switch (state()) {
+                    case I0:
+                        return 0;
+                    case I1:
+                        return 0;
+                    case G:
+                        return 10;
+                    case GR:
+                        return 5;
+                    case WW:
+                        return 2;
+                    case W:
+                        return 26;
+                    case DW:
+                        return 2;
+                    }
+                    return common::DoubleTime::infinity;
+                }
+            };
+
+            enum MXR_state_values {
+                A00 = 0, A01, A10, A11, R11
+            };
+
+            class MXR : public artis::fddevs::Dynamics<common::DoubleTime, MXR, MXR_state_values> {
+            public:
+                enum inputs {
+                    IN_A, IN_B
+                };
+
+                MXR(const std::string& name,
+                        const artis::fddevs::Context<common::DoubleTime, MXR, artis::common::NoParameters>& context)
+                        :
+                        artis::fddevs::Dynamics<common::DoubleTime, MXR, MXR_state_values>(name,
+                                context)
+                {
+                    input_ports({{IN_A, "a"},
+                                 {IN_B, "b"}});
+                    initial_state(A00);
+                }
+
+                ~MXR() override = default;
+
+                void delta_tau(typename common::DoubleTime::type /* t */) override
+                {
+                    if (state() == A11) { state(R11); }
+                }
+
+                void
+                delta_x(typename common::DoubleTime::type /* t */,
+                        typename common::DoubleTime::type /* e */,
+                        const common::Bag<common::DoubleTime>& bag) override
+                {
+                    std::for_each(bag.begin(), bag.end(),
+                            [this](const artis::common::ExternalEvent<common::DoubleTime>& e) {
+                                int data;
+
+                                e.data()(data);
+                                if (e.on_port(IN_A)) {
+                                    switch (state()) {
+                                    case A00: {
+                                        if (data == 1) { state(A01); }
+                                        break;
+                                    }
+                                    case A01: {
+                                        if (data == 0) { state(A00); }
+                                        break;
+                                    }
+                                    case A10: {
+                                        if (data == 1) { state(A11); }
+                                        break;
+                                    }
+                                    case A11: {
+                                        if (data == 0) { state(A10); }
+                                        break;
+                                    }
+                                    case R11:
+                                        break;
+                                    }
+                                } else if (e.on_port(IN_B)) {
+                                    switch (state()) {
+                                    case A00: {
+                                        if (data == 1) { state(A10); }
+                                        break;
+                                    }
+                                    case A01: {
+                                        if (data == 1) { state(A11); }
+                                        break;
+                                    }
+                                    case A10: {
+                                        if (data == 0) { state(A00); }
+                                        break;
+                                    }
+                                    case A11: {
+                                        if (data == 0) { state(A01); }
+                                        break;
+                                    }
+                                    case R11:
+                                        break;
+                                    }
+                                }
+                            });
+                }
+
+                common::Bag<common::DoubleTime>
+                lambda(typename common::DoubleTime::type /* t */) const override
+                {
+                    common::Bag<common::DoubleTime> msgs;
+
+                    return msgs;
+                }
+
+                bool rho(typename common::DoubleTime::type /* time */,
+                        const common::Bag<common::DoubleTime>& /* bag */) const override
+                {
+                    return false;
+                }
+
+                typename common::DoubleTime::type
+                tau(typename common::DoubleTime::type /* t */) const override
+                {
+                    if (state() == A11) { return 0.01; }
+                    else { return common::DoubleTime::infinity; }
+                }
+            };
+
+            enum Beep_state_values {
+                INIT = 0, SEND
+            };
+
+            class Beep
+                    : public artis::fddevs::Dynamics<common::DoubleTime, Beep, Beep_state_values> {
+            public:
+                enum outputs {
+                    OUT_P
+                };
+
+                Beep(const std::string& name,
+                        const artis::fddevs::Context<common::DoubleTime, Beep, artis::common::NoParameters>& context)
+                        :
+                        artis::fddevs::Dynamics<common::DoubleTime, Beep, Beep_state_values>(name,
+                                context)
+                {
+                    output_ports({{OUT_P, "p"}});
+
+                    initial_state(INIT);
+                }
+
+                ~Beep() override = default;
+
+                void delta_tau(typename common::DoubleTime::type /* t */) override
+                {
+                    if (state() == INIT) { state(SEND); }
+                }
+
+                common::Bag<common::DoubleTime>
+                lambda(typename common::DoubleTime::type /* t */) const override
+                {
+                    common::Bag<common::DoubleTime> msgs;
+
+                    switch (state()) {
+                    case INIT:
+                        msgs.push_back(
+                                artis::common::ExternalEvent<common::DoubleTime>(OUT_P, 1));
+                        break;
+                    case SEND:
+                        break;
+                    }
+                    return msgs;
+                }
+
+                bool rho(typename common::DoubleTime::type /* time */,
+                        const common::Bag<common::DoubleTime>& /* bag */) const override
+                {
+                    return false;
+                }
+
+                typename common::DoubleTime::type
+                tau(typename common::DoubleTime::type /* t */) const override
+                {
+                    switch (state()) {
+                    case INIT:
+                        return 27;
+                    case SEND:
+                        return common::DoubleTime::infinity;
+                    }
+                    return common::DoubleTime::infinity;
+                }
+            };
+
+        }
+    }
+} // namespace artis tests fddevs
+
+#endif

+ 100 - 0
src/tests/fddevs/tests.cpp

@@ -0,0 +1,100 @@
+/**
+ * @file tests/pdevs/tests.cpp
+ * @author The ARTIS Development Team
+ * See the AUTHORS or Authors.txt file
+ */
+
+/*
+ * ARTIS - the multimodeling and simulation environment
+ * This file is a part of the ARTIS environment
+ *
+ * Copyright (C) 2013-2019 ULCO http://www.univ-littoral.fr
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <tests/fddevs/graph_manager.hpp>
+#include <tests/fddevs/models.hpp>
+
+#include <artis-star/common/RootCoordinator.hpp>
+
+#define CATCH_CONFIG_MAIN
+
+#include <tests/catch.hpp>
+
+using namespace artis::tests::fddevs;
+using namespace artis::common;
+
+TEST_CASE("fddevs/cross road system", "run")
+{
+    context::Context<DoubleTime> context(0, 70);
+    RootCoordinator<
+            DoubleTime, artis::fddevs::Coordinator<
+                    DoubleTime,
+                    FlatGraphManager>
+    > rc(context, "root", NoParameters(), NoParameters());
+
+    Trace<DoubleTime>::trace().clear();
+    rc.run(context);
+
+    std::cout << Trace<DoubleTime>::trace().elements().filter_model_name("crc").to_string()
+              << std::endl;
+    std::cout << Trace<DoubleTime>::trace().elements().filter_model_name("mxr").to_string()
+              << std::endl;
+
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE).size() == 18);
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[0].get_comment() == ": BEFORE => tl = 0 ; tn = 0 ; S = 0");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[1].get_comment() == ": AFTER => tl = 0 ; tn = 0 ; S = 1");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[2].get_comment() == ": BEFORE => tl = 0 ; tn = 0 ; S = 1");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[3].get_comment() == ": AFTER => tl = 0 ; tn = 10 ; S = 2");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[4].get_comment() == ": BEFORE => tl = 0 ; tn = 10 ; S = 2");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[5].get_comment() == ": AFTER => tl = 10 ; tn = 20 ; S = 2");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[6].get_comment() == ": BEFORE => tl = 10 ; tn = 20 ; S = 2");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[7].get_comment() == ": AFTER => tl = 20 ; tn = 30 ; S = 2");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[8].get_comment() == ": BEFORE => tl = 20 ; tn = 30 ; S = 2");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[9].get_comment() == ": AFTER => tl = 27 ; tn = 32 ; S = 3");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[10].get_comment() == ": BEFORE => tl = 27 ; tn = 32 ; S = 3");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[11].get_comment() == ": AFTER => tl = 32 ; tn = 34 ; S = 4");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[12].get_comment() == ": BEFORE => tl = 32 ; tn = 34 ; S = 4");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[13].get_comment() == ": AFTER => tl = 34 ; tn = 60 ; S = 5");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[14].get_comment() == ": BEFORE => tl = 34 ; tn = 60 ; S = 5");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[15].get_comment() == ": AFTER => tl = 60 ; tn = 62 ; S = 6");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[16].get_comment() == ": BEFORE => tl = 60 ; tn = 62 ; S = 6");
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("crc").filter_function_type(
+            FunctionType::S_MESSAGE)[17].get_comment() == ": AFTER => tl = 62 ; tn = 72 ; S = 2");
+
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("mxr").filter_function_type(
+            FunctionType::S_MESSAGE).size() == 12);
+    REQUIRE(Trace<DoubleTime>::trace().elements().filter_model_name("mxr").filter_function_type(
+            FunctionType::POST_EVENT).size() == 12);
+
+}