Skip to content

Commit 5c0a8e7

Browse files
committed
Add TargetPainter test
1 parent 43a9c1c commit 5c0a8e7

File tree

5 files changed

+215
-0
lines changed

5 files changed

+215
-0
lines changed

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ add_subdirectory(mocks)
2222

2323
add_subdirectory(projectloader)
2424
add_subdirectory(renderedtarget)
25+
add_subdirectory(targetpainter)

test/mocks/renderedtargetmock.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#pragma once
2+
3+
#include <irenderedtarget.h>
4+
#include <qnanoquickitem.h>
5+
#include <gmock/gmock.h>
6+
7+
using namespace scratchcppgui;
8+
9+
namespace scratchcppgui
10+
{
11+
12+
class RenderedTargetMock
13+
: public QNanoQuickItem
14+
, public IRenderedTarget
15+
{
16+
public:
17+
MOCK_METHOD(void, loadProperties, (), (override));
18+
MOCK_METHOD(void, loadCostume, (libscratchcpp::Costume *), (override));
19+
MOCK_METHOD(void, updateProperties, (), (override));
20+
21+
MOCK_METHOD(libscratchcpp::IEngine *, engine, (), (const, override));
22+
MOCK_METHOD(void, setEngine, (libscratchcpp::IEngine *), (override));
23+
24+
MOCK_METHOD(StageModel *, stageModel, (), (const, override));
25+
MOCK_METHOD(void, setStageModel, (StageModel *), (override));
26+
27+
MOCK_METHOD(SpriteModel *, spriteModel, (), (const, override));
28+
MOCK_METHOD(void, setSpriteModel, (SpriteModel *), (override));
29+
30+
MOCK_METHOD(libscratchcpp::Target *, scratchTarget, (), (const, override));
31+
32+
MOCK_METHOD(qreal, width, (), (const, override));
33+
MOCK_METHOD(void, setWidth, (qreal), (override));
34+
35+
MOCK_METHOD(qreal, height, (), (const, override));
36+
MOCK_METHOD(void, setHeight, (qreal), (override));
37+
38+
MOCK_METHOD(double, costumeWidth, (), (const, override));
39+
MOCK_METHOD(void, setCostumeWidth, (double), (override));
40+
41+
MOCK_METHOD(double, costumeHeight, (), (const, override));
42+
MOCK_METHOD(void, setCostumeHeight, (double), (override));
43+
44+
MOCK_METHOD(unsigned char *, svgBitmap, (), (const, override));
45+
MOCK_METHOD(QBuffer *, bitmapBuffer, (), (override));
46+
MOCK_METHOD(const QString &, bitmapUniqueKey, (), (const, override));
47+
48+
MOCK_METHOD(void, lockCostume, (), (override));
49+
MOCK_METHOD(void, unlockCostume, (), (override));
50+
51+
MOCK_METHOD(bool, mirrorHorizontally, (), (const, override));
52+
53+
MOCK_METHOD(QNanoQuickItemPainter *, createItemPainter, (), (const, override));
54+
};
55+
56+
} // namespace scratchcppgui

test/svg_bitmap_result.png

138 Bytes
Loading

