Persistency: store special double values
Json library handles infinity and NaN as null. During deserialization,
we expect a double and those files were marked as invalid and removed.
To prevent this behavior and preserve all double values, LabeledTuple
'to_json' and 'from_json' functions were improved to accommodate those
special values by using string literals.
Testing done:
- UTs added for double<=>json conversion.
- UTs passing.
Signed-off-by: Szymon Dompke <szymon.dompke@intel.com>
Change-Id: I9193df29cce1db28cda3c895d117d9f3bfca2c24
diff --git a/tests/meson.build b/tests/meson.build
index ce86dd3..29aaeb0 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -40,6 +40,7 @@
'src/test_detached_timer.cpp',
'src/test_discrete_threshold.cpp',
'src/test_ensure.cpp',
+ 'src/test_labeled_tuple.cpp',
'src/test_make_id_name.cpp',
'src/test_metric.cpp',
'src/test_numeric_threshold.cpp',
diff --git a/tests/src/test_labeled_tuple.cpp b/tests/src/test_labeled_tuple.cpp
new file mode 100644
index 0000000..85f2edb
--- /dev/null
+++ b/tests/src/test_labeled_tuple.cpp
@@ -0,0 +1,84 @@
+#include "helpers.hpp"
+#include "utils/labeled_tuple.hpp"
+
+#include <iostream>
+#include <limits>
+
+#include <gmock/gmock.h>
+
+using namespace testing;
+
+struct TestingLabelDouble
+{
+ static std::string str()
+ {
+ return "DoubleValue";
+ }
+};
+
+struct TestingLabelString
+{
+ static std::string str()
+ {
+ return "StringValue";
+ }
+};
+
+using LabeledTestingTuple =
+ utils::LabeledTuple<std::tuple<double, std::string>, TestingLabelDouble,
+ TestingLabelString>;
+
+class TestLabeledTupleDoubleSpecialization :
+ public Test,
+ public WithParamInterface<
+ std::tuple<double, std::variant<double, std::string>>>
+{
+ public:
+ const std::string string_value = "Some value";
+};
+
+TEST_P(TestLabeledTupleDoubleSpecialization,
+ serializeAndDeserializeMakesSameTuple)
+{
+ auto [double_value, expected_serialized_value] = GetParam();
+ LabeledTestingTuple initial(double_value, string_value);
+ nlohmann::json serialized(initial);
+
+ EXPECT_EQ(serialized["StringValue"], string_value);
+
+ auto& actual_serialized_value = serialized["DoubleValue"];
+ if (std::holds_alternative<std::string>(expected_serialized_value))
+ {
+ EXPECT_TRUE(actual_serialized_value.is_string());
+ EXPECT_EQ(actual_serialized_value.get<std::string>(),
+ std::get<std::string>(expected_serialized_value));
+ }
+ else
+ {
+ EXPECT_TRUE(actual_serialized_value.is_number());
+ EXPECT_EQ(actual_serialized_value.get<double>(),
+ std::get<double>(expected_serialized_value));
+ }
+
+ LabeledTestingTuple deserialized = serialized.get<LabeledTestingTuple>();
+ EXPECT_EQ(initial, deserialized);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ _, TestLabeledTupleDoubleSpecialization,
+ Values(std::make_tuple(10.0, std::variant<double, std::string>(10.0)),
+ std::make_tuple(std::numeric_limits<double>::infinity(),
+ std::variant<double, std::string>("inf")),
+ std::make_tuple(-std::numeric_limits<double>::infinity(),
+ std::variant<double, std::string>("-inf")),
+ std::make_tuple(std::numeric_limits<double>::quiet_NaN(),
+ std::variant<double, std::string>("NaN"))));
+
+TEST(TestLabeledTupleDoubleSpecializationNegative,
+ ThrowsWhenUnknownLiteralDuringDeserialization)
+{
+ nlohmann::json data = nlohmann::json{{"DoubleValue", "FooBar"},
+ {"StringValue", "Some Text Val"}};
+
+ EXPECT_THROW(data.get<LabeledTestingTuple>(), std::invalid_argument);
+}