UpdateStrategy Refactor: 6. draft, now looks good, not fully tested

This commit is contained in:
2020-12-12 16:55:27 +01:00
parent bab5552e6f
commit c1ae30c89c
18 changed files with 990 additions and 290 deletions

View File

@ -1,8 +1,13 @@
add_executable(engine_test
update_test.cpp
run_test.cpp
service_system_test.cpp
default_service_test.cpp
update_strategy_test.cpp
default_us_test.cpp
#dependency_check_us_test.cpp
# old:
#update_test.cpp
#run_test.cpp
#service_test.cpp
#default_service_test.cpp
)
target_include_directories(engine_test PRIVATE ".")
@ -10,6 +15,7 @@ target_include_directories(engine_test PRIVATE ".")
target_link_libraries(engine_test
engine
gtest_main
gmock
)
add_test(NAME engine_test COMMAND engine_test)

View File

@ -0,0 +1,108 @@
#include "mm/update_strategies/update_strategy.hpp"
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <memory>
#include <mm/engine.hpp>
#include <mm/update_strategies/default_strategy.hpp>
#include <entt/core/hashed_string.hpp>
using ::testing::Return;
using ::testing::_;
class MockService : public MM::Services::Service {
public:
const char* name(void) override { return "MockService"; }
MOCK_METHOD(bool, enable, (MM::Engine& engine), (override));
MOCK_METHOD(void, disable, (MM::Engine& engine), (override));
MOCK_METHOD(std::vector<MM::UpdateStrategies::UpdateCreationInfo>, registerUpdates, (), (override));
};
TEST(default_update_strategy, simple_update) {
MM::Engine engine(std::make_unique<MM::UpdateStrategies::SingleThreadedDefault>());
engine.update();
}
TEST(default_update_strategy, service) {
class TmpMockService : public MockService {
public:
TmpMockService(void) {
EXPECT_CALL(*this, registerUpdates())
.Times(1);
EXPECT_CALL(*this, enable(_))
.Times(1);
ON_CALL(*this, enable(_))
.WillByDefault(Return(true));
EXPECT_CALL(*this, disable(_))
.Times(1);
}
};
{
MM::Engine engine(std::make_unique<MM::UpdateStrategies::SingleThreadedDefault>());
engine.addService<TmpMockService>();
ASSERT_TRUE(engine.enableService<TmpMockService>());
engine.disableService<TmpMockService>();
}
}
TEST(default_update_strategy, run_1) {
class TmpMockService : public MockService {
int& _counter;
public:
explicit TmpMockService(int& counter) : _counter(counter) {
EXPECT_CALL(*this, registerUpdates())
.Times(1);
ON_CALL(*this, registerUpdates())
.WillByDefault([this]() -> std::vector<MM::UpdateStrategies::UpdateCreationInfo> {
return {
{
"TmpMockService"_hs,
"TmpMockService",
[this](MM::Engine&) { _counter++; }
}
};
});
EXPECT_CALL(*this, enable(_))
.Times(1);
ON_CALL(*this, enable(_))
.WillByDefault(Return(true));
EXPECT_CALL(*this, disable(_))
.Times(1);
}
};
{
int counter = 1;
MM::Engine engine(std::make_unique<MM::UpdateStrategies::SingleThreadedDefault>());
ASSERT_EQ(counter, 1);
engine.addService<TmpMockService>(counter);
ASSERT_EQ(counter, 1);
ASSERT_TRUE(engine.enableService<TmpMockService>());
ASSERT_EQ(counter, 1);
engine.getUpdateStrategy().addDefered([](MM::Engine& e) { e.stop(); });
engine.run();
ASSERT_EQ(counter, 2);
engine.disableService<TmpMockService>();
ASSERT_EQ(counter, 2);
}
}

View File

