Skip to content

Commit a475b03

Browse files
authored
Merge pull request #304 from scratchcpp/fps_test
Add FPS test
2 parents 4ff1f12 + 928683f commit a475b03

File tree

8 files changed

+59
-5
lines changed

8 files changed

+59
-5
lines changed

src/engine/internal/clock.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// SPDX-License-Identifier: Apache-2.0
22

3+
#include <thread>
4+
35
#include "clock.h"
46

57
using namespace libscratchcpp;
@@ -24,3 +26,8 @@ std::chrono::system_clock::time_point Clock::currentSystemTime() const
2426
{
2527
return std::chrono::system_clock::now();
2628
}
29+
30+
void Clock::sleep(const std::chrono::milliseconds &time) const
31+
{
32+
std::this_thread::sleep_for(time);
33+
}

src/engine/internal/clock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class Clock : public IClock
1919
std::chrono::steady_clock::time_point currentSteadyTime() const override;
2020
std::chrono::system_clock::time_point currentSystemTime() const override;
2121

22+
void sleep(const std::chrono::milliseconds &time) const override;
23+
2224
private:
2325
static std::shared_ptr<Clock> m_instance;
2426
};

src/engine/internal/engine.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,19 @@
1717
#include <scratchcpp/keyevent.h>
1818
#include <cassert>
1919
#include <iostream>
20-
#include <thread>
2120

2221
#include "engine.h"
2322
#include "blocksectioncontainer.h"
2423
#include "timer.h"
24+
#include "clock.h"
2525
#include "../../blocks/standardblocks.h"
2626

2727
using namespace libscratchcpp;
2828

2929
Engine::Engine() :
3030
m_defaultTimer(std::make_unique<Timer>()),
31-
m_timer(m_defaultTimer.get())
31+
m_timer(m_defaultTimer.get()),
32+
m_clock(Clock::instance().get())
3233
{
3334
}
3435

@@ -354,7 +355,7 @@ void Engine::run()
354355
start();
355356

356357
while (true) {
357-
auto lastFrameTime = std::chrono::steady_clock::now();
358+
auto lastFrameTime = m_clock->currentSteadyTime();
358359
m_skipFrame = false;
359360

360361
// Execute the frame
@@ -363,13 +364,13 @@ void Engine::run()
363364
break;
364365

365366
// Sleep until the time for the next frame
366-
auto currentTime = std::chrono::steady_clock::now();
367+
auto currentTime = m_clock->currentSteadyTime();
367368
auto elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastFrameTime);
368369
auto sleepTime = m_frameDuration - elapsedTime;
369370
bool timeOut = sleepTime <= std::chrono::milliseconds::zero();
370371

371372
if (!timeOut && !m_skipFrame)
372-
std::this_thread::sleep_for(sleepTime);
373+
m_clock->sleep(sleepTime);
373374

374375
if ((m_skipFrame && timeOut) || !m_skipFrame) {
375376
// TODO: Repaint here

src/engine/internal/engine.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace libscratchcpp
1515
{
1616

1717
class Entity;
18+
class IClock;
1819

1920
class Engine : public IEngine
2021
{
@@ -116,6 +117,8 @@ class Engine : public IEngine
116117
BlockSectionContainer *blockSectionContainer(const std::string &opcode) const;
117118
BlockSectionContainer *blockSectionContainer(IBlockSection *section) const;
118119

120+
IClock *m_clock = nullptr;
121+
119122
private:
120123
void finalize();
121124
void deleteClones();

src/engine/internal/iclock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ class IClock
1414

1515
virtual std::chrono::steady_clock::time_point currentSteadyTime() const = 0;
1616
virtual std::chrono::system_clock::time_point currentSystemTime() const = 0;
17+
18+
virtual void sleep(const std::chrono::milliseconds &time) const = 0;
1719
};
1820

1921
} // namespace libscratchcpp

test/2_frames.sb3

932 Bytes
Binary file not shown.

test/engine/engine_test.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,25 @@
66
#include <scratchcpp/variable.h>
77
#include <scratchcpp/list.h>
88
#include <timermock.h>
9+
#include <clockmock.h>
910

1011
#include "../common.h"
1112
#include "testsection.h"
1213
#include "engine/internal/engine.h"
14+
#include "engine/internal/clock.h"
1315

1416
using namespace libscratchcpp;
1517

18+
using ::testing::Return;
19+
1620
// NOTE: resolveIds() and compile() are tested in load_project_test
1721

22+
TEST(EngineTest, Clock)
23+
{
24+
Engine engine;
25+
ASSERT_EQ(engine.m_clock, Clock::instance().get());
26+
}
27+
1828
TEST(EngineTest, Clear)
1929
{
2030
Engine engine;
@@ -61,6 +71,33 @@ TEST(EngineTest, Fps)
6171
ASSERT_EQ(engine.fps(), 60.25);
6272
}
6373

74+
TEST(EngineTest, FpsProject)
75+
{
76+
Project p("2_frames.sb3");
77+
ASSERT_TRUE(p.load());
78+
79+
ClockMock clock;
80+
Engine *engine = dynamic_cast<Engine *>(p.engine().get());
81+
engine->m_clock = &clock;
82+
83+
std::chrono::steady_clock::time_point time1(std::chrono::milliseconds(50));
84+
std::chrono::steady_clock::time_point time2(std::chrono::milliseconds(75));
85+
std::chrono::steady_clock::time_point time3(std::chrono::milliseconds(83));
86+
std::chrono::steady_clock::time_point time4(std::chrono::milliseconds(116));
87+
EXPECT_CALL(clock, currentSteadyTime()).WillOnce(Return(time1)).WillOnce(Return(time2)).WillOnce(Return(time3)).WillOnce(Return(time4)).WillOnce(Return(time4));
88+
EXPECT_CALL(clock, sleep(std::chrono::milliseconds(8)));
89+
p.run();
90+
91+
engine->setFps(10);
92+
std::chrono::steady_clock::time_point time5(std::chrono::milliseconds(100));
93+
std::chrono::steady_clock::time_point time6(std::chrono::milliseconds(115));
94+
std::chrono::steady_clock::time_point time7(std::chrono::milliseconds(200));
95+
std::chrono::steady_clock::time_point time8(std::chrono::milliseconds(300));
96+
EXPECT_CALL(clock, currentSteadyTime()).WillOnce(Return(time5)).WillOnce(Return(time6)).WillOnce(Return(time7)).WillOnce(Return(time8)).WillOnce(Return(time8));
97+
EXPECT_CALL(clock, sleep(std::chrono::milliseconds(85)));
98+
p.run();
99+
}
100+
64101
TEST(EngineTest, KeyState)
65102
{
66103
Engine engine;

test/mocks/clockmock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ class ClockMock : public IClock
1010
public:
1111
MOCK_METHOD(std::chrono::steady_clock::time_point, currentSteadyTime, (), (const, override));
1212
MOCK_METHOD(std::chrono::system_clock::time_point, currentSystemTime, (), (const, override));
13+
14+
MOCK_METHOD(void, sleep, (const std::chrono::milliseconds &time), (const, override));
1315
};

0 commit comments

Comments
 (0)