Skip to content

Commit

Permalink
PR comments and some cleanup
Browse files Browse the repository at this point in the history
The code should now be testing const/non const permutations of char** string list.
  • Loading branch information
tarcila committed Nov 18, 2024
1 parent 4fba8f4 commit c38ae21
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 54 deletions.
5 changes: 3 additions & 2 deletions src/anari/include/anari/anari_cpp/Traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ ANARI_TYPEFOR_SPECIALIZATION_STRING(char[], ANARI_STRING);
ANARI_TYPEFOR_SPECIALIZATION_STRING(const char *, ANARI_STRING);
ANARI_TYPEFOR_SPECIALIZATION_STRING(const char[], ANARI_STRING);

ANARI_TYPEFOR_SPECIALIZATION(char *[], ANARI_STRING_LIST);
ANARI_TYPEFOR_SPECIALIZATION(char **, ANARI_STRING_LIST);
ANARI_TYPEFOR_SPECIALIZATION_STRING(const char *[], ANARI_STRING_LIST);
ANARI_TYPEFOR_SPECIALIZATION_STRING(const char **, ANARI_STRING_LIST);
ANARI_TYPEFOR_SPECIALIZATION_STRING(const char * const*, ANARI_STRING_LIST);

ANARI_TYPEFOR_SPECIALIZATION(int8_t, ANARI_INT8);
ANARI_TYPEFOR_SPECIALIZATION(int8_t[2], ANARI_INT8_VEC2);
Expand Down
47 changes: 31 additions & 16 deletions src/helium/utility/AnariAny.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,24 +126,13 @@ inline AnariAny::AnariAny(T value) : AnariAny()
static_assert(
detail::validType<T>(), "unknown type used initialize visrtx::AnariAny");

static_assert(
type != ANARI_STRING_LIST, "Don't know how to build a string list from the given type. Please specialize AnariAny constructor."
);

if constexpr (type == ANARI_STRING)
m_string = value;
else if constexpr (type == ANARI_STRING_LIST) {
if constexpr (std::is_same_v<T, std::vector<std::string>>) {
m_stringList = value;
m_stringListPtrs.clear();
} else if constexpr (std::is_same_v<T, const char **>) {
m_stringList.clear();
m_stringListPtrs.clear();
if (value) {
while (*value)
m_stringList.push_back(*value++);
}
} else
static_assert(false,
"AnariAny string list can only be built from const char**, const char*[] and vector<string>.");

} else
else
std::memcpy(m_storage.data(), &value, sizeof(value));

m_type = type;
Expand All @@ -157,6 +146,32 @@ inline AnariAny::AnariAny(bool value) : AnariAny()
*this = AnariAny(ANARI_BOOL, &b);
}

template<>
inline AnariAny::AnariAny(std::vector<std::string> value) : AnariAny()
{
m_stringList = value;
}

template<>
inline AnariAny::AnariAny(char** value) : AnariAny(ANARI_STRING_LIST, value)
{
}

template<>
inline AnariAny::AnariAny(const char** value) : AnariAny(ANARI_STRING_LIST, value)
{
}

template<>
inline AnariAny::AnariAny(char* const* value) : AnariAny(ANARI_STRING_LIST, value)
{
}

template<>
inline AnariAny::AnariAny(const char* const* value) : AnariAny(ANARI_STRING_LIST, value)
{
}

