Skip to content

Commit 166176c

Browse files
committed
tests: glTF/FBX/OBJ + point-cloud loader unit tests + coverage flush
test_unit_threedim_loaders: AssetLoader/GltfParser/FbxParser/TinyObj/Ply/Vcg + the PrimitiveCloud parsers, compiled straight into the test (plugin is -fvisibility=hidden). test_unit_primitivecloud: PLY/.splat/.spz parsers + scene helpers. ObjectGallery: explicit llvm profile flush on _Exit + SEGV/ABRT so coverage runs of the render-regression harness still emit .profraw (atop this branch's render-regression mode). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
1 parent a8241d5 commit 166176c

4 files changed

Lines changed: 2535 additions & 0 deletions

File tree

tests/integration/ObjectGallery.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,46 @@
5252
#include <QImage>
5353

5454
#include <algorithm>
55+
#include <csignal>
5556
#include <cstdio>
5657

58+
// Coverage support: this harness intentionally exits via std::_Exit (to bypass a
59+
// gfx teardown crash) and often SEGVs on shutdown, both of which skip the normal
60+
// atexit profile writer. When built with -fprofile-instr-generate we flush
61+
// counters explicitly before _Exit and from a SEGV/ABRT handler so instrumented
62+
// runs still yield a .profraw. Mach-O has no ELF-style weak undefined externals
63+
// (the static link still requires the symbol), so resolve dynamically there.
64+
#if defined(__APPLE__)
65+
#include <dlfcn.h>
66+
#else
67+
extern "C" __attribute__((weak)) int __llvm_profile_write_file(void);
68+
#endif
69+
5770
namespace
5871
{
72+
void flush_coverage()
73+
{
74+
#if defined(__APPLE__)
75+
if(auto f = reinterpret_cast<int (*)(void)>(
76+
dlsym(RTLD_DEFAULT, "__llvm_profile_write_file")))
77+
f();
78+
#else
79+
if(&__llvm_profile_write_file != nullptr)
80+
__llvm_profile_write_file();
81+
#endif
82+
}
83+
void coverage_signal_handler(int sig)
84+
{
85+
flush_coverage();
86+
std::signal(sig, SIG_DFL);
87+
std::raise(sig);
88+
}
89+
void install_coverage_flush()
90+
{
91+
std::signal(SIGSEGV, coverage_signal_handler);
92+
std::signal(SIGABRT, coverage_signal_handler);
93+
}
94+
5995
bool matches(const QString& name, const QString& filter)
6096
{
6197
return filter.isEmpty() || name.contains(filter, Qt::CaseInsensitive);
@@ -253,6 +289,7 @@ void run_render_check(const QString& filter, int seconds)
253289
// crashes in the offscreen readback release path) via a hard exit. If the
254290
// object had crashed *during* rendering, we would never reach here — that
255291
// is exactly the render-path failure this check is meant to catch.
292+
flush_coverage();
256293
std::_Exit(rc);
257294
});
258295
}
@@ -353,13 +390,15 @@ void run_shader_check(const QString& path, int seconds)
353390
}
354391
}
355392
std::fflush(stdout);
393+
flush_coverage();
356394
std::_Exit(rc);
357395
});
358396
}
359397
}
360398

