Files
SDL3CPlusPlus/MaterialX/source/MaterialXTest/MaterialXCore/Value.cpp
2026-01-06 13:25:49 +00:00

134 lines
5.5 KiB
C++

//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//
#include <MaterialXTest/External/Catch/catch.hpp>
#include <MaterialXCore/Util.h>
#include <MaterialXCore/Value.h>
namespace mx = MaterialX;
template<class T> void testTypedValue(const T& v1, const T& v2)
{
T v0{};
// Constructor and assignment
mx::ValuePtr value0 = mx::Value::createValue(v0);
mx::ValuePtr value1 = mx::Value::createValue(v1);
mx::ValuePtr value2 = mx::Value::createValue(v2);
REQUIRE(value0->isA<T>());
REQUIRE(value1->isA<T>());
REQUIRE(value2->isA<T>());
REQUIRE(value0->asA<T>() == v0);
REQUIRE(value1->asA<T>() == v1);
REQUIRE(value2->asA<T>() == v2);
// Equality and inequality
REQUIRE(value0->copy()->asA<T>() == value0->asA<T>());
REQUIRE(value1->copy()->asA<T>() == value1->asA<T>());
REQUIRE(value2->copy()->asA<T>() == value2->asA<T>());
REQUIRE(value1->asA<T>() != value2->asA<T>());
// Serialization and deserialization
mx::ValuePtr newValue0 = mx::TypedValue<T>::createFromString(value0->getValueString());
mx::ValuePtr newValue1 = mx::TypedValue<T>::createFromString(value1->getValueString());
mx::ValuePtr newValue2 = mx::TypedValue<T>::createFromString(value2->getValueString());
REQUIRE(newValue0->asA<T>() == v0);
REQUIRE(newValue1->asA<T>() == v1);
REQUIRE(newValue2->asA<T>() == v2);
}
TEST_CASE("Value strings", "[value]")
{
// Convert from data values to value strings.
REQUIRE(mx::toValueString(1) == "1");
REQUIRE(mx::toValueString(1.0f) == "1");
REQUIRE(mx::toValueString(true) == "true");
REQUIRE(mx::toValueString(false) == "false");
REQUIRE(mx::toValueString(mx::Color3(1.0f)) == "1, 1, 1");
REQUIRE(mx::toValueString(std::string("text")) == "text");
// Convert from floats to value strings with custom formatting.
{
mx::ScopedFloatFormatting fmt(mx::Value::FloatFormatFixed, 3);
REQUIRE(mx::toValueString(0.1234f) == "0.123");
REQUIRE(mx::toValueString(mx::Color3(1.0f)) == "1.000, 1.000, 1.000");
}
{
mx::ScopedFloatFormatting fmt(mx::Value::FloatFormatScientific, 2);
REQUIRE(mx::toValueString(0.1234f) == "1.23e-01");
}
{
mx::ScopedFloatFormatting fmt(mx::Value::FloatFormatDefault, 2);
REQUIRE(mx::toValueString(0.1234f) == "0.12");
}
// Convert from value strings to data values.
REQUIRE(mx::fromValueString<int>("1") == 1);
REQUIRE(mx::fromValueString<float>("1") == 1.0f);
REQUIRE(mx::fromValueString<bool>("true") == true);
REQUIRE(mx::fromValueString<bool>("false") == false);
REQUIRE(mx::fromValueString<mx::Color3>("1, 1, 1") == mx::Color3(1.0f));
REQUIRE(mx::fromValueString<std::string>("text") == "text");
// Verify that invalid conversions throw exceptions.
REQUIRE_THROWS_AS(mx::fromValueString<int>("text"), mx::ExceptionTypeError);
REQUIRE_THROWS_AS(mx::fromValueString<float>("text"), mx::ExceptionTypeError);
REQUIRE_THROWS_AS(mx::fromValueString<bool>("1"), mx::ExceptionTypeError);
REQUIRE_THROWS_AS(mx::fromValueString<mx::Color3>("1"), mx::ExceptionTypeError);
// Parse value strings using structure syntax features.
REQUIRE(mx::parseStructValueString("{{1;2;3};4}") == (std::vector<std::string>{"{1;2;3}","4"}));
REQUIRE(mx::parseStructValueString("{1;2;3;4}") == (std::vector<std::string>{"1","2","3","4"}));
REQUIRE(mx::parseStructValueString("{1;{2;3};4}") == (std::vector<std::string>{"1","{2;3}","4"}));
REQUIRE(mx::parseStructValueString("{1;{2;3;4}}") == (std::vector<std::string>{"1","{2;3;4}"}));
REQUIRE(mx::parseStructValueString("{1;{2;{3;4}}}") == (std::vector<std::string>{"1","{2;{3;4}}"}));
REQUIRE(mx::parseStructValueString("{1;2;{3};4}") == (std::vector<std::string>{"1","2","{3}","4"}));
REQUIRE(mx::parseStructValueString("{1;2;{3};4}") == (std::vector<std::string>{"1","2","{3}","4"}));
}
TEST_CASE("Typed values", "[value]")
{
// Base types
testTypedValue<int>(1, 2);
testTypedValue<bool>(false, true);
testTypedValue<float>(1.0f, 2.0f);
testTypedValue(mx::Color3(0.1f, 0.2f, 0.3f),
mx::Color3(0.5f, 0.6f, 0.7f));
testTypedValue(mx::Color4(0.1f, 0.2f, 0.3f, 0.4f),
mx::Color4(0.5f, 0.6f, 0.7f, 0.8f));
testTypedValue(mx::Vector2(1.0f, 2.0f),
mx::Vector2(1.5f, 2.5f));
testTypedValue(mx::Vector3(1.0f, 2.0f, 3.0f),
mx::Vector3(1.5f, 2.5f, 3.5f));
testTypedValue(mx::Vector4(1.0f, 2.0f, 3.0f, 4.0f),
mx::Vector4(1.5f, 2.5f, 3.5f, 4.5f));
testTypedValue(mx::Matrix33(0.0f),
mx::Matrix33(1.0f));
testTypedValue(mx::Matrix44(0.0f),
mx::Matrix44(1.0f));
testTypedValue(std::string("first_value"),
std::string("second_value"));
// Array types
testTypedValue(mx::IntVec{1, 2, 3},
mx::IntVec{4, 5, 6});
testTypedValue(mx::BoolVec{false, false, false},
mx::BoolVec{true, true, true});
testTypedValue(mx::FloatVec{1.0f, 2.0f, 3.0f},
mx::FloatVec{4.0f, 5.0f, 6.0f});
testTypedValue(mx::StringVec{"Item A", "Item B", "Item C"},
mx::StringVec{"Item D", "Item E", "Item F"});
// Alias types
testTypedValue<long>(1l, 2l);
testTypedValue<double>(1.0, 2.0);
// Construct a string value from a string literal
mx::ValuePtr value = mx::Value::createValue("text");
REQUIRE(value->isA<std::string>());
REQUIRE(value->asA<std::string>() == "text");
}