summaryrefslogtreecommitdiff
path: root/test/test-value-map.cpp
diff options
context:
space:
mode:
authorVasile Vilvoiu <vasi@vilvoiu.ro>2021-07-21 18:43:02 +0300
committerVasile Vilvoiu <vasi@vilvoiu.ro>2021-07-21 18:43:02 +0300
commita7c430fa81c9e22dbce74869a0a27304da78855b (patch)
tree8a9f91f64131f404f61ba33bd92082996ca13c1c /test/test-value-map.cpp
parent270dfd60cde3a7b65a2654eef0f299f32ca704c4 (diff)
Implement unit tests.
ColorMap, FFT, InputParser, InputReader, ValueMap, WindowFunction. Closes #11.
Diffstat (limited to 'test/test-value-map.cpp')
-rw-r--r--test/test-value-map.cpp129
1 files changed, 129 insertions, 0 deletions
diff --git a/test/test-value-map.cpp b/test/test-value-map.cpp
new file mode 100644
index 0000000..940e70f
--- /dev/null
+++ b/test/test-value-map.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2020-2021 Vasile Vilvoiu <vasi@vilvoiu.ro>
+ *
+ * specgram is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+#include "test.hpp"
+#include "../src/value-map.hpp"
+#include <vector>
+#include <cmath>
+
+static std::vector<ValueMapType> ALL_VALUE_MAP_TYPES { ValueMapType::kLinear, ValueMapType::kDecibel };
+
+TEST(TestValueMap, FactoryWrongType)
+{
+ EXPECT_THROW_MATCH(auto ret = ValueMap::Build((ValueMapType)999, 0.0, 1.0, "V"),
+ std::runtime_error, "unknown value map type");
+}
+
+TEST(TestValueMap, FactoryBoundsOrder)
+{
+ for (auto type : ALL_VALUE_MAP_TYPES) {
+ EXPECT_THROW_MATCH(auto ret = ValueMap::Build(type, 1.0, 0.0, ""),
+ std::runtime_error, "lower bound cannot exceed upper bound");
+ EXPECT_THROW_MATCH(auto ret = ValueMap::Build(type, std::numeric_limits<double>::quiet_NaN(), 0.0, ""),
+ std::runtime_error, "bounds cannot be nan or inf");
+ EXPECT_THROW_MATCH(auto ret = ValueMap::Build(type, std::numeric_limits<double>::infinity(), 0.0, ""),
+ std::runtime_error, "bounds cannot be nan or inf");
+ EXPECT_NO_THROW(auto ret = ValueMap::Build(type, 1.0, 1.0, ""));
+ }
+}
+
+TEST(TestValueMap, FactoryBoundsNanInf)
+{
+ for (auto type : ALL_VALUE_MAP_TYPES) {
+ EXPECT_THROW_MATCH(auto ret = ValueMap::Build(type, std::numeric_limits<double>::quiet_NaN(), 0.0, ""),
+ std::runtime_error, "bounds cannot be nan or inf");
+ EXPECT_THROW_MATCH(auto ret = ValueMap::Build(type, std::numeric_limits<double>::infinity(), 0.0, ""),
+ std::runtime_error, "bounds cannot be nan or inf");
+ EXPECT_THROW_MATCH(auto ret = ValueMap::Build(type, 0.0, std::numeric_limits<double>::quiet_NaN(), ""),
+ std::runtime_error, "bounds cannot be nan or inf");
+ EXPECT_THROW_MATCH(auto ret = ValueMap::Build(type, 0.0, std::numeric_limits<double>::infinity(), ""),
+ std::runtime_error, "bounds cannot be nan or inf");
+ }
+}
+
+TEST(TestValueMap, GetUnit)
+{
+ EXPECT_STREQ(ValueMap::Build(ValueMapType::kLinear, 0.0, 1.0, "")->GetUnit().c_str(), "");
+ EXPECT_STREQ(ValueMap::Build(ValueMapType::kDecibel, 0.0, 1.0, "")->GetUnit().c_str(), "dB");
+ EXPECT_STREQ(ValueMap::Build(ValueMapType::kLinear, 0.0, 1.0, "V")->GetUnit().c_str(), "V");
+ EXPECT_STREQ(ValueMap::Build(ValueMapType::kDecibel, 0.0, 1.0, "V")->GetUnit().c_str(), "dBV");
+}
+
+TEST(TestValueMap, LinearMapDomain)
+{
+ constexpr double lower_bound = -33.0;
+ constexpr double upper_bound = 57.0;
+ constexpr double epsilon = 1e-9;
+ constexpr std::size_t steps = 100;
+
+ std::unique_ptr<ValueMap> map;
+ EXPECT_NO_THROW(map = ValueMap::Build(ValueMapType::kLinear, lower_bound, upper_bound, ""));
+
+ for (std::size_t i=0; i<=steps; i++) {
+ double expect = (double)i / (double)steps;
+ double input = lower_bound + (upper_bound - lower_bound) * expect;
+ auto out = map->Map(RealWindow { input });
+
+ EXPECT_EQ(out.size(), 1);
+ EXPECT_LE(std::abs(out[0] - expect), epsilon);
+ }
+
+ {
+ RealWindow expect(steps+1);
+ RealWindow win(steps+1);
+ for (std::size_t i = 0; i <= steps; i++) {
+ expect[i] = (double) i / (double) steps;
+ win[i] = lower_bound + (upper_bound - lower_bound) * expect[i];
+ }
+ RealWindow out;
+ EXPECT_NO_THROW(out = map->Map(win));
+ for (std::size_t i = 0; i <= steps; i++) {
+ EXPECT_LE(std::abs(out[i] - expect[i]), epsilon);
+ }
+ }
+
+ EXPECT_LE(std::abs(map->Map(RealWindow { -40.0 })[0]), epsilon);
+ EXPECT_LE(std::abs(map->Map(RealWindow { 70.0 })[0] - 1.0), epsilon);
+}
+
+TEST(TestValueMap, LogarithmicMapDomain)
+{
+ constexpr double lower_bound = -120.;
+ constexpr double upper_bound = 20.0;
+ constexpr double epsilon = 1e-9;
+ constexpr std::size_t steps = 100;
+
+ std::unique_ptr<ValueMap> map;
+ EXPECT_NO_THROW(map = ValueMap::Build(ValueMapType::kDecibel, lower_bound, upper_bound, ""));
+
+ for (std::size_t i=0; i<=steps; i++) {
+ double expect = (double)i / (double)steps;
+ /* y = 20log10(x) */
+ /* x = 10^(y/20) */
+ double input = std::pow(10.0, (lower_bound + (upper_bound - lower_bound) * expect) / 20.0);
+ auto out = map->Map(RealWindow { input });
+
+ EXPECT_EQ(out.size(), 1);
+ EXPECT_LE(std::abs(out[0] - expect), epsilon);
+ }
+
+ {
+ RealWindow expect(steps+1);
+ RealWindow win(steps+1);
+ for (std::size_t i = 0; i <= steps; i++) {
+ expect[i] = (double) i / (double) steps;
+ win[i] = std::pow(10.0, (lower_bound + (upper_bound - lower_bound) * expect[i]) / 20.0);
+ }
+ RealWindow out;
+ EXPECT_NO_THROW(out = map->Map(win));
+ for (std::size_t i = 0; i <= steps; i++) {
+ EXPECT_LE(std::abs(out[i] - expect[i]), epsilon);
+ }
+ }
+
+ EXPECT_LE(std::abs(map->Map(RealWindow { 0.0 })[0]), epsilon);
+ EXPECT_LE(std::abs(map->Map(RealWindow { 100.0 })[0] - 1.0), epsilon);
+} \ No newline at end of file