Skip to content

Commit 29cc656

Browse files
committed
Add ProjectLoader test
1 parent ed1f742 commit 29cc656

File tree

7 files changed

+363
-0
lines changed

7 files changed

+363
-0
lines changed

test/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@ include(GoogleTest)
1616
function(add_test TARGET)
1717
target_include_directories(${TARGET} PRIVATE ${CMAKE_SOURCE_DIR}/ScratchCPPGui)
1818
endfunction()
19+
20+
add_subdirectory(mocks)
21+
22+
add_subdirectory(projectloader)

test/empty_project.sb3

853 Bytes
Binary file not shown.

test/load_test.sb3

47.6 KB
Binary file not shown.

test/mocks/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
add_library(scratchcppgui_mocks INTERFACE)
2+
target_include_directories(scratchcppgui_mocks INTERFACE .)

test/mocks/enginemock.h

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#pragma once
2+
3+
#include <scratchcpp/iengine.h>
4+
#include <gmock/gmock.h>
5+
6+
using namespace libscratchcpp;
7+
8+
namespace scratchcppgui
9+
{
10+
11+
using ScriptMap = std::unordered_map<std::shared_ptr<Block>, std::shared_ptr<Script>>;
12+
13+
class EngineMock : public IEngine
14+
{
15+
public:
16+
MOCK_METHOD(void, clear, (), (override));
17+
MOCK_METHOD(void, compile, (), (override));
18+
19+
MOCK_METHOD(void, start, (), (override));
20+
MOCK_METHOD(void, stop, (), (override));
21+
MOCK_METHOD(void, startScript, (std::shared_ptr<Block>, std::shared_ptr<Target>), (override));
22+
MOCK_METHOD(void, broadcast, (unsigned int, VirtualMachine *, bool), (override));
23+
MOCK_METHOD(void, broadcastByPtr, (Broadcast *, VirtualMachine *, bool), (override));
24+
MOCK_METHOD(void, stopScript, (VirtualMachine *), (override));
25+
MOCK_METHOD(void, stopTarget, (Target *, VirtualMachine *), (override));
26+
MOCK_METHOD(void, initClone, (Sprite *), (override));
27+
MOCK_METHOD(void, deinitClone, (Sprite *), (override));
28+
29+
MOCK_METHOD(void, run, (), (override));
30+
MOCK_METHOD(void, runEventLoop, (), (override));
31+
MOCK_METHOD(void, stopEventLoop, (), (override));
32+
33+
MOCK_METHOD(void, setRedrawHandler, (const std::function<void()> &), (override));
34+
35+
MOCK_METHOD(bool, isRunning, (), (const, override));
36+
37+
MOCK_METHOD(double, fps, (), (const, override));
38+
MOCK_METHOD(void, setFps, (double fps), (override));
39+
40+
MOCK_METHOD(bool, turboModeEnabled, (), (const, override));
41+
MOCK_METHOD(void, setTurboModeEnabled, (bool), (override));
42+
43+
MOCK_METHOD(bool, keyPressed, (const std::string &), (const, override));
44+
MOCK_METHOD(void, setKeyState, (const std::string &, bool), (override));
45+
MOCK_METHOD(void, setAnyKeyPressed, (bool), (override));
46+
47+
MOCK_METHOD(double, mouseX, (), (const, override));
48+
MOCK_METHOD(void, setMouseX, (double x), (override));
49+
50+
MOCK_METHOD(double, mouseY, (), (const, override));
51+
MOCK_METHOD(void, setMouseY, (double y), (override));
52+
53+
MOCK_METHOD(bool, mousePressed, (), (const, override));
54+
MOCK_METHOD(void, setMousePressed, (bool), (override));
55+
56+
MOCK_METHOD(unsigned int, stageWidth, (), (const, override));
57+
MOCK_METHOD(void, setStageWidth, (unsigned int), (override));
58+
59+
MOCK_METHOD(unsigned int, stageHeight, (), (const, override));
60+
MOCK_METHOD(void, setStageHeight, (unsigned int), (override));
61+
62+
MOCK_METHOD(int, cloneLimit, (), (const, override));
63+
MOCK_METHOD(void, setCloneLimit, (int), (override));
64+
65+
MOCK_METHOD(int, cloneCount, (), (const, override));
66+
67+
MOCK_METHOD(bool, spriteFencingEnabled, (), (const, override));
68+
MOCK_METHOD(void, setSpriteFencingEnabled, (bool), (override));
69+
70+
MOCK_METHOD(bool, broadcastRunning, (unsigned int, VirtualMachine *), (override));
71+
MOCK_METHOD(bool, broadcastByPtrRunning, (Broadcast *, VirtualMachine *), (override));
72+
73+
MOCK_METHOD(void, requestRedraw, (), (override));
74+
75+
MOCK_METHOD(ITimer *, timer, (), (const, override));
76+
77+
MOCK_METHOD(void, registerSection, (std::shared_ptr<IBlockSection>), (override));
78+
MOCK_METHOD(unsigned int, functionIndex, (BlockFunc), (override));
79+
80+
MOCK_METHOD(void, addCompileFunction, (IBlockSection *, const std::string &, BlockComp), (override));
81+
MOCK_METHOD(void, addHatBlock, (IBlockSection *, const std::string &), (override));
82+
MOCK_METHOD(void, addInput, (IBlockSection *, const std::string &, int), (override));
83+
MOCK_METHOD(void, addField, (IBlockSection *, const std::string &, int), (override));
84+
MOCK_METHOD(void, addFieldValue, (IBlockSection *, const std::string &, int), (override));
85+
86+
MOCK_METHOD(const std::vector<std::shared_ptr<Broadcast>> &, broadcasts, (), (const, override));
87+
MOCK_METHOD(void, setBroadcasts, (const std::vector<std::shared_ptr<Broadcast>> &), (override));
88+
MOCK_METHOD(std::shared_ptr<Broadcast>, broadcastAt, (int), (const, override));
89+
MOCK_METHOD(int, findBroadcast, (const std::string &), (const, override));
90+
MOCK_METHOD(int, findBroadcastById, (const std::string &), (const, override));
91+
92+
MOCK_METHOD(void, addBroadcastScript, (std::shared_ptr<Block>, Broadcast *), (override));
93+
MOCK_METHOD(void, addCloneInitScript, (std::shared_ptr<Block>), (override));
94+
MOCK_METHOD(void, addKeyPressScript, (std::shared_ptr<Block>, std::string), (override));
95+
96+
MOCK_METHOD(const std::vector<std::shared_ptr<Target>> &, targets, (), (const, override));
97+
MOCK_METHOD(void, setTargets, (const std::vector<std::shared_ptr<Target>> &), (override));
98+
MOCK_METHOD(Target *, targetAt, (int), (const, override));
99+
MOCK_METHOD(int, findTarget, (const std::string &), (const, override));
100+
101+
MOCK_METHOD(void, moveSpriteToFront, (Sprite * sprite), (override));
102+
MOCK_METHOD(void, moveSpriteToBack, (Sprite * sprite), (override));
103+
MOCK_METHOD(void, moveSpriteForwardLayers, (Sprite * sprite, int layers), (override));
104+
MOCK_METHOD(void, moveSpriteBackwardLayers, (Sprite * sprite, int layers), (override));
105+
MOCK_METHOD(void, moveSpriteBehindOther, (Sprite * sprite, Sprite *other), (override));
106+
107+
MOCK_METHOD(Stage *, stage, (), (const, override));
108+
109+
MOCK_METHOD(std::vector<std::string> &, extensions, (), (const, override));
110+
MOCK_METHOD(void, setExtensions, (const std::vector<std::string> &), (override));
111+
112+
MOCK_METHOD(const ScriptMap &, scripts, (), (const, override));
113+
};
114+
115+
} // namespace libscratchcpp