test/targetpainter/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
add_executable(
2+
targetpainter_test
3+
targetpainter_test.cpp
4+
)
5+
6+
target_link_libraries(
7+
targetpainter_test
8+
GTest::gtest_main
9+
GTest::gmock_main
10+
libscratchcpp-gui
11+
scratchcppgui_mocks
12+
${QT_LIBS}
13+
qnanopainter
14+
)
15+
16+
add_test(targetpainter_test)
17+
gtest_discover_tests(targetpainter_test)
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#include <targetpainter.h>
2+
#include <renderedtargetmock.h>
3+
4+
#include "../common.h"
5+
6+
using namespace scratchcppgui;
7+
8+
using ::testing::Return;
9+
using ::testing::ReturnRef;
10+
11+
class TargetPainterTest : public testing::Test
12+
{
13+
public:
14+
void createContextAndSurface(QOpenGLContext *context, QOffscreenSurface *surface)
15+
{
16+
QSurfaceFormat surfaceFormat;
17+
surfaceFormat.setMajorVersion(4);
18+
surfaceFormat.setMinorVersion(3);
19+
20+
context->setFormat(surfaceFormat);
21+
context->create();
22+
ASSERT_TRUE(context->isValid());
23+
24+
surface->setFormat(surfaceFormat);
25+
surface->create();
26+
ASSERT_TRUE(surface->isValid());
27+
28+
context->makeCurrent(surface);
29+
ASSERT_EQ(QOpenGLContext::currentContext(), context);
30+
}
31+
};
32+
33+
TEST_F(TargetPainterTest, PaintBitmap)
34+
{
35+
QOpenGLContext context;
36+
QOffscreenSurface surface;
37+
createContextAndSurface(&context, &surface);
38+
39+
std::unordered_map<std::string, std::string> files = { { "image.jpg", "jpeg_result.png" }, { "image.png", "png_result.png" } };
40+
41+
for (const auto &[inFile, outFile] : files) {
42+
// Create target painter
43+
TargetPainter targetPainter;
44+
QNanoPainter painter;
45+
RenderedTargetMock target;
46+
targetPainter.synchronize(&target);
47+
48+
// Load the image
49+
QBuffer buffer;
50+
buffer.open(QBuffer::WriteOnly);
51+
std::string str = readFileStr(inFile);
52+
buffer.write(str.c_str(), str.size());
53+
buffer.close();
54+
55+
QOpenGLFramebufferObjectFormat format;
56+
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
57+
58+
// Begin painting reference
59+
QNanoPainter refPainter;
60+
QOpenGLFramebufferObject refFbo(100, 100, format);
61+
refFbo.bind();
62+
refPainter.beginFrame(refFbo.width(), refFbo.height());
63+
64+
// Paint reference
65+
QNanoImage refImage = QNanoImage::fromCache(&refPainter, &buffer, "abc");
66+
refPainter.drawImage(refImage, 0, 0, 40, 60);
67+
refPainter.endFrame();
68+
69+
// Begin painting
70+
QOpenGLFramebufferObject fbo(100, 100, format);
71+
fbo.bind();
72+
painter.beginFrame(fbo.width(), fbo.height());
73+
74+
// Paint
75+
EXPECT_CALL(target, lockCostume());
76+
EXPECT_CALL(target, svgBitmap()).WillOnce(Return(nullptr));
77+
EXPECT_CALL(target, width()).WillOnce(Return(40));
78+
EXPECT_CALL(target, height()).WillOnce(Return(60));
79+
EXPECT_CALL(target, bitmapBuffer()).WillOnce(Return(&buffer));
80+
static const QString uniqueKey("abc");
81+
EXPECT_CALL(target, bitmapUniqueKey()).WillOnce(ReturnRef(uniqueKey));
82+
EXPECT_CALL(target, unlockCostume());
83+
targetPainter.paint(&painter);
84+
painter.endFrame();
85+
86+
// Compare resulting images
87+
ASSERT_EQ(fbo.toImage(), refFbo.toImage());
88+
89+
// Release
90+
fbo.release();
91+
refFbo.release();
92+
}
93+
94+
context.doneCurrent();
95+
}
96+
97+
TEST_F(TargetPainterTest, PaintSvgBitmap)
98+
{
99+
QOpenGLContext context;
100+
QOffscreenSurface surface;
101+
createContextAndSurface(&context, &surface);
102+
103+
// Create target painter
104+
TargetPainter targetPainter;
105+
QNanoPainter painter;
106+
RenderedTargetMock target;
107+
targetPainter.synchronize(&target);
108+
109+
// Load the image
110+
unsigned char bitmap[] = {
111+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255, 255, 255, 128, 128, 255, 0, 0, 0, 0, 0, 0, 128, 255, 0, 0, 0, 0, 87, 149, 87, 149,
112+
0, 0, 0, 0, 128, 0, 128, 255, 128, 128, 255, 255, 128, 128, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
113+
}; // from image.png
114+
115+
// Begin painting
116+
QOpenGLFramebufferObjectFormat format;
117+
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
118+
QOpenGLFramebufferObject fbo(10, 10, format);
119+
fbo.bind();
120+
painter.beginFrame(fbo.width(), fbo.height());
121+
122+
// Paint
123+
EXPECT_CALL(target, lockCostume());
124+
EXPECT_CALL(target, svgBitmap()).WillOnce(Return(bitmap));
125+
EXPECT_CALL(target, width()).WillOnce(Return(4));
126+
EXPECT_CALL(target, height()).WillOnce(Return(6));
127+
EXPECT_CALL(target, unlockCostume());
128+
targetPainter.paint(&painter);
129+
painter.endFrame();
130+
131+
// Get image and compare it with the expected one
132+
QBuffer outBuffer;
133+
QImage image = fbo.toImage();
134+
image.save(&outBuffer, "png");
135+
outBuffer.open(QBuffer::ReadOnly);
136+
ASSERT_EQ(outBuffer.readAll(), QByteArray::fromStdString(readFileStr("svg_bitmap_result.png")));
137+
138+
// Release
139+
fbo.release();
140+
context.doneCurrent();
141+
}

0 commit comments

Comments
 (0)