361399
int main(int argc, char** argv)
362400
{
401+
install_coverage_flush();
363402
QLocale::setDefault(QLocale::C);
364403
std::setlocale(LC_ALL, "C");
365404

tests/unit/CMakeLists.txt

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,65 @@ if(TARGET score_plugin_threedim)
166166
PLUGINS score_plugin_threedim score_plugin_gfx score_plugin_avnd
167167
LIBS ${QT_PREFIX}::Gui)
168168
endif()
169+
# --- threedim asset loaders ------------------------------------------------
170+
# The plugin is built with -fvisibility=hidden, so the loader entry points
171+
# (GltfParser/FbxParser/AssetLoader::process, ObjFromString, ...) are not
172+
# reachable through libscore_plugin_threedim.so. Compile the loader layer
173+
# straight into the test binary instead; linking the plugins still provides
174+
# the include dirs + the exported gfx/registry symbols.
175+
if(TARGET score_plugin_threedim)
176+
set(_threedim_src "${SCORE_ROOT_SOURCE_DIR}/src/plugins/score-plugin-threedim/Threedim")
177+
178+
# C sources go in a separate static lib: mixing C into the test target
179+
# breaks the score_lib_pch REUSE_FROM (PCH is C++-only).
180+
add_library(test_unit_threedim_3rdparty STATIC
181+
"${SCORE_ROOT_SOURCE_DIR}/3rdparty/miniply/miniply.cpp"
182+
"${SCORE_ROOT_SOURCE_DIR}/3rdparty/mikktspace/mikktspace.c"
183+
"${SCORE_ROOT_SOURCE_DIR}/3rdparty/ufbx/ufbx.c")
184+
target_include_directories(test_unit_threedim_3rdparty SYSTEM PUBLIC
185+
"${SCORE_ROOT_SOURCE_DIR}/3rdparty/miniply"
186+
"${SCORE_ROOT_SOURCE_DIR}/3rdparty/mikktspace"
187+
"${SCORE_ROOT_SOURCE_DIR}/3rdparty/ufbx")
188+
set_target_properties(test_unit_threedim_3rdparty
189+
PROPERTIES FOLDER "Tests" POSITION_INDEPENDENT_CODE ON)
190+
191+
score_add_test(test_unit_threedim_loaders
192+
SOURCES
193+
ThreedimLoaderTest.cpp
194+
"${_threedim_src}/AssetLoader.cpp"
195+
"${_threedim_src}/GltfParser.cpp"
196+
"${_threedim_src}/FbxParser.cpp"
197+
"${_threedim_src}/TinyObj.cpp"
198+
"${_threedim_src}/Ply.cpp"
199+
"${_threedim_src}/VcgImporters.cpp"
200+
"${_threedim_src}/SceneFromMeshes.cpp"
201+
"${_threedim_src}/PrimitiveCloud/PlyParser.cpp"
202+
"${_threedim_src}/PrimitiveCloud/SplatBinary.cpp"
203+
"${_threedim_src}/PrimitiveCloud/SpzCodec.cpp"
204+
"${_threedim_src}/PrimitiveCloud/SceneFromCloud.cpp"
205+
"${_threedim_src}/PrimitiveCloud/FormatOverride.cpp"
206+
PLUGINS score_plugin_threedim score_plugin_gfx score_plugin_avnd
207+
LIBS test_unit_threedim_3rdparty fastgltf spz "${QT_PREFIX}::Gui")
208+
target_include_directories(test_unit_threedim_loaders SYSTEM PRIVATE
209+
"${SCORE_ROOT_SOURCE_DIR}/3rdparty/vcglib"
210+
"${SCORE_ROOT_SOURCE_DIR}/3rdparty/eigen")
211+
endif()
212+
213+
# PrimitiveCloud parsers (PLY / .splat / .spz + scene helpers). The parser
214+
# entry points are not exported from the dynamic score_plugin_threedim
215+
# (hidden visibility), so compile the parser translation units directly
216+
# into the test.
217+
set(_pc_dir "${SCORE_ROOT_SOURCE_DIR}/src/plugins/score-plugin-threedim/Threedim/PrimitiveCloud")
218+
score_add_test(test_unit_primitivecloud
219+
SOURCES
220+
PrimitiveCloudTest.cpp
221+
"${_pc_dir}/PlyParser.cpp"
222+
"${_pc_dir}/SplatBinary.cpp"
223+
"${_pc_dir}/SpzCodec.cpp"
224+
"${_pc_dir}/SceneFromCloud.cpp"
225+
"${_pc_dir}/FormatOverride.cpp"
226+
"${3RDPARTY_FOLDER}/miniply/miniply.cpp"
227+
LIBS spz)
228+
target_include_directories(test_unit_primitivecloud SYSTEM PRIVATE
229+
"${SCORE_ROOT_SOURCE_DIR}/src/plugins/score-plugin-threedim"
230+
"${3RDPARTY_FOLDER}/miniply")

0 commit comments

Comments
 (0)