From 0afb4efadca624bed5a230f2b04e2c3510c6580e Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Sun, 17 Mar 2024 11:21:45 +0100 Subject: [PATCH 1/4] Replace TestSection with BlockSectionMock --- test/engine/CMakeLists.txt | 2 -- test/engine/engine_test.cpp | 56 ++++++++++++++++++++++------------- test/engine/testsection.cpp | 14 --------- test/engine/testsection.h | 16 ---------- test/mocks/blocksectionmock.h | 15 ++++++++++ 5 files changed, 51 insertions(+), 52 deletions(-) delete mode 100644 test/engine/testsection.cpp delete mode 100644 test/engine/testsection.h create mode 100644 test/mocks/blocksectionmock.h diff --git a/test/engine/CMakeLists.txt b/test/engine/CMakeLists.txt index b8d97c5c..d669bda3 100644 --- a/test/engine/CMakeLists.txt +++ b/test/engine/CMakeLists.txt @@ -1,8 +1,6 @@ add_executable( engine_test engine_test.cpp - testsection.cpp - testsection.h ) target_link_libraries( diff --git a/test/engine/engine_test.cpp b/test/engine/engine_test.cpp index e4c59e7a..4ca5a801 100644 --- a/test/engine/engine_test.cpp +++ b/test/engine/engine_test.cpp @@ -17,10 +17,10 @@ #include #include #include +#include #include #include "../common.h" -#include "testsection.h" #include "engine/internal/engine.h" #include "engine/internal/clock.h" @@ -77,7 +77,8 @@ TEST(EngineTest, Clear) auto broadcast2 = std::make_shared("", ""); engine.setBroadcasts({ broadcast1, broadcast2 }); - auto section = std::make_shared(); + auto section = std::make_shared(); + EXPECT_CALL(*section, registerBlocks); engine.registerSection(section); auto monitor1 = std::make_shared("", ""); @@ -126,7 +127,8 @@ TEST(EngineTest, CompileAndExecuteMonitors) m2->setSprite(sprite.get()); engine.setMonitors({ m1, m2 }); - auto section = std::make_shared(); + auto section = std::make_shared(); + EXPECT_CALL(*section, registerBlocks); engine.registerSection(section); engine.addCompileFunction(section.get(), m1->opcode(), [](Compiler *compiler) { compiler->addConstValue(5.4); }); engine.addCompileFunction(section.get(), m2->opcode(), [](Compiler *compiler) { compiler->addConstValue("test"); }); @@ -859,12 +861,16 @@ TEST(EngineTest, Sections) { Engine engine; - auto section1 = std::make_shared(); + auto section1 = std::make_shared(); + EXPECT_CALL(*section1, registerBlocks(&engine)); engine.registerSection(section1); - auto section2 = std::make_shared(); + auto section2 = std::make_shared(); + EXPECT_CALL(*section2, registerBlocks(&engine)); engine.registerSection(section2); + EXPECT_CALL(*section1, name()).WillOnce(Return("test")); + EXPECT_CALL(*section1, registerBlocks).Times(0); engine.registerSection(section1); // register existing section ASSERT_EQ(engine.registeredSections().size(), 2); @@ -908,15 +914,17 @@ TEST(EngineTest, CompileFunctions) { Engine engine; - auto section1 = std::make_shared(); + auto section1 = std::make_shared(); + EXPECT_CALL(*section1, registerBlocks); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); - auto section2 = std::make_shared(); + auto section2 = std::make_shared(); + EXPECT_CALL(*section2, registerBlocks); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); - TestSection section3; + BlockSectionMock section3; engine.addCompileFunction(section1.get(), "test1", &compileTest1); engine.addCompileFunction(section2.get(), "test2", &compileTest2); @@ -933,15 +941,17 @@ TEST(EngineTest, HatBlocks) { Engine engine; - auto section1 = std::make_shared(); + auto section1 = std::make_shared(); + EXPECT_CALL(*section1, registerBlocks); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); - auto section2 = std::make_shared(); + auto section2 = std::make_shared(); + EXPECT_CALL(*section2, registerBlocks); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); - TestSection section3; + BlockSectionMock section3; engine.addHatBlock(section1.get(), "test1"); engine.addHatBlock(section2.get(), "test2"); @@ -958,15 +968,17 @@ TEST(EngineTest, Inputs) { Engine engine; - auto section1 = std::make_shared(); + auto section1 = std::make_shared(); + EXPECT_CALL(*section1, registerBlocks); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); - auto section2 = std::make_shared(); + auto section2 = std::make_shared(); + EXPECT_CALL(*section2, registerBlocks); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); - TestSection section3; + BlockSectionMock section3; engine.addInput(section1.get(), "VALUE1", 1); engine.addInput(section2.get(), "VALUE2", 2); @@ -985,15 +997,17 @@ TEST(EngineTest, Fields) { Engine engine; - auto section1 = std::make_shared(); + auto section1 = std::make_shared(); + EXPECT_CALL(*section1, registerBlocks); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); - auto section2 = std::make_shared(); + auto section2 = std::make_shared(); + EXPECT_CALL(*section2, registerBlocks); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); - TestSection section3; + BlockSectionMock section3; engine.addField(section1.get(), "VALUE1", 1); engine.addField(section2.get(), "VALUE2", 2); @@ -1012,15 +1026,17 @@ TEST(EngineTest, FieldValues) { Engine engine; - auto section1 = std::make_shared(); + auto section1 = std::make_shared(); + EXPECT_CALL(*section1, registerBlocks); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); - auto section2 = std::make_shared(); + auto section2 = std::make_shared(); + EXPECT_CALL(*section2, registerBlocks); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); - TestSection section3; + BlockSectionMock section3; engine.addFieldValue(section1.get(), "value1", 1); engine.addFieldValue(section2.get(), "value2", 2); diff --git a/test/engine/testsection.cpp b/test/engine/testsection.cpp deleted file mode 100644 index 255e6938..00000000 --- a/test/engine/testsection.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -#include "testsection.h" - -using namespace libscratchcpp; - -std::string TestSection::name() const -{ - return "Test"; -} - -void TestSection::registerBlocks(IEngine *engine) -{ -} diff --git a/test/engine/testsection.h b/test/engine/testsection.h deleted file mode 100644 index 78a0507d..00000000 --- a/test/engine/testsection.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include - -namespace libscratchcpp -{ - -class TestSection : public IBlockSection -{ - public: - std::string name() const override; - - void registerBlocks(IEngine *engine) override; -}; - -} // namespace libscratchcpp diff --git a/test/mocks/blocksectionmock.h b/test/mocks/blocksectionmock.h new file mode 100644 index 00000000..2de5f41d --- /dev/null +++ b/test/mocks/blocksectionmock.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +using namespace libscratchcpp; + +class BlockSectionMock : public IBlockSection +{ + public: + MOCK_METHOD(std::string, name, (), (const, override)); + MOCK_METHOD(bool, categoryVisible, (), (const, override)); + + MOCK_METHOD(void, registerBlocks, (IEngine *), (override)); +}; From aa50fad1ff3d34f3bd0b4887fb8d15693cf03b49 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Sun, 17 Mar 2024 11:34:00 +0100 Subject: [PATCH 2/4] Add missing tests for block section containers --- test/engine/engine_test.cpp | 96 ++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/test/engine/engine_test.cpp b/test/engine/engine_test.cpp index 4ca5a801..9cc7f871 100644 --- a/test/engine/engine_test.cpp +++ b/test/engine/engine_test.cpp @@ -937,6 +937,100 @@ TEST(EngineTest, CompileFunctions) ASSERT_EQ(container2->resolveBlockCompileFunc("test2"), &compileTest2); } +TEST(EngineTest, HatPredicateCompileFunctions) +{ + Engine engine; + + auto section1 = std::make_shared(); + EXPECT_CALL(*section1, registerBlocks); + engine.registerSection(section1); + auto container1 = engine.blockSectionContainer(section1.get()); + + auto section2 = std::make_shared(); + EXPECT_CALL(*section2, registerBlocks); + engine.registerSection(section2); + auto container2 = engine.blockSectionContainer(section2.get()); + + BlockSectionMock section3; + + engine.addHatPredicateCompileFunction(section1.get(), "test1", &compileTest1); + engine.addHatPredicateCompileFunction(section2.get(), "test2", &compileTest2); + engine.addHatPredicateCompileFunction(section1.get(), "test1", &compileTest1); + engine.addHatPredicateCompileFunction(§ion3, "test1", &compileTest1); + + ASSERT_EQ(container1->resolveHatPredicateCompileFunc("test1"), &compileTest1); + ASSERT_EQ(container1->resolveHatPredicateCompileFunc("test2"), nullptr); + ASSERT_EQ(container2->resolveHatPredicateCompileFunc("test1"), nullptr); + ASSERT_EQ(container2->resolveHatPredicateCompileFunc("test2"), &compileTest2); +} + +TEST(EngineTest, MonitorNameFunctions) +{ + Engine engine; + + auto section1 = std::make_shared(); + EXPECT_CALL(*section1, registerBlocks); + engine.registerSection(section1); + auto container1 = engine.blockSectionContainer(section1.get()); + + auto section2 = std::make_shared(); + EXPECT_CALL(*section2, registerBlocks); + engine.registerSection(section2); + auto container2 = engine.blockSectionContainer(section2.get()); + + BlockSectionMock section3; + + MonitorNameFunc f1 = [](Block *) -> const std::string & { + static const std::string ret; + return ret; + }; + + MonitorNameFunc f2 = [](Block *) -> const std::string & { + static const std::string ret; + return ret; + }; + + engine.addMonitorNameFunction(section1.get(), "test1", f1); + engine.addMonitorNameFunction(section2.get(), "test2", f2); + engine.addMonitorNameFunction(section1.get(), "test1", f1); + engine.addMonitorNameFunction(§ion3, "test1", f1); + + ASSERT_EQ(container1->resolveMonitorNameFunc("test1"), f1); + ASSERT_EQ(container1->resolveMonitorNameFunc("test2"), nullptr); + ASSERT_EQ(container2->resolveMonitorNameFunc("test1"), nullptr); + ASSERT_EQ(container2->resolveMonitorNameFunc("test2"), f2); +} + +TEST(EngineTest, MonitorChangeFunctions) +{ + Engine engine; + + auto section1 = std::make_shared(); + EXPECT_CALL(*section1, registerBlocks); + engine.registerSection(section1); + auto container1 = engine.blockSectionContainer(section1.get()); + + auto section2 = std::make_shared(); + EXPECT_CALL(*section2, registerBlocks); + engine.registerSection(section2); + auto container2 = engine.blockSectionContainer(section2.get()); + + BlockSectionMock section3; + + MonitorChangeFunc f1 = [](Block *, const Value &) {}; + MonitorChangeFunc f2 = [](Block *, const Value &) {}; + + engine.addMonitorChangeFunction(section1.get(), "test1", f1); + engine.addMonitorChangeFunction(section2.get(), "test2", f2); + engine.addMonitorChangeFunction(section1.get(), "test1", f1); + engine.addMonitorChangeFunction(§ion3, "test1", f1); + + ASSERT_EQ(container1->resolveMonitorChangeFunc("test1"), f1); + ASSERT_EQ(container1->resolveMonitorChangeFunc("test2"), nullptr); + ASSERT_EQ(container2->resolveMonitorChangeFunc("test1"), nullptr); + ASSERT_EQ(container2->resolveMonitorChangeFunc("test2"), f2); +} + TEST(EngineTest, HatBlocks) { Engine engine; @@ -1040,7 +1134,7 @@ TEST(EngineTest, FieldValues) engine.addFieldValue(section1.get(), "value1", 1); engine.addFieldValue(section2.get(), "value2", 2); - engine.addFieldValue(section1.get(), "value1", 3); // change ID of existing field + engine.addFieldValue(section1.get(), "value1", 3); // change ID of existing field value engine.addFieldValue(§ion3, "value3", 4); ASSERT_EQ(container1->resolveFieldValue("value1"), 3); From 3f4c47d751595a2e5f29c14d86bd8c4620d75655 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Sun, 17 Mar 2024 11:37:53 +0100 Subject: [PATCH 3/4] Add onInit() method to IBlockSection --- include/scratchcpp/iblocksection.h | 3 +++ src/engine/internal/engine.cpp | 1 + test/engine/engine_test.cpp | 21 +++++++++++++++++++++ test/mocks/blocksectionmock.h | 1 + 4 files changed, 26 insertions(+) diff --git a/include/scratchcpp/iblocksection.h b/include/scratchcpp/iblocksection.h index d12159e4..92b71cfb 100644 --- a/include/scratchcpp/iblocksection.h +++ b/include/scratchcpp/iblocksection.h @@ -36,6 +36,9 @@ class LIBSCRATCHCPP_EXPORT IBlockSection /*! Override this method to register blocks. */ virtual void registerBlocks(IEngine *engine) = 0; + + /*! This method is called when a project is loaded. */ + virtual void onInit(IEngine *engine) { } }; } // namespace libscratchcpp diff --git a/src/engine/internal/engine.cpp b/src/engine/internal/engine.cpp index a810a99d..ed4ce7ef 100644 --- a/src/engine/internal/engine.cpp +++ b/src/engine/internal/engine.cpp @@ -864,6 +864,7 @@ void Engine::registerSection(std::shared_ptr section) m_sections[section] = std::make_unique(); section->registerBlocks(this); + section->onInit(this); } } diff --git a/test/engine/engine_test.cpp b/test/engine/engine_test.cpp index 9cc7f871..b2d390fc 100644 --- a/test/engine/engine_test.cpp +++ b/test/engine/engine_test.cpp @@ -79,6 +79,7 @@ TEST(EngineTest, Clear) auto section = std::make_shared(); EXPECT_CALL(*section, registerBlocks); + EXPECT_CALL(*section, onInit); engine.registerSection(section); auto monitor1 = std::make_shared("", ""); @@ -129,6 +130,7 @@ TEST(EngineTest, CompileAndExecuteMonitors) auto section = std::make_shared(); EXPECT_CALL(*section, registerBlocks); + EXPECT_CALL(*section, onInit); engine.registerSection(section); engine.addCompileFunction(section.get(), m1->opcode(), [](Compiler *compiler) { compiler->addConstValue(5.4); }); engine.addCompileFunction(section.get(), m2->opcode(), [](Compiler *compiler) { compiler->addConstValue("test"); }); @@ -863,14 +865,17 @@ TEST(EngineTest, Sections) auto section1 = std::make_shared(); EXPECT_CALL(*section1, registerBlocks(&engine)); + EXPECT_CALL(*section1, onInit(&engine)); engine.registerSection(section1); auto section2 = std::make_shared(); EXPECT_CALL(*section2, registerBlocks(&engine)); + EXPECT_CALL(*section2, onInit(&engine)); engine.registerSection(section2); EXPECT_CALL(*section1, name()).WillOnce(Return("test")); EXPECT_CALL(*section1, registerBlocks).Times(0); + EXPECT_CALL(*section1, onInit).Times(0); engine.registerSection(section1); // register existing section ASSERT_EQ(engine.registeredSections().size(), 2); @@ -916,11 +921,13 @@ TEST(EngineTest, CompileFunctions) auto section1 = std::make_shared(); EXPECT_CALL(*section1, registerBlocks); + EXPECT_CALL(*section1, onInit); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); auto section2 = std::make_shared(); EXPECT_CALL(*section2, registerBlocks); + EXPECT_CALL(*section2, onInit); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); @@ -943,11 +950,13 @@ TEST(EngineTest, HatPredicateCompileFunctions) auto section1 = std::make_shared(); EXPECT_CALL(*section1, registerBlocks); + EXPECT_CALL(*section1, onInit); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); auto section2 = std::make_shared(); EXPECT_CALL(*section2, registerBlocks); + EXPECT_CALL(*section2, onInit); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); @@ -970,11 +979,13 @@ TEST(EngineTest, MonitorNameFunctions) auto section1 = std::make_shared(); EXPECT_CALL(*section1, registerBlocks); + EXPECT_CALL(*section1, onInit); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); auto section2 = std::make_shared(); EXPECT_CALL(*section2, registerBlocks); + EXPECT_CALL(*section2, onInit); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); @@ -1007,11 +1018,13 @@ TEST(EngineTest, MonitorChangeFunctions) auto section1 = std::make_shared(); EXPECT_CALL(*section1, registerBlocks); + EXPECT_CALL(*section1, onInit); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); auto section2 = std::make_shared(); EXPECT_CALL(*section2, registerBlocks); + EXPECT_CALL(*section2, onInit); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); @@ -1037,11 +1050,13 @@ TEST(EngineTest, HatBlocks) auto section1 = std::make_shared(); EXPECT_CALL(*section1, registerBlocks); + EXPECT_CALL(*section1, onInit); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); auto section2 = std::make_shared(); EXPECT_CALL(*section2, registerBlocks); + EXPECT_CALL(*section2, onInit); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); @@ -1064,11 +1079,13 @@ TEST(EngineTest, Inputs) auto section1 = std::make_shared(); EXPECT_CALL(*section1, registerBlocks); + EXPECT_CALL(*section1, onInit); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); auto section2 = std::make_shared(); EXPECT_CALL(*section2, registerBlocks); + EXPECT_CALL(*section2, onInit); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); @@ -1093,11 +1110,13 @@ TEST(EngineTest, Fields) auto section1 = std::make_shared(); EXPECT_CALL(*section1, registerBlocks); + EXPECT_CALL(*section1, onInit); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); auto section2 = std::make_shared(); EXPECT_CALL(*section2, registerBlocks); + EXPECT_CALL(*section2, onInit); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); @@ -1122,11 +1141,13 @@ TEST(EngineTest, FieldValues) auto section1 = std::make_shared(); EXPECT_CALL(*section1, registerBlocks); + EXPECT_CALL(*section1, onInit); engine.registerSection(section1); auto container1 = engine.blockSectionContainer(section1.get()); auto section2 = std::make_shared(); EXPECT_CALL(*section2, registerBlocks); + EXPECT_CALL(*section2, onInit); engine.registerSection(section2); auto container2 = engine.blockSectionContainer(section2.get()); diff --git a/test/mocks/blocksectionmock.h b/test/mocks/blocksectionmock.h index 2de5f41d..5050d83c 100644 --- a/test/mocks/blocksectionmock.h +++ b/test/mocks/blocksectionmock.h @@ -12,4 +12,5 @@ class BlockSectionMock : public IBlockSection MOCK_METHOD(bool, categoryVisible, (), (const, override)); MOCK_METHOD(void, registerBlocks, (IEngine *), (override)); + MOCK_METHOD(void, onInit, (IEngine *), (override)); }; From 3fd4cc90eeb976c2a55410e1323686b297be5044 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Sun, 17 Mar 2024 12:01:46 +0100 Subject: [PATCH 4/4] Clear waiting sounds on init --- src/blocks/soundblocks.cpp | 6 ++++++ src/blocks/soundblocks.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/blocks/soundblocks.cpp b/src/blocks/soundblocks.cpp index edd9659b..4543f6c3 100644 --- a/src/blocks/soundblocks.cpp +++ b/src/blocks/soundblocks.cpp @@ -33,6 +33,12 @@ void SoundBlocks::registerBlocks(IEngine *engine) engine->addInput(this, "VOLUME", VOLUME); } +void SoundBlocks::onInit(IEngine *engine) +{ + m_waitingSounds.clear(); + // TODO: Remove stopped threads from m_waitingSounds +} + bool SoundBlocks::compilePlayCommon(Compiler *compiler, bool untilDone, bool *byIndex) { Target *target = compiler->target(); diff --git a/src/blocks/soundblocks.h b/src/blocks/soundblocks.h index f2a1faed..866be118 100644 --- a/src/blocks/soundblocks.h +++ b/src/blocks/soundblocks.h @@ -36,6 +36,7 @@ class SoundBlocks : public IBlockSection std::string name() const override; void registerBlocks(IEngine *engine) override; + void onInit(IEngine *engine) override; static bool compilePlayCommon(Compiler *compiler, bool untilDone, bool *byIndex = nullptr); static void compilePlay(Compiler *compiler);