inline AnariAny::AnariAny(ANARIDataType type, const void *v) : AnariAny()
{
m_type = type;
Expand Down
102 changes: 66 additions & 36 deletions tests/unit/test_helium_AnariAny.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
// helium
#include "helium/utility/AnariAny.h"
// std
#include <cstring>
#include <string>
#include <type_traits>

namespace anari {
ANARI_TYPEFOR_SPECIALIZATION(helium::RefCounted *, ANARI_OBJECT);
Expand All @@ -42,26 +44,38 @@ ANARI_TYPEFOR_DEFINITION(helium::RefCounted *);

namespace {

template<typename T>
static constexpr const bool IsStringListLike =
std::is_pointer_v<T> &&
std::is_pointer_v<std::remove_pointer_t<T>> &&
std::is_same_v<std::decay_t<std::remove_pointer_t<std::remove_pointer_t<T>>>, char>;


using helium::AnariAny;

template <typename T>
inline void verify_value(const AnariAny &v, T correctValue)
template<typename T, typename Enabler = void>
struct VerifyValue {
static inline void verify_value(const AnariAny &v, T correctValue)
{
REQUIRE(v.valid());
REQUIRE(v.is<T>());
REQUIRE(v.get<T>() == correctValue);
}
};

template <>
inline void verify_value(const AnariAny &v, const char *correctValue)
struct VerifyValue<const char*> {
static inline void verify_value(const AnariAny &v, const char *correctValue)
{
REQUIRE(v.valid());
REQUIRE(v.type() == ANARI_STRING);
REQUIRE(v.getString() == correctValue);
}
};

template <>
inline void verify_value(const AnariAny &v, const char **correctValue)
template <typename T>
struct VerifyValue<T, std::enable_if_t<IsStringListLike<T>>> {
static inline void verify_value(const AnariAny &v, T correctValue)
{
REQUIRE(v.valid());
REQUIRE(v.type() == ANARI_STRING_LIST);
Expand All @@ -77,38 +91,41 @@ inline void verify_value(const AnariAny &v, const char **correctValue)
}
REQUIRE((it == stringList.cend() && *correctValue == nullptr));
}
};

template <typename T>
inline void test_interface(T testValue, T testValue2)
template<typename T, typename Enabler = void>
struct TestInterface {
using VerifyValue = ::VerifyValue<T>;
static inline void test_interface(T testValue, T testValue2)
{
AnariAny v;
REQUIRE(!v.valid());

SECTION("Can make valid by C++ construction")
{
AnariAny v2(testValue);
verify_value<T>(v2, testValue);
VerifyValue::verify_value(v2, testValue);
}

if (!std::is_same_v<bool, T>) {
SECTION("Can make valid by C construction")
{
AnariAny v2(anari::ANARITypeFor<T>::value, &testValue);
verify_value<T>(v2, testValue);
VerifyValue::verify_value(v2, testValue);
}
}

SECTION("Can make valid by calling operator=()")
{
v = testValue;
verify_value<T>(v, testValue);
VerifyValue::verify_value(v, testValue);
}

SECTION("Can make valid by copy construction")
{
v = testValue;
AnariAny v2(v);
verify_value<T>(v2, testValue);
VerifyValue::verify_value(v2, testValue);
}

SECTION("Two objects with same value are equal if constructed the same")
Expand All @@ -134,36 +151,39 @@ inline void test_interface(T testValue, T testValue2)
REQUIRE(v != v2);
}
}
};

template <>
inline void test_interface(const char *testValue, const char *testValue2)
template<>
struct TestInterface<const char*> {
using VerifyValue = ::VerifyValue<const char*>;
static inline void test_interface(const char* testValue, const char* testValue2)
{
AnariAny v;
REQUIRE(!v.valid());

SECTION("Can make valid by C++ construction")
{
AnariAny v2(testValue);
verify_value(v2, testValue);
VerifyValue::verify_value(v2, testValue);
}

SECTION("Can make valid by C construction")
{
AnariAny v2(ANARI_STRING, testValue);
verify_value(v2, testValue);
VerifyValue::verify_value(v2, testValue);
}

SECTION("Can make valid by calling operator=()")
{
v = testValue;
verify_value(v, testValue);
VerifyValue::verify_value(v, testValue);
}

SECTION("Can make valid by copy construction")
{
v = testValue;
AnariAny v2(v);
verify_value(v2, testValue);
VerifyValue::verify_value(v2, testValue);
}

SECTION("Two objects with same value are equal if constructed the same")
Expand All @@ -189,36 +209,39 @@ inline void test_interface(const char *testValue, const char *testValue2)
REQUIRE(v != v2);
}
}
};

