Skip to content

Commit e099bd5

Browse files
committed
Unit test data is now external, enabled CTest support, README update, upgraded Catch
1 parent 9fd35ff commit e099bd5

20 files changed

+402
-129
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,4 @@ before_script:
4444
- cd build
4545
- cmake .. ${CMAKE_OPTIONS} -DGLTFPP_BUILD_TESTS=1
4646

47-
script: make -j2 gltfpp_test && test/gltfpp_test
47+
script: make -j2 gltfpp_test && ctest .

3rdparty/Catch

Submodule Catch updated from 3dcc923 to 3e018ef

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Requirements
1616

1717
Building
1818
--------
19-
gltfpp is header only and therefore does not require a build step. Make sure you have all dependencies set up correctly if you only copy the directory. Additionally, add `BOOST_OUTCOME_ENABLE_ADVANCED` as a definition.
19+
gltfpp is header only and therefore does not require a build step. Make sure you have all dependencies set up correctly if you only copy the directory.
2020
### Clang Modules
2121
When using clang, modules can by enabled by passing `-DGLTFPP_ENABLE_MODULES=1` to CMake. This should speed up the compilation, however this is experimental and has only been tested with clang 5.0 snapshots so far.
2222

@@ -35,7 +35,7 @@ Running the tests
3535
mkdir build && cd build
3636
cmake .. -DGLTFPP_BUILD_TESTS=1 [-GNinja]
3737
make gltfpp_test # Or ninja
38-
test/gltfpp_test
38+
ctest .
3939
```
4040
### Fuzzing
4141
To run the fuzzer, build the `fuzz` target and execute it via `test/fuzz`. There is no meaningful dictionary for efficient fuzzing yet.

cmake/ParseAndAddCatchTests.cmake

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#==================================================================================================#
2+
# supported macros #
3+
# - TEST_CASE, #
4+
# - SCENARIO, #
5+
# - TEST_CASE_METHOD, #
6+
# - CATCH_TEST_CASE, #
7+
# - CATCH_SCENARIO, #
8+
# - CATCH_TEST_CASE_METHOD. #
9+
# #
10+
# Usage #
11+
# 1. make sure this module is in the path or add this otherwise: #
12+
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
13+
# 2. make sure that you've enabled testing option for the project by the call: #
14+
# enable_testing() #
15+
# 3. add the lines to the script for testing target (sample CMakeLists.txt): #
16+
# project(testing_target) #
17+
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
18+
# enable_testing() #
19+
# #
20+
# find_path(CATCH_INCLUDE_DIR "catch.hpp") #
21+
# include_directories(${INCLUDE_DIRECTORIES} ${CATCH_INCLUDE_DIR}) #
22+
# #
23+
# file(GLOB SOURCE_FILES "*.cpp") #
24+
# add_executable(${PROJECT_NAME} ${SOURCE_FILES}) #
25+
# #
26+
# include(ParseAndAddCatchTests) #
27+
# ParseAndAddCatchTests(${PROJECT_NAME}) #
28+
# #
29+
# The following variables affect the behavior of the script: #
30+
# #
31+
# PARSE_CATCH_TESTS_VERBOSE (Default OFF) #
32+
# -- enables debug messages #
33+
# #
34+
#==================================================================================================#
35+
36+
cmake_minimum_required(VERSION 2.8.8)
37+
38+
option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF)
39+
40+
function(PrintDebugMessage)
41+
if(PARSE_CATCH_TESTS_VERBOSE)
42+
message(STATUS "ParseAndAddCatchTests: ${ARGV}")
43+
endif()
44+
endfunction()
45+
46+
# This removes the contents between
47+
# - block comments (i.e. /* ... */)
48+
# - full line comments (i.e. // ... )
49+
# contents have been read into '${CppCode}'.
50+
# !keep partial line comments
51+
function(RemoveComments CppCode)
52+
string(ASCII 2 CMakeBeginBlockComment)
53+
string(ASCII 3 CMakeEndBlockComment)
54+
string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}")
55+
string(REGEX REPLACE "\\*/" "${CMakeEndBlockComment}" ${CppCode} "${${CppCode}}")
56+
string(REGEX REPLACE "${CMakeBeginBlockComment}[^${CMakeEndBlockComment}]*${CMakeEndBlockComment}" "" ${CppCode} "${${CppCode}}")
57+
string(REGEX REPLACE "\n[ \t]*//+[^\n]+" "\n" ${CppCode} "${${CppCode}}")
58+
59+
set(${CppCode} "${${CppCode}}" PARENT_SCOPE)
60+
endfunction()
61+
62+
# Worker function
63+
function(ParseFile SourceFile TestTarget)
64+
# According to CMake docs EXISTS behavior is well-defined only for full paths.
65+
get_filename_component(SourceFile ${SourceFile} ABSOLUTE)
66+
if(NOT EXISTS ${SourceFile})
67+
message(WARNING "Cannot find source file: ${SourceFile}")
68+
return()
69+
endif()
70+
PrintDebugMessage("parsing ${SourceFile}")
71+
file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME)
72+
73+
# Remove block and fullline comments
74+
RemoveComments(Contents)
75+
76+
# Find definition of test names
77+
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}")
78+
79+
foreach(TestName ${Tests})
80+
# Strip newlines
81+
string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}")
82+
83+
# Get test type and fixture if applicable
84+
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
85+
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}")
86+
string(REPLACE "${TestType}(" "" TestFixture "${TestTypeAndFixture}")
87+
88+
# Get string parts of test definition
89+
string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}")
90+
91+
# Strip wrapping quotation marks
92+
string(REGEX REPLACE "^\"(.*)\"$" "\\1" TestStrings "${TestStrings}")
93+
string(REPLACE "\";\"" ";" TestStrings "${TestStrings}")
94+
95+
# Validate that a test name and tags have been provided
96+
list(LENGTH TestStrings TestStringsLength)
97+
if(TestStringsLength GREATER 2 OR TestStringsLength LESS 1)
98+
message(FATAL_ERROR "You must provide a valid test name and tags for all tests in ${SourceFile}")
99+
endif()
100+
101+
# Assign name and tags
102+
list(GET TestStrings 0 Name)
103+
if("${TestType}" STREQUAL "SCENARIO")
104+
set(Name "Scenario: ${Name}")
105+
endif()
106+
if(TestFixture)
107+
set(CTestName "${TestFixture}:${Name}")
108+
else()
109+
set(CTestName "${Name}")
110+
endif()
111+
set(CTestName "${TestTarget}:${CTestName}")
112+
# add target to labels to enable running all tests added from this target
113+
set(Labels ${TestTarget})
114+
if(TestStringsLength EQUAL 2)
115+
list(GET TestStrings 1 Tags)
116+
string(TOLOWER "${Tags}" Tags)
117+
# remove target from labels if the test is hidden
118+
if("${Tags}" MATCHES ".*\\[!?(hide|\\.)\\].*")
119+
list(REMOVE_ITEM Labels ${TestTarget})
120+
endif()
121+
string(REPLACE "]" ";" Tags "${Tags}")
122+
string(REPLACE "[" "" Tags "${Tags}")
123+
endif()
124+
125+
list(APPEND Labels ${Tags})
126+
127+
PrintDebugMessage("Adding test \"${CTestName}\"")
128+
if(Labels)
129+
PrintDebugMessage("Setting labels to ${Labels}")
130+
endif()
131+
132+
# Add the test and set its properties
133+
add_test(NAME "\"${CTestName}\"" COMMAND ${TestTarget} ${Name} ${AdditionalCatchParameters})
134+
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
135+
LABELS "${Labels}")
136+
137+
endforeach()
138+
endfunction()
139+
140+
# entry point
141+
function(ParseAndAddCatchTests TestTarget)
142+
PrintDebugMessage("Started parsing ${TestTarget}")
143+
get_target_property(SourceFiles ${TestTarget} SOURCES)
144+
PrintDebugMessage("Found the following sources: ${SourceFiles}")
145+
foreach(SourceFile ${SourceFiles})
146+
ParseFile(${SourceFile} ${TestTarget})
147+
endforeach()
148+
PrintDebugMessage("Finished parsing ${TestTarget}")
149+
endfunction()

format.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/sh
22
for x in $(find test/ gltfpp/ -name '*.cpp' -o -name '*.h'); do clang-format -style=file -i $x; done
3-
for x in $(find test/ gltfpp/ -name '*.gltf'); do
3+
for x in $(find test/ gltfpp/ -name '*.gltf' -o -name '*.json'); do
44
tmp=$(python -m json.tool $x)
55
echo "$tmp" > $x
66
done

test/Asset.cpp

+41-17
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,48 @@
1-
#include "Buffer.h"
2-
#include "Error.h"
3-
#include "glTF.h"
4-
#include <catch.hpp>
5-
#include <json.hpp>
1+
#include "Asset.h"
2+
#include "common.h"
63

74
using namespace gltfpp;
8-
using nlohmann::json;
95

10-
namespace {
11-
const auto minimalAsset = R"({
12-
"version": "2.0"
13-
})"_json;
6+
TEST_CASE("Asset_minimal", "[Asset]") {
7+
common_fixture<Asset> fixture("data/asset_minimal.json");
8+
auto result = parse(fixture.unit_under_test)(fixture.ctx);
9+
CHECK_GLTF_RESULT(result);
10+
11+
auto &asset = fixture.unit_under_test;
12+
CHECK(asset.version == "2.0");
13+
CHECK(!asset.copyright.has_value());
14+
CHECK(!asset.generator.has_value());
15+
CHECK(!asset.minVersion.has_value());
16+
CHECK(!asset.extensions.has_value());
17+
CHECK(!asset.extras.has_value());
18+
}
19+
20+
TEST_CASE("Asset_complete", "[Asset]") {
21+
nlohmann::json expected_extensions, expected_extras;
22+
expected_extensions["MY_EXTENSION"] = 42.0;
23+
expected_extras.push_back("covfefe");
24+
25+
common_fixture<Asset> fixture("data/asset_complete.json");
26+
auto result = parse(fixture.unit_under_test)(fixture.ctx);
27+
CHECK_GLTF_RESULT(result);
28+
29+
auto &asset = fixture.unit_under_test;
30+
CHECK(asset.version == "2.0");
31+
CHECK_GLTF_OPTION(asset.copyright, "2017 (c) Khronos Group");
32+
CHECK_GLTF_OPTION(asset.generator, "collada2gltf@f356b99aef8868f74877c7ca545f2cd206b9d3b7");
33+
CHECK_GLTF_OPTION(asset.minVersion, "2.0");
34+
CHECK_GLTF_OPTION(asset.extensions, expected_extensions);
35+
CHECK_GLTF_OPTION(asset.extras, expected_extras);
1436
}
1537

16-
TEST_CASE("Asset_Minimal", "[Asset]") {
17-
glTF g;
18-
ParseContext ctx{&g, &minimalAsset};
38+
TEST_CASE("Asset_missing_version", "[Asset]") {
39+
common_fixture<Asset> fixture("data/asset_missing_version.json");
40+
auto result = parse(fixture.unit_under_test)(fixture.ctx);
41+
CHECK_THAT(result, IsError(gltfpp::gltf_error::key_not_found));
42+
}
1943

20-
Asset a;
21-
auto success = parse(a)(ctx);
22-
REQUIRE(success);
23-
REQUIRE(a.version == "2.0");
44+
TEST_CASE("Asset_version_wrong_type", "[Asset]") {
45+
common_fixture<Asset> fixture("data/asset_version_wrong_type.json");
46+
auto result = parse(fixture.unit_under_test)(fixture.ctx);
47+
CHECK_THAT(result, IsError(gltfpp::gltf_error::type_error));
2448
}

0 commit comments

Comments
 (0)