@ -0,0 +1,144 @@
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <memory>
#include <stdexcept>
#include <mm/engine.hpp>
#include <mm/update_strategies/update_strategy.hpp>
#include <mm/update_strategies/dependency_check_decorater.hpp>
#include <mm/services/service.hpp>
using ::testing::Return;
using ::testing::_;
#include <entt/core/hashed_string.hpp>
//using namespace ::entt::literals;
class MockUpdateStrategy : public MM::UpdateStrategies::UpdateStrategy {
public:
MOCK_METHOD(
bool,
registerService,
(const entt::id_type s_id, std::vector<MM::UpdateStrategies::UpdateCreationInfo>&& info),
(override)
);
// protected:
MOCK_METHOD(void, doUpdate, (MM::Engine& engine), (override));
MOCK_METHOD(bool, enableService, (const entt::id_type s_id), (override));
MOCK_METHOD(bool, disableService, (const entt::id_type s_id), (override));
// public:
MOCK_METHOD(bool, enable, (const MM::UpdateStrategies::update_key_t key), (override));
MOCK_METHOD(bool, disable, (const MM::UpdateStrategies::update_key_t key), (override));
MOCK_METHOD(bool, depend, (const MM::UpdateStrategies::update_key_t A, const MM::UpdateStrategies::update_key_t B), (override));
MOCK_METHOD(void, addDefered, (std::function<void(MM::Engine&)> function), (override));
};
class MockService : public MM::Services::Service {
public:
const char* name(void) override { return "MockService"; }
MOCK_METHOD(bool, enable, (MM::Engine& engine), (override));
MOCK_METHOD(void, disable, (MM::Engine& engine), (override));
MOCK_METHOD(std::vector<MM::UpdateStrategies::UpdateCreationInfo>, registerUpdates, (), (override));
};
TEST(dependency_check_update_strategy, decoration_mock) {
auto dep = std::make_unique<MM::UpdateStrategies::DependencyCheckDecorator<MockUpdateStrategy>>();
auto* mock = static_cast<MockUpdateStrategy*>(dep.get());
EXPECT_CALL(*mock, registerService(_, _))
.Times(1);
EXPECT_CALL(*mock, enableService(_))
.Times(1);
EXPECT_CALL(*mock, disableService(_))
.Times(1);
class TmpMockService : public MockService {
public:
TmpMockService(void) {
EXPECT_CALL(*this, registerUpdates())
.Times(1);
EXPECT_CALL(*this, enable(_))
.Times(1);
ON_CALL(*this, enable(_))
.WillByDefault(Return(true));
EXPECT_CALL(*this, disable(_))
.Times(1);
}
};
{
MM::Engine engine(std::move(dep));
engine.addService<TmpMockService>();
ASSERT_TRUE(engine.enableService<TmpMockService>());
engine.disableService<TmpMockService>();
}
}
TEST(dependency_check_update_strategy, simple_loop) {
auto dep = std::make_unique<MM::UpdateStrategies::DependencyCheckDecorator<MockUpdateStrategy>>();
auto* mock = static_cast<MockUpdateStrategy*>(dep.get());
EXPECT_CALL(*mock, registerService(_, _))
.Times(1);
EXPECT_CALL(*mock, enableService(_))
.Times(1);
//EXPECT_CALL(*mock, disableService(_))
//.Times(1);
EXPECT_CALL(*mock, depend(_, _))
.Times(1); // the layer should catch the error before forwarding it
class BonkersService : public MM::Services::Service {
public:
virtual ~BonkersService(void) {}
const char* name(void) override { return "BonkersService"; }
bool enable(MM::Engine& engine) override {
engine.getUpdateStrategy().depend("BonkerA"_hs, "BonkerB"_hs);
// maleformed: direct cycle
engine.getUpdateStrategy().depend("BonkerB"_hs, "BonkerA"_hs);
return true;
}
void disable(MM::Engine&) override {}
std::vector<MM::UpdateStrategies::UpdateCreationInfo> registerUpdates(void) override {
return {
MM::UpdateStrategies::UpdateCreationInfo{
"BonkerA"_hs,
"BonkerA",
[](MM::Engine&) {}
},
MM::UpdateStrategies::UpdateCreationInfo{
"BonkerB"_hs,
"BonkerB",
[](MM::Engine&) {}
}
};
}
};
{
MM::Engine engine(std::move(dep));
engine.addService<BonkersService>();
ASSERT_THROW(engine.enableService<BonkersService>(), std::logic_error);
//engine.disableService<BonkersService>();
}
}

View File