template <>
inline void test_interface(const char **testValue, const char **testValue2)
template <typename T>
struct TestInterface<T, std::enable_if_t<IsStringListLike<T>>> {
using VerifyValue = ::VerifyValue<T>;
static inline void test_interface(T testValue, T testValue2)
{
AnariAny v;
REQUIRE(!v.valid());

SECTION("Can make valid by C++ construction")
{
AnariAny v2(testValue);
verify_value(v2, testValue);
VerifyValue::verify_value(v2, testValue);
}

SECTION("Can make valid by C construction")
{
AnariAny v2(ANARI_STRING_LIST, testValue);
verify_value(v2, testValue);
VerifyValue::verify_value(v2, testValue);
}

SECTION("Can make valid by calling operator=()")
{
v = testValue;
verify_value(v, testValue);
VerifyValue::verify_value(v, testValue);
}

SECTION("Can make valid by copy construction")
{
v = testValue;
AnariAny v2(v);
verify_value(v2, testValue);
VerifyValue::verify_value(v2, testValue);
}

SECTION("Two objects with same value are equal if constructed the same")
Expand Down Expand Up @@ -247,7 +270,7 @@ inline void test_interface(const char **testValue, const char **testValue2)
SECTION("Get raw data from matches the input data")
{
v = testValue;
const char **anyValue = reinterpret_cast<const char **>(v.data());
auto anyValue = reinterpret_cast<decltype(testValue)>(v.data());
REQUIRE(anyValue != nullptr);
while (*testValue && *anyValue) {
REQUIRE(strcmp(*testValue++, *anyValue++) == 0);
Expand All @@ -256,43 +279,50 @@ inline void test_interface(const char **testValue, const char **testValue2)
REQUIRE(*anyValue == nullptr);
}
}
};

// Value Tests ////////////////////////////////////////////////////////////////

TEST_CASE("helium::AnariAny 'int' type behavior", "[helium_AnariAny]")
{
test_interface<int>(5, 7);
TestInterface<int>::test_interface(5, 7);
}

TEST_CASE("helium::AnariAny 'float' type behavior", "[helium_AnariAny]")
{
test_interface<float>(1.f, 2.f);
TestInterface<float>::test_interface(1.f, 2.f);
}

TEST_CASE("helium::AnariAny 'bool' type behavior", "[helium_AnariAny]")
{
test_interface<bool>(true, false);
TestInterface<bool>::test_interface(true, false);
}

TEST_CASE("helium::AnariAny 'string' type behavior", "[helium_AnariAny]")
{
test_interface<const char *>("test1", "test2");
TestInterface<const char *>::test_interface("test1", "test2");
}

TEST_CASE("helium::AnariAny 'stringList' type behavior", "[helium_AnariAny]")
{
const char *test1[] = {
"a",
"b",
"c",
char *test1[] = {
strdup("a"),
strdup("b"),
strdup("c"),
nullptr,
};
const char *test2[] = {
"d",
"e",
char *test2[] = {
strdup("d"),
strdup("e"),
nullptr,
};
test_interface<const char **>(test1, test2);
TestInterface<char **>::test_interface(test1, test2);
TestInterface<const char **>::test_interface((const char**)test1, (const char**)test2);
TestInterface<char * const*>::test_interface((char*const*)test1, (char*const*)test2);
TestInterface<const char * const*>::test_interface((const char*const*)test1, (const char*const*)test2);

for (auto ptr : test1) free(ptr);
for (auto ptr : test2) free(ptr);
}
// Object Tests ///////////////////////////////////////////////////////////////

Expand Down

0 comments on commit c38ae21

Please sign in to comment.