test/projectloader/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
add_executable(
2+
projectloader_test
3+
projectloader_test.cpp
4+
)
5+
6+
target_link_libraries(
7+
projectloader_test
8+
GTest::gtest_main
9+
GTest::gmock_main
10+
libscratchcpp-gui
11+
scratchcppgui_mocks
12+
${QT_LIBS}
13+
Qt6::Test
14+
)
15+
16+
add_test(projectloader_test)
17+
gtest_discover_tests(projectloader_test)
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
#include <QtTest/QSignalSpy>
2+
#include <projectloader.h>
3+
#include <spritemodel.h>
4+
#include <enginemock.h>
5+
6+
#include "../common.h"
7+
8+
using namespace scratchcppgui;
9+
using namespace libscratchcpp;
10+
11+
using ::testing::Return;
12+
13+
class ProjectLoaderTest : public testing::Test
14+
{
15+
public:
16+
void load(ProjectLoader *loader, const QString &fileName)
17+
{
18+
static const std::chrono::milliseconds timeout(5000);
19+
auto startTime = std::chrono::steady_clock::now();
20+
loader->setEventLoopEnabled(false);
21+
QSignalSpy fileNameSpy(loader, &ProjectLoader::fileNameChanged);
22+
QSignalSpy loadStatusSpy(loader, &ProjectLoader::loadStatusChanged);
23+
QSignalSpy loadingFinishedSpy(loader, &ProjectLoader::loadingFinished);
24+
QSignalSpy engineSpy(loader, &ProjectLoader::engineChanged);
25+
QSignalSpy stageSpy(loader, &ProjectLoader::stageChanged);
26+
QSignalSpy spritesSpy(loader, &ProjectLoader::spritesChanged);
27+
28+
loader->setFileName(fileName);
29+
30+
ASSERT_EQ(fileNameSpy.count(), 1);
31+
ASSERT_EQ(loadStatusSpy.count(), 1);
32+
ASSERT_TRUE(loadingFinishedSpy.empty());
33+
ASSERT_TRUE(engineSpy.empty());
34+
ASSERT_TRUE(stageSpy.empty());
35+
ASSERT_TRUE(spritesSpy.empty());
36+
ASSERT_EQ(loader->fileName(), fileName);
37+
ASSERT_FALSE(loader->loadStatus());
38+
39+
while (!loader->loadStatus())
40+
ASSERT_LE(std::chrono::steady_clock::now(), startTime + timeout);
41+
42+
ASSERT_EQ(loader->fileName(), fileName);
43+
ASSERT_EQ(fileNameSpy.count(), 1);
44+
ASSERT_EQ(loadStatusSpy.count(), 2);
45+
ASSERT_EQ(loadingFinishedSpy.count(), 1);
46+
ASSERT_EQ(engineSpy.count(), 1);
47+
ASSERT_EQ(stageSpy.count(), 1);
48+
ASSERT_EQ(spritesSpy.count(), 1);
49+
}
50+
};
51+
52+
TEST_F(ProjectLoaderTest, Load)
53+
{
54+
ProjectLoader loader;
55+
ASSERT_TRUE(loader.fileName().isEmpty());
56+
ASSERT_FALSE(loader.loadStatus());
57+
ASSERT_TRUE(loader.stage());
58+
59+
load(&loader, "load_test.sb3");
60+
61+
auto engine = loader.engine();
62+
ASSERT_EQ(loader.engine()->targets().size(), 3);
63+
ASSERT_EQ(loader.stage()->stage(), engine->stage());
64+
const auto &sprites = loader.spriteList();
65+
ASSERT_EQ(sprites.size(), 2);
66+
ASSERT_EQ(sprites[0]->sprite(), engine->targetAt(1));
67+
ASSERT_EQ(sprites[1]->sprite(), engine->targetAt(2));
68+
}
69+
70+
TEST_F(ProjectLoaderTest, StartStop)
71+
{
72+
ProjectLoader loader;
73+
load(&loader, "empty_project.sb3");
74+
75+
EngineMock engine;
76+
loader.setEngine(&engine);
77+
78+
EXPECT_CALL(engine, start());
79+
loader.start();
80+
81+
EXPECT_CALL(engine, stop());
82+
loader.stop();
83+
}
84+
85+
TEST_F(ProjectLoaderTest, Fps)
86+
{
87+
ProjectLoader loader;
88+
loader.setEventLoopEnabled(false);
89+
EngineMock engine;
90+
loader.setEngine(&engine);
91+
ASSERT_EQ(loader.fps(), 30);
92+
93+
EXPECT_CALL(engine, setFps(34.8));
94+
EXPECT_CALL(engine, fps()).WillOnce(Return(34.8));
95+
QSignalSpy spy(&loader, SIGNAL(fpsChanged()));
96+
loader.setFps(34.8);
97+
ASSERT_EQ(spy.count(), 1);
98+
ASSERT_EQ(loader.fps(), 34.8);
99+
100+
spy.clear();
101+
loader.setEngine(nullptr);
102+
loader.setFps(57.6);
103+
ASSERT_EQ(spy.count(), 1);
104+
ASSERT_EQ(loader.fps(), 57.6);
105+
}
106+
107+
TEST_F(ProjectLoaderTest, TurboMode)
108+
{
109+
ProjectLoader loader;
110+
loader.setEventLoopEnabled(false);
111+
EngineMock engine;
112+
loader.setEngine(&engine);
113+
ASSERT_FALSE(loader.turboMode());
114+
115+
EXPECT_CALL(engine, setTurboModeEnabled(true));
116+
QSignalSpy spy(&loader, SIGNAL(turboModeChanged()));
117+
loader.setTurboMode(true);
118+
ASSERT_EQ(spy.count(), 1);
119+
ASSERT_TRUE(loader.turboMode());
120+
121+
EXPECT_CALL(engine, setTurboModeEnabled(false));
122+
spy.clear();
123+
loader.setTurboMode(false);
124+
ASSERT_EQ(spy.count(), 1);
125+
ASSERT_FALSE(loader.turboMode());
126+
}
127+
128+
TEST_F(ProjectLoaderTest, StageWidth)
129+
{
130+
ProjectLoader loader;
131+
loader.setEventLoopEnabled(false);
132+
EngineMock engine;
133+
loader.setEngine(&engine);
134+
ASSERT_EQ(loader.stageWidth(), 480);
135+
136+
EXPECT_CALL(engine, setStageWidth(567));
137+
QSignalSpy spy(&loader, SIGNAL(stageWidthChanged()));
138+
loader.setStageWidth(567);
139+
ASSERT_EQ(spy.count(), 1);
140+
ASSERT_EQ(loader.stageWidth(), 567);
141+
}
142+
143+
TEST_F(ProjectLoaderTest, StageHeight)
144+
{
145+
ProjectLoader loader;
146+
loader.setEventLoopEnabled(false);
147+
EngineMock engine;
148+
loader.setEngine(&engine);
149+
ASSERT_EQ(loader.stageHeight(), 360);
150+
151+
EXPECT_CALL(engine, setStageHeight(462));
152+
QSignalSpy spy(&loader, SIGNAL(stageHeightChanged()));
153+
loader.setStageHeight(462);
154+
ASSERT_EQ(spy.count(), 1);
155+
ASSERT_EQ(loader.stageHeight(), 462);
156+
}
157+
158+
TEST_F(ProjectLoaderTest, CloneLimit)
159+
{
160+
ProjectLoader loader;
161+
loader.setEventLoopEnabled(false);
162+
EngineMock engine;
163+
loader.setEngine(&engine);
164+
ASSERT_EQ(loader.cloneLimit(), 300);
165+
166+
EXPECT_CALL(engine, setCloneLimit(379));
167+
EXPECT_CALL(engine, cloneLimit()).WillOnce(Return(379));
168+
QSignalSpy spy(&loader, SIGNAL(cloneLimitChanged()));
169+
loader.setCloneLimit(379);
170+
ASSERT_EQ(spy.count(), 1);
171+
ASSERT_EQ(loader.cloneLimit(), 379);
172+
173+
spy.clear();
174+
loader.setEngine(nullptr);
175+
loader.setCloneLimit(291);
176+
ASSERT_EQ(spy.count(), 1);
177+
ASSERT_EQ(loader.cloneLimit(), 291);
178+
}
179+
180+
TEST_F(ProjectLoaderTest, SpriteFencing)
181+
{
182+
ProjectLoader loader;
183+
loader.setEventLoopEnabled(false);
184+
EngineMock engine;
185+
loader.setEngine(&engine);
186+
ASSERT_TRUE(loader.spriteFencing());
187+
188+
EXPECT_CALL(engine, setSpriteFencingEnabled(false));
189+
QSignalSpy spy(&loader, SIGNAL(spriteFencingChanged()));
190+
loader.setSpriteFencing(false);
191+
ASSERT_EQ(spy.count(), 1);
192+
ASSERT_FALSE(loader.spriteFencing());
193+
194+
EXPECT_CALL(engine, setSpriteFencingEnabled(true));
195+
spy.clear();
196+
loader.setSpriteFencing(true);
197+
ASSERT_EQ(spy.count(), 1);
198+
ASSERT_TRUE(loader.spriteFencing());
199+
}
200+
201+
TEST_F(ProjectLoaderTest, EventLoopEnabled)
202+
{
203+
ProjectLoader loader;
204+
EngineMock engine;
205+
loader.setEngine(&engine);
206+
ASSERT_TRUE(loader.eventLoopEnabled());
207+
208+
EXPECT_CALL(engine, stopEventLoop());
209+
QSignalSpy spy(&loader, SIGNAL(eventLoopEnabledChanged()));
210+
loader.setEventLoopEnabled(false);
211+
ASSERT_EQ(spy.count(), 1);
212+
ASSERT_FALSE(loader.eventLoopEnabled());
213+
214+
EXPECT_CALL(engine, runEventLoop());
215+
spy.clear();
216+
loader.setEventLoopEnabled(true);
217+
ASSERT_EQ(spy.count(), 1);
218+
ASSERT_TRUE(loader.eventLoopEnabled());
219+
220+
EXPECT_CALL(engine, stopEventLoop());
221+
spy.clear();
222+
loader.setEventLoopEnabled(false);
223+
ASSERT_EQ(spy.count(), 1);
224+
ASSERT_FALSE(loader.eventLoopEnabled());
225+
}

0 commit comments

Comments
 (0)