@ -1,9 +1,10 @@
#include <gtest/gtest.h>
#include <memory>
#include <mm/engine.hpp>
TEST(engine_run, test_run) {
MM::Engine engine;
MM::Engine engine{std::make_unique};
bool run = false;

View File

@ -0,0 +1,140 @@
#include "mm/services/service.hpp"
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <memory>
#include <mm/engine.hpp>
#include <mm/update_strategies/update_strategy.hpp>
#include <entt/core/hashed_string.hpp>
using ::testing::Return;
using ::testing::_;
class MockUpdateStrategy : public MM::UpdateStrategies::UpdateStrategy {
public:
MOCK_METHOD(
bool,
registerService,
(const entt::id_type s_id, std::vector<MM::UpdateStrategies::UpdateCreationInfo>&& info),
(override)
);
// protected:
MOCK_METHOD(void, doUpdate, (MM::Engine& engine), (override));
MOCK_METHOD(bool, enableService, (const entt::id_type s_id), (override));
MOCK_METHOD(bool, disableService, (const entt::id_type s_id), (override));
// public:
MOCK_METHOD(bool, enable, (const MM::UpdateStrategies::update_key_t key), (override));
MOCK_METHOD(bool, disable, (const MM::UpdateStrategies::update_key_t key), (override));
MOCK_METHOD(bool, depend, (const MM::UpdateStrategies::update_key_t A, const MM::UpdateStrategies::update_key_t B), (override));
MOCK_METHOD(void, addDefered, (std::function<void(MM::Engine&)> function), (override));
};
class MockService : public MM::Services::Service {
public:
const char* name(void) override { return "MockService"; }
MOCK_METHOD(bool, enable, (MM::Engine& engine), (override));
MOCK_METHOD(void, disable, (MM::Engine& engine), (override));
MOCK_METHOD(std::vector<MM::UpdateStrategies::UpdateCreationInfo>, registerUpdates, (), (override));
};
TEST(engine_mock, update_strategy_run) {
auto mock = std::make_unique<MockUpdateStrategy>();
EXPECT_CALL(*mock, doUpdate(_))
.Times(1);
MM::Engine engine(std::move(mock));
engine.update();
}
TEST(engine_mock, service_update_strategy) {
auto mock = std::make_unique<MockUpdateStrategy>();
EXPECT_CALL(*mock, registerService(_, _))
.Times(1);
EXPECT_CALL(*mock, enableService(_))
.Times(1);
EXPECT_CALL(*mock, disableService(_))
.Times(1);
class TmpMockService : public MockService {
public:
TmpMockService(void) {
EXPECT_CALL(*this, registerUpdates())
.Times(1);
EXPECT_CALL(*this, enable(_))
.Times(1);
ON_CALL(*this, enable(_))
.WillByDefault(Return(true));
EXPECT_CALL(*this, disable(_))
.Times(1);
}
};
{
MM::Engine engine(std::move(mock));
engine.addService<TmpMockService>();
ASSERT_TRUE(engine.enableService<TmpMockService>());
engine.disableService<TmpMockService>();
}
}
TEST(engine_mock, service_update_strategy_run_1) {
auto mock = std::make_unique<MockUpdateStrategy>();
EXPECT_CALL(*mock, registerService(_, _))
.Times(1);
EXPECT_CALL(*mock, enableService(_))
.Times(1);
EXPECT_CALL(*mock, disableService(_))
.Times(1);
class TmpMockService : public MockService {
public:
explicit TmpMockService(void) {
EXPECT_CALL(*this, registerUpdates())
.Times(1);
ON_CALL(*this, registerUpdates())
.WillByDefault([]() -> std::vector<MM::UpdateStrategies::UpdateCreationInfo> {
return {
{
"TmpMockService"_hs,
"TmpMockService",
[](MM::Engine&) {}
}
};
});
EXPECT_CALL(*this, enable(_))
.Times(1);
ON_CALL(*this, enable(_))
.WillByDefault(Return(true));
EXPECT_CALL(*this, disable(_))
.Times(1);
}
};
{
MM::Engine engine(std::move(mock));
engine.addService<TmpMockService>();
ASSERT_TRUE(engine.enableService<TmpMockService>());
engine.disableService<TmpMockService>();
}
}

View File

@ -1,84 +1,123 @@
#include <gtest/gtest.h>
#include <memory>
#include <mm/engine.hpp>
//class MyUpdateStrategy : public MM::UpdateStrategy::UpdateStrategy {
//public:
//virtual ~MyUpdateStrategy(void) {}
//// return nullptr on error
//[[nodiscard]] MM::UpdateStrategy::FunctionDataHandle addUpdate(std::function<void(MM::Engine&)> fn) override {
//}
//[[nodiscard]] MM::UpdateStrategy::FunctionDataHandle addFixedUpdate(std::function<void(MM::Engine&)> fn) override {
//}
//// knows which one
//void removeUpdate(MM::UpdateStrategy::FunctionDataHandle handle) override {
//}
//// dont use, if you are not using it to modify the engine.
//// you usualy dont need to use this, if you think you need to use this, you probably dont.
//void addFixedDefered(std::function<void(MM::Engine&)> function) override {
//}
////virtual std::future addAsync(std::function<void(Engine&)> function) = 0;
//void doUpdate(MM::Engine& engine) override {
//}
//void doFixedUpdate(MM::Engine& engine) override {
//}
//};
class MyEngine : public MM::Engine {
public:
MyEngine(void) : MM::Engine(std::make_unique<MyUpdateStrategy>()) {
}
};
TEST(engine_fixed_update, empty_add_rm) {
MM::Engine engine;
MyEngine engine;
auto test_fun = [](auto&) {};
auto handle = engine.addFixedUpdate(test_fun);
auto handle = engine.getUpdateStrategy().addFixedUpdate(test_fun);
ASSERT_NE(handle.lock(), nullptr);
handle.lock()->priority = 1;
//handle.lock()->priority = 1;
engine.removeFixedUpdate(handle);
engine.getUpdateStrategy().removeUpdate(handle);
}
TEST(engine_update, empty_add_rm) {
MM::Engine engine;
MyEngine engine;
auto test_fun = [](auto&) {};
auto handle = engine.addUpdate(test_fun);
auto handle = engine.getUpdateStrategy().addUpdate(test_fun);
ASSERT_NE(handle.lock(), nullptr);
handle.lock()->priority = 1;
//handle.lock()->priority = 1;
engine.removeUpdate(handle);
engine.getUpdateStrategy().removeUpdate(handle);
}
TEST(engine_fixed_update, empty_run) {
MM::Engine engine;
MyEngine engine;
auto test_fun = [](auto&) {};
auto handle = engine.addFixedUpdate(test_fun);
auto handle = engine.getUpdateStrategy().addFixedUpdate(test_fun);
ASSERT_NE(handle.lock(), nullptr);
handle.lock()->priority = 1;
//handle.lock()->priority = 1;
engine.fixedUpdate(); // single update
engine.removeFixedUpdate(handle);
engine.getUpdateStrategy().removeUpdate(handle);
}
TEST(engine_update, empty_run) {
MM::Engine engine;
MyEngine engine;
auto test_fun = [](auto&) {};
auto handle = engine.addUpdate(test_fun);
auto handle = engine.getUpdateStrategy().addUpdate(test_fun);
ASSERT_NE(handle.lock(), nullptr);
handle.lock()->priority = 1;
//handle.lock()->priority = 1;
engine.update();
engine.removeUpdate(handle);
engine.getUpdateStrategy().removeUpdate(handle);
}
TEST(engine_fixed_update, test_run) {
MM::Engine engine;
MyEngine engine;
bool run = false;
auto test_fun = [&run](auto&) { run = true; };
auto handle = engine.addFixedUpdate(test_fun);
auto handle = engine.getUpdateStrategy().addFixedUpdate(test_fun);
ASSERT_NE(handle.lock(), nullptr);
handle.lock()->priority = 1;
//handle.lock()->priority = 1;
ASSERT_FALSE(run);
engine.fixedUpdate(); // single update
ASSERT_TRUE(run);
engine.removeFixedUpdate(handle);
engine.getUpdateStrategy().removeUpdate(handle);
}
#if 0
TEST(engine_update, test_run) {
MM::Engine engine;
MyEngine engine;
bool run = false;
@ -97,7 +136,7 @@ TEST(engine_update, test_run) {
}
TEST(engine_fixed_update, test_order_run) {
MM::Engine engine;
MyEngine engine;
bool run1 = false;
bool run2 = false;
@ -228,3 +267,4 @@ TEST(engine_update, test_order_rev_run) {
engine.removeUpdate(handle2);
}
#endif