From 90c463734bd1a01468644e6aee79c572fb045aa4 Mon Sep 17 00:00:00 2001 From: sean Date: Wed, 6 Mar 2024 12:15:37 +0100 Subject: [PATCH] Add: Validate UTF-8 for exported JSON strings --- tests/basic_test.cpp | 10 +++++----- tests/write_tests.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/tests/basic_test.cpp b/tests/basic_test.cpp index dd26b5824..4d05fbbda 100644 --- a/tests/basic_test.cpp +++ b/tests/basic_test.cpp @@ -562,17 +562,17 @@ TEST_CASE("Test accessors min/max", "[gltf-loader]") { TEST_CASE("Test unicode characters", "[gltf-loader]") { #if FASTGLTF_CPP_20 - auto lightsLamp = sampleModels / "2.0" / std::filesystem::path(u8"Unicode❤♻Test") / "glTF"; + auto unicodePath = sampleModels / "2.0" / std::filesystem::path(u8"Unicode❤♻Test") / "glTF"; fastgltf::GltfDataBuffer jsonData; - REQUIRE(jsonData.loadFromFile(lightsLamp / std::filesystem::path(u8"Unicode❤♻Test.gltf"))); + REQUIRE(jsonData.loadFromFile(unicodePath / std::filesystem::path(u8"Unicode❤♻Test.gltf"))); #else - auto lightsLamp = sampleModels / "2.0" / std::filesystem::u8path(u8"Unicode❤♻Test") / "glTF"; + auto unicodePath = sampleModels / "2.0" / std::filesystem::u8path(u8"Unicode❤♻Test") / "glTF"; fastgltf::GltfDataBuffer jsonData; - REQUIRE(jsonData.loadFromFile(lightsLamp / std::filesystem::u8path(u8"Unicode❤♻Test.gltf"))); + REQUIRE(jsonData.loadFromFile(unicodePath / std::filesystem::u8path(u8"Unicode❤♻Test.gltf"))); #endif fastgltf::Parser parser; - auto asset = parser.loadGltfJson(&jsonData, lightsLamp); + auto asset = parser.loadGltfJson(&jsonData, unicodePath); REQUIRE(asset.error() == fastgltf::Error::None); REQUIRE(fastgltf::validate(asset.get()) == fastgltf::Error::None); diff --git a/tests/write_tests.cpp b/tests/write_tests.cpp index 814b660b7..3732b5f22 100644 --- a/tests/write_tests.cpp +++ b/tests/write_tests.cpp @@ -4,6 +4,8 @@ #include +#include + #include #include "gltf_path.hpp" @@ -153,8 +155,11 @@ TEST_CASE("Test all local models and re-export them", "[write-tests]") { auto exported = exporter.writeGltfJson(model.get()); REQUIRE(exported.error() == fastgltf::Error::None); - // Parse the re-generated glTF and validate + // UTF-8 validation on the exported JSON string auto& exportedJson = exported.get().output; + REQUIRE(simdjson::validate_utf8(exportedJson)); + + // Parse the re-generated glTF and validate fastgltf::GltfDataBuffer regeneratedJson; regeneratedJson.copyBytes(reinterpret_cast(exportedJson.data()), exportedJson.size()); auto regeneratedModel = parser.loadGltf(®eneratedJson, epath.parent_path()); @@ -166,3 +171,39 @@ TEST_CASE("Test all local models and re-export them", "[write-tests]") { } printf("Successfully tested fastgltf exporter on %" PRIu64 " assets.", testedAssets); } + +TEST_CASE("Test Unicode exporting", "[write-tests]") { +#if FASTGLTF_CPP_20 + auto unicodePath = sampleModels / "2.0" / std::filesystem::path(u8"Unicode❤♻Test") / "glTF"; + fastgltf::GltfDataBuffer jsonData; + REQUIRE(jsonData.loadFromFile(unicodePath / std::filesystem::path(u8"Unicode❤♻Test.gltf"))); +#else + auto unicodePath = sampleModels / "2.0" / std::filesystem::u8path(u8"Unicode❤♻Test") / "glTF"; + fastgltf::GltfDataBuffer jsonData; + REQUIRE(jsonData.loadFromFile(unicodePath / std::filesystem::u8path(u8"Unicode❤♻Test.gltf"))); +#endif + + fastgltf::Parser parser; + auto asset = parser.loadGltfJson(&jsonData, unicodePath); + REQUIRE(asset.error() == fastgltf::Error::None); + + fastgltf::Exporter exporter; + auto exported = exporter.writeGltfJson(asset.get()); + REQUIRE(exported.error() == fastgltf::Error::None); + + // UTF-8 validation on the exported JSON string + auto& exportedJson = exported.get().output; + REQUIRE(simdjson::validate_utf8(exportedJson)); + + fastgltf::GltfDataBuffer regeneratedJson; + regeneratedJson.copyBytes(reinterpret_cast(exportedJson.data()), exportedJson.size()); + auto reparsed = parser.loadGltfJson(®eneratedJson, unicodePath); + REQUIRE(reparsed.error() == fastgltf::Error::None); + + REQUIRE(!asset->materials.empty()); + REQUIRE(asset->materials[0].name == "Unicode❤♻Material"); + + REQUIRE(!asset->buffers.empty()); + auto bufferUri = std::get(asset->buffers[0].data); + REQUIRE(bufferUri.uri.path() == "Unicode❤♻Binary.bin"); +}