I am trying to test some math operations with GLM using GoogleTest and pretty print when the assertions fail. I have been following the guides regarding the pretty printing and I found a function named PrintTo
. Overloading this function for a custom structure in a namespace works:
namespace my_ns {
struct A {
A(uint32_t a_, uint32_t b_) : a(a_), b(b_) {}
uint32_t a = 0, b = 0;
bool operator==(const A &rhs) const { return a == rhs.a && b == rhs.b; }
};
void PrintTo(const test::A &value, std::ostream *out) {
*out << value.a << " - " << value.b;
}
}
TEST(PrettyTest, Test) { EXPECT_EQ(my_ns::A(10, 20), my_ns::A(20, 25)); }
This works and I get human readable expect failure messages:
error: Expected equality of these values:
my_ns::A(10, 20)
Which is: 10 - 20
my_ns::A(20, 25)
Which is: 20 - 25
However, when I am trying to do the same for GLM math library, I keep getting the default string, which is a binary value:
namespace glm {
void PrintTo(const vec3 &value, std::ostream *out) {
*out << to_string(value);
}
} // namespace glm
TEST_F(PrettyTest, GlmTest) { EXPECT_EQ(glm::vec3(1.0f), glm::vec3(2.0f)); }
The following test prints:
error: Expected equality of these values:
glm::vec3(1.0f)
Which is: 12-byte object <00-00 80-3F 00-00 80-3F 00-00 80-3F>
glm::vec3(2.0f)
Which is: 12-byte object <00-00 00-40 00-00 00-40 00-00 00-40>
This issue only exists in GLM and I cannot figure out what causes this issue. I tried to use different namespaces but I could not get it to working.
CodePudding user response:
As you can see from glm source code here, vec3
is not a type, but a typedef in namespace glm
to the actual type, which for some versions of the library resides in the same glm
namespace (see here), but for other (older) - in glm::detail
namespace (see here). Note that ADL doesn't add namespaces of typedefs to associated namespaces, only namespaces of actual type definitions, which is discussed in
this question. So, since in your case ADL doesn't help to find PrintTo
function in glm
namespace, for your version of glm it most probably will do its job if you put function definition into glm::detail
namespace like this:
namespace glm::detail {
void PrintTo(const ::glm::vec3 &value, std::ostream *out) {
*out << ::glm::to_string(value);
}
} // namespace glm::detail
CodePudding user response:
The issue was that I had many test files but the customization that I was applying was only in one file. I debugged this by removing all the tests and keeping only one. As I did that, everything worked. When I added a new test file as compile target, the printing stopped working. I solved this issue by creating a custom header file and adding encapsulating all the logic in that file and including only that file in my tests:
// Testing.h
#pragma once
namespace glm {
// Covers all vectors
template <length_t L, typename T, qualifier Q>
void PrintTo(const vec<L, T, Q> &value, std::ostream *out) {
*out << to_string(value);
}
// Covers all matrices
template <length_t C, length_t R, typename T, qualifier Q>
void PrintTo(const mat<C, R, T, Q> &value, std::ostream *out) {
*out << to_string(value);
}
// Covers all quaternions
template <typename T, qualifier Q>
void PrintTo(const qua<T, Q> &value, std::ostream *out) {
*out << to_string(value);
}
} // namespace glm
#include <gtest/gtest.h>
#include <gmock/gmock.h>
// ------
// In all my test files
// other includes...
#include "Testing.h"
// test code here