aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libnvxx/nvxx.cc278
-rw-r--r--libnvxx/nvxx_base.h72
-rw-r--r--libnvxx/tests/nvxx_basic.cc297
3 files changed, 608 insertions, 39 deletions
diff --git a/libnvxx/nvxx.cc b/libnvxx/nvxx.cc
index 69b57f5..8decebf 100644
--- a/libnvxx/nvxx.cc
+++ b/libnvxx/nvxx.cc
@@ -376,7 +376,21 @@ __const_nv_list::exists_null(std::string_view key) const
void
__nv_list::add_null(std::string_view key)
{
- ::nvlist_add_null(__m_nv, std::string(key).c_str());
+ auto skey = std::string(key);
+
+ ::nvlist_add_null(__m_nv, skey.c_str());
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
void
@@ -392,7 +406,21 @@ __nv_list::free_null(std::string_view key)
void
__nv_list::add_bool(std::string_view key, bool value)
{
- ::nvlist_add_bool(__m_nv, std::string(key).c_str(), value);
+ auto skey = std::string(key);
+
+ ::nvlist_add_bool(__m_nv, skey.c_str(), value);
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
bool
@@ -404,13 +432,23 @@ __const_nv_list::exists_bool(std::string_view key) const
bool
__const_nv_list::get_bool(std::string_view key) const
{
- return ::nvlist_get_bool(__m_nv, std::string(key).c_str());
+ auto skey = std::string(key);
+
+ if (!::nvlist_exists_bool(__m_nv, skey.c_str()))
+ throw nv_key_not_found(skey);
+
+ return ::nvlist_get_bool(__m_nv, skey.c_str());
}
bool
__nv_list::take_bool(std::string_view key)
{
- return ::nvlist_take_bool(__m_nv, std::string(key).c_str());
+ auto skey = std::string(key);
+
+ if (!::nvlist_exists_bool(__m_nv, skey.c_str()))
+ throw nv_key_not_found(skey);
+
+ return ::nvlist_take_bool(__m_nv, skey.c_str());
}
void
@@ -449,10 +487,23 @@ void
__nv_list::add_bool_array(std::string_view key,
std::span<bool const> value)
{
- ::nvlist_add_bool_array(__m_nv,
- std::string(key).c_str(),
+ auto skey = std::string(key);
+
+ ::nvlist_add_bool_array(__m_nv, skey.c_str(),
std::ranges::data(value),
std::ranges::size(value));
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
void
@@ -482,7 +533,21 @@ __nv_list::free_bool_array(std::string_view key)
void
__nv_list::add_number(std::string_view key, std::uint64_t value)
{
- ::nvlist_add_number(__m_nv, std::string(key).c_str(), value);
+ auto skey = std::string(key);
+
+ ::nvlist_add_number(__m_nv, skey.c_str(), value);
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
bool
@@ -494,13 +559,23 @@ __const_nv_list::exists_number(std::string_view key) const
std::uint64_t
__const_nv_list::get_number(std::string_view key) const
{
- return ::nvlist_get_number(__m_nv, std::string(key).c_str());
+ auto skey = std::string(key);
+
+ if (!::nvlist_exists_number(__m_nv, skey.c_str()))
+ throw nv_key_not_found(skey);
+
+ return ::nvlist_get_number(__m_nv, skey.c_str());
}
std::uint64_t
__nv_list::take_number(std::string_view key)
{
- return ::nvlist_take_number(__m_nv, std::string(key).c_str());
+ auto skey = std::string(key);
+
+ if (!::nvlist_exists_number(__m_nv, skey.c_str()))
+ throw nv_key_not_found(skey);
+
+ return ::nvlist_take_number(__m_nv, skey.c_str());
}
void
@@ -539,9 +614,23 @@ void
__nv_list::add_number_array(std::string_view key,
std::span<std::uint64_t const> value)
{
- ::nvlist_add_number_array(__m_nv, std::string(key).c_str(),
+ auto skey = std::string(key);
+
+ ::nvlist_add_number_array(__m_nv, skey.c_str(),
std::ranges::data(value),
std::ranges::size(value));
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
void
@@ -572,9 +661,21 @@ __nv_list::free_number_array(std::string_view key)
void
__nv_list::add_string(std::string_view key, std::string_view value)
{
- ::nvlist_add_string(__m_nv,
- std::string(key).c_str(),
- std::string(value).c_str());
+ auto skey = std::string(key);
+
+ ::nvlist_add_string(__m_nv, skey.c_str(), std::string(value).c_str());
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
void
@@ -592,13 +693,23 @@ __const_nv_list::exists_string(std::string_view key) const
std::string_view
__const_nv_list::get_string(std::string_view key) const
{
- return nvlist_get_string(__m_nv, std::string(key).c_str());
+ auto skey = std::string(key);
+
+ if (!::nvlist_exists_string(__m_nv, skey.c_str()))
+ throw nv_key_not_found(skey);
+
+ return nvlist_get_string(__m_nv, skey.c_str());
}
std::string
__nv_list::take_string(std::string_view key)
{
- return nvlist_take_string(__m_nv, std::string(key).c_str());
+ auto skey = std::string(key);
+
+ if (!::nvlist_exists_string(__m_nv, skey.c_str()))
+ throw nv_key_not_found(skey);
+
+ return nvlist_take_string(__m_nv, skey.c_str());
}
void
@@ -611,6 +722,8 @@ void
__nv_list::add_string_array(std::string_view key,
std::span<std::string_view const> value)
{
+ auto skey = std::string(key);
+
// nvlist_add_string_array expects an array of NUL-terminated
// C strings.
@@ -622,8 +735,20 @@ __nv_list::add_string_array(std::string_view key,
| std::views::transform(&std::string::c_str)
| std::ranges::to<std::vector>();
- nvlist_add_string_array(__m_nv, std::string(key).c_str(),
- ptrs.data(), ptrs.size());
+ ::nvlist_add_string_array(__m_nv, skey.c_str(),
+ ptrs.data(), ptrs.size());
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
void
@@ -684,7 +809,21 @@ __nv_list::free_string_array(std::string_view key)
void
__nv_list::add_nvlist(std::string_view key, const_nv_list const &other)
{
- nvlist_add_nvlist(__m_nv, std::string(key).c_str(), other.__m_nv);
+ auto skey = std::string(key);
+
+ ::nvlist_add_nvlist(__m_nv, skey.c_str(), other.__m_nv);
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
void
@@ -709,14 +848,24 @@ __const_nv_list::exists_nvlist(std::string_view key) const
const_nv_list
__const_nv_list::get_nvlist(std::string_view key) const
{
- auto nvl = nvlist_get_nvlist(__m_nv, std::string(key).c_str());
+ auto skey = std::string(key);
+
+ if (!::nvlist_exists_nvlist(__m_nv, skey.c_str()))
+ throw nv_key_not_found(skey);
+
+ auto nvl = ::nvlist_get_nvlist(__m_nv, skey.c_str());
return const_nv_list(nvl);
}
nv_list
__nv_list::take_nvlist(std::string_view key)
{
- auto nvl = nvlist_take_nvlist(__m_nv, std::string(key).c_str());
+ auto skey = std::string(key);
+
+ if (!::nvlist_exists_nvlist(__m_nv, skey.c_str()))
+ throw nv_key_not_found(skey);
+
+ auto nvl = nvlist_take_nvlist(__m_nv, skey.c_str());
return nv_list(nvl);
}
@@ -736,24 +885,52 @@ void
__nv_list::add_nvlist_array(std::string_view key,
std::span<const_nv_list const> value)
{
+ auto skey = std::string(key);
+
auto ptrs = value
| std::views::transform(&const_nv_list::__m_nv)
| std::ranges::to<std::vector>();
- ::nvlist_add_nvlist_array(__m_nv, std::string(key).c_str(),
+ ::nvlist_add_nvlist_array(__m_nv, skey.c_str(),
ptrs.data(), ptrs.size());
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
void
__nv_list::add_nvlist_array(std::string_view key,
std::span<nv_list const> value)
{
+ auto skey = std::string(key);
+
auto ptrs = value
| std::views::transform(&nv_list::__m_nv)
| std::ranges::to<std::vector>();
- nvlist_add_nvlist_array(__m_nv, std::string(key).c_str(),
+ nvlist_add_nvlist_array(__m_nv, skey.c_str(),
ptrs.data(), ptrs.size());
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
void
@@ -820,7 +997,21 @@ __nv_list::take_descriptor(std::string_view key)
void
__nv_list::add_descriptor(std::string_view key, int value)
{
- ::nvlist_add_descriptor(__m_nv, std::string(key).c_str(), value);
+ auto skey = std::string(key);
+
+ ::nvlist_add_descriptor(__m_nv, skey.c_str(), value);
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
void
@@ -847,9 +1038,23 @@ void
__nv_list::add_descriptor_array(std::string_view key,
std::span<int const> value)
{
- ::nvlist_add_descriptor_array(__m_nv, std::string(key).c_str(),
+ auto skey = std::string(key);
+
+ ::nvlist_add_descriptor_array(__m_nv, skey.c_str(),
std::ranges::data(value),
std::ranges::size(value));
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
void
@@ -912,9 +1117,23 @@ __const_nv_list::exists_binary(std::string_view key) const
void
__nv_list::add_binary(std::string_view key, std::span<std::byte const> value)
{
- ::nvlist_add_binary(__m_nv, std::string(key).c_str(),
+ auto skey = std::string(key);
+
+ ::nvlist_add_binary(__m_nv, skey.c_str(),
std::ranges::data(value),
std::ranges::size(value));
+
+ switch (auto err = ::nvlist_error(__m_nv)) {
+ case 0:
+ return;
+
+ case EEXIST:
+ throw nv_key_exists(skey);
+
+ default:
+ throw std::system_error(
+ std::error_code(err, std::generic_category()));
+ }
}
void
@@ -943,10 +1162,13 @@ __const_nv_list::get_binary(std::string_view key) const
std::vector<std::byte>
__nv_list::take_binary(std::string_view key)
{
+ auto skey = std::string(key);
+
+ if (!::nvlist_exists_binary(__m_nv, skey.c_str()))
+ throw nv_key_not_found(skey);
+
auto size = std::size_t{};
- auto *data = ::nvlist_take_binary(__m_nv,
- std::string(key).c_str(),
- &size);
+ auto *data = ::nvlist_take_binary(__m_nv, skey.c_str(), &size);
auto ptr = ptr_guard(static_cast<std::byte *>(data));
return {ptr.ptr, ptr.ptr + size};
}
diff --git a/libnvxx/nvxx_base.h b/libnvxx/nvxx_base.h
index aa0a765..4700e79 100644
--- a/libnvxx/nvxx_base.h
+++ b/libnvxx/nvxx_base.h
@@ -33,12 +33,42 @@
#include <system_error>
#include <vector>
#include <stdexcept>
+#include <format>
namespace bsd {
struct nv_list;
struct const_nv_list;
+struct nv_error : std::runtime_error {
+ template<typename... _Args>
+ nv_error(std::format_string<_Args...> __fmt, _Args && ...__args)
+ : runtime_error(std::format(__fmt,
+ std::forward<_Args>(__args)...))
+ {
+ }
+};
+
+struct nv_key_not_found : nv_error {
+ std::string key;
+
+ nv_key_not_found(std::string __key)
+ : nv_error("key \"{0}\" not found", __key)
+ , key(__key)
+ {
+ }
+};
+
+struct nv_key_exists : nv_error {
+ std::string key;
+
+ nv_key_exists(std::string __key)
+ : nv_error("key \"{0}\" already exists", __key)
+ , key(__key)
+ {
+ }
+};
+
namespace __detail {
enum struct __nvlist_owning {
@@ -413,6 +443,48 @@ struct __nv_list : virtual __nv_list_base {
auto __arr = std::vector(std::from_range, __value);
add_number_range(__key, __arr);
}
+
+ /* add_nvlist_range */
+
+ template<std::ranges::contiguous_range _Range>
+ requires std::is_same_v<nv_list,
+ std::remove_cvref_t<
+ std::ranges::range_value_t<_Range>>>
+ void add_nvlist_range(std::string_view __key, _Range &&__value)
+ {
+ add_nvlist_array(__key, std::span(__value));
+ }
+
+ template<std::ranges::range _Range>
+ requires (!std::ranges::contiguous_range<_Range>
+ && std::is_same_v<nv_list,
+ std::remove_cvref_t<
+ std::ranges::range_value_t<_Range>>>)
+ void add_nvlist_range(std::string_view __key, _Range &&__value)
+ {
+ auto __arr = std::vector(std::from_range, __value);
+ add_nvlist_range(__key, __arr);
+ }
+
+ template<std::ranges::contiguous_range _Range>
+ requires std::is_same_v<const_nv_list,
+ std::remove_cvref_t<
+ std::ranges::range_value_t<_Range>>>
+ void add_nvlist_range(std::string_view __key, _Range &&__value)
+ {
+ add_nvlist_array(__key, std::span(__value));
+ }
+
+ template<std::ranges::range _Range>
+ requires (!std::ranges::contiguous_range<_Range>
+ && std::is_same_v<const_nv_list,
+ std::remove_cvref_t<
+ std::ranges::range_value_t<_Range>>>)
+ void add_nvlist_range(std::string_view __key, _Range &&__value)
+ {
+ auto __arr = std::vector(std::from_range, __value);
+ add_nvlist_range(__key, __arr);
+ }
};
} // namespace bsd::__detail
diff --git a/libnvxx/tests/nvxx_basic.cc b/libnvxx/tests/nvxx_basic.cc
index 1cf2bfd..7cdf639 100644
--- a/libnvxx/tests/nvxx_basic.cc
+++ b/libnvxx/tests/nvxx_basic.cc
@@ -66,10 +66,40 @@ TEST_CASE(nvxx_ignore_case)
TEST_CASE(nvxx_add_null)
{
+ using namespace std::literals;
+ auto constexpr key = "test_null"sv;
+
+ auto nvl = bsd::nv_list();
+ nvl.add_null(key);
+ ATF_REQUIRE_EQ(true, nvl.exists_null(key));
+ ATF_REQUIRE_EQ(true, nvl.exists(key));
+}
+
+TEST_CASE(nvxx_add_duplicate_null)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_null"sv;
+
+ auto nvl = bsd::nv_list();
+ nvl.add_null(key);
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_exists,
+ "key \"test_null\" already exists",
+ nvl.add_null(key));
+}
+
+TEST_CASE(nvxx_free_null)
+{
+ using namespace std::literals;
+ auto constexpr key = "test null"sv;
+
auto nvl = bsd::nv_list();
- nvl.add_null("test");
- ATF_REQUIRE_EQ(true, nvl.exists_null("test"));
- ATF_REQUIRE_EQ(true, nvl.exists("test"));
+
+ nvl.add_null(key);
+ ATF_REQUIRE_EQ(true, nvl.exists_null(key));
+
+ nvl.free_null(key);
+ ATF_REQUIRE_EQ(false, nvl.exists_null(key));
}
/*
@@ -90,6 +120,29 @@ TEST_CASE(nvxx_add_bool)
ATF_REQUIRE_EQ(value, nvl.get_bool(key));
}
+TEST_CASE(nvxx_add_duplicate_bool)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_bool"sv;
+ auto constexpr value = true;
+
+ auto nvl = bsd::nv_list();
+ nvl.add_bool(key, value);
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_exists,
+ "key \"test_bool\" already exists",
+ nvl.add_bool(key, value));
+}
+
+TEST_CASE(nvxx_get_nonexistent_bool)
+{
+ auto nvl = bsd::nv_list();
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_not_found,
+ "key \"nonesuch\" not found",
+ (void)nvl.get_bool("nonesuch"));
+}
+
TEST_CASE(nvxx_take_bool)
{
using namespace std::literals;
@@ -100,7 +153,10 @@ TEST_CASE(nvxx_take_bool)
nvl.add_bool(key, value);
auto b = nvl.take_bool(key);
ATF_REQUIRE_EQ(value, b);
- ATF_REQUIRE_EQ(false, nvl.exists(key));
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_not_found,
+ "key \"test_bool\" not found",
+ (void)nvl.take_bool(key));
}
TEST_CASE(nvxx_free_bool)
@@ -140,6 +196,21 @@ TEST_CASE(nvxx_add_bool_array)
ATF_REQUIRE_EQ(false, nvl.exists(key));
}
+TEST_CASE(nvxx_add_duplicate_bool_array)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_bool"sv;
+ auto data = std::array<bool, 2>{true, false};
+ auto value = std::span(data);
+
+ auto nvl = bsd::nv_list();
+ nvl.add_bool_array(key, value);
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_exists,
+ "key \"test_bool\" already exists",
+ nvl.add_bool_array(key, value));
+}
+
TEST_CASE(nvxx_add_bool_range)
{
using namespace std::literals;
@@ -201,6 +272,28 @@ TEST_CASE(nvxx_add_number)
ATF_REQUIRE_EQ(value, nvl.get_number(key));
}
+TEST_CASE(nvxx_add_duplicate_number)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_number"sv;
+ auto constexpr value = 42u;
+
+ auto nvl = bsd::nv_list();
+ nvl.add_number(key, value);
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_exists,
+ "key \"test_number\" already exists",
+ nvl.add_number(key, value));
+}
+
+TEST_CASE(nvxx_get_nonexistent_number)
+{
+ auto nvl = bsd::nv_list();
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_not_found,
+ "key \"nonesuch\" not found",
+ (void)nvl.get_number("nonesuch"));
+}
+
TEST_CASE(nvxx_take_number)
{
using namespace std::literals;
@@ -212,7 +305,10 @@ TEST_CASE(nvxx_take_number)
nvl.add_number(key, value);
auto n = nvl.take_number(key);
ATF_REQUIRE_EQ(value, n);
- ATF_REQUIRE_EQ(false, nvl.exists(key));
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_not_found,
+ "key \"test_number\" not found",
+ (void)nvl.take_number(key));
}
TEST_CASE(nvxx_free_number)
@@ -251,6 +347,20 @@ TEST_CASE(nvxx_add_number_array)
ATF_REQUIRE_EQ(false, nvl.exists(key));
}
+TEST_CASE(nvxx_add_duplicate_number_array)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_number"sv;
+ auto value = std::vector{42_u64, 1024_u64};
+
+ auto nvl = bsd::nv_list();
+ nvl.add_number_range(key, value);
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_exists,
+ "key \"test_number\" already exists",
+ nvl.add_number_range(key, value));
+}
+
TEST_CASE(nvxx_add_number_range)
{
using namespace std::literals;
@@ -307,6 +417,28 @@ TEST_CASE(nvxx_add_string)
ATF_REQUIRE_EQ(value, nvl.get_string(key));
}
+TEST_CASE(nvxx_add_duplicate_string)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_string"sv;
+ auto constexpr value = "testing value"sv;
+
+ auto nvl = bsd::nv_list();
+ nvl.add_string(key, value);
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_exists,
+ "key \"test_string\" already exists",
+ nvl.add_string(key, value));
+}
+
+TEST_CASE(nvxx_get_nonexistent_string)
+{
+ auto nvl = bsd::nv_list();
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_not_found,
+ "key \"nonesuch\" not found",
+ (void)nvl.get_string("nonesuch"));
+}
+
TEST_CASE(nvxx_take_string)
{
using namespace std::literals;
@@ -317,7 +449,10 @@ TEST_CASE(nvxx_take_string)
nvl.add_string(key, value);
auto s = nvl.take_string(key);
ATF_REQUIRE_EQ(value, s);
- ATF_REQUIRE_EQ(false, nvl.exists(key));
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_not_found,
+ "key \"test_string\" not found",
+ (void)nvl.take_string(key));
}
TEST_CASE(nvxx_free_string)
@@ -353,6 +488,20 @@ TEST_CASE(nvxx_add_string_array)
ATF_REQUIRE_EQ(false, nvl.exists(key));
}
+TEST_CASE(nvxx_add_duplicate_string_array)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_string"sv;
+ auto value = std::vector{"one"sv, "two"sv, "three"sv};
+
+ auto nvl = bsd::nv_list();
+ nvl.add_string_range(key, value);
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_exists,
+ "key \"test_string\" already exists",
+ nvl.add_string_range(key, value));
+}
+
TEST_CASE(nvxx_add_string_range)
{
using namespace std::literals;
@@ -412,16 +561,43 @@ TEST_CASE(nvxx_add_nvlist)
.get_number("test_number"));
}
+TEST_CASE(nvxx_add_duplicate_nvlist)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_nvlist"sv;
+ auto value = bsd::nv_list{};
+
+ auto nvl = bsd::nv_list{};
+ nvl.add_nvlist(key, value);
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_exists,
+ "key \"test_nvlist\" already exists",
+ nvl.add_nvlist(key, value));
+}
+
+TEST_CASE(nvxx_get_nonexistent_nvlist)
+{
+ auto nvl = bsd::nv_list();
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_not_found,
+ "key \"nonesuch\" not found",
+ (void)nvl.get_nvlist("nonesuch"));
+}
+
TEST_CASE(nvxx_take_nvlist)
{
+ using namespace std::literals;
+ auto constexpr key = "test_nvlist"sv;
auto nvl = bsd::nv_list(), nvl2 = bsd::nv_list();
nvl2.add_number("test_number", 42);
- nvl.add_nvlist("test_nvlist", nvl2);
+ nvl.add_nvlist(key, nvl2);
- auto nvl3 = nvl.take_nvlist("test_nvlist");
- ATF_REQUIRE_EQ(false, nvl.exists("test_nvlist"));
+ auto nvl3 = nvl.take_nvlist(key);
ATF_REQUIRE_EQ(42, nvl3.get_number("test_number"));
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_not_found,
+ "key \"test_nvlist\" not found",
+ (void)nvl.take_nvlist(key));
}
TEST_CASE(nvxx_free_nvlist)
@@ -469,9 +645,23 @@ TEST_CASE(nvxx_add_nvlist_array)
ATF_REQUIRE_EQ(n2, 2);
}
+TEST_CASE(nvxx_add_duplicate_nvlist_array)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_nvlist"sv;
+ auto value = std::vector<bsd::nv_list>(2);
+
+ auto nvl = bsd::nv_list();
+ nvl.add_nvlist_range(key, value);
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_exists,
+ "key \"test_nvlist\" already exists",
+ nvl.add_nvlist_range(key, value));
+}
+
TEST_CASE(nvxx_add_descriptor)
{
- int fds[2] = {};
+ auto fds = std::array<int, 2>{};
auto ret = ::pipe(&fds[0]);
ATF_REQUIRE_EQ(0, ret);
@@ -479,7 +669,7 @@ TEST_CASE(nvxx_add_descriptor)
decltype([](auto fds) {
::close(fds[0]);
::close(fds[1]);
- })>(fds);
+ })>(&fds[0]);
auto nvl = bsd::nv_list();
nvl.add_descriptor("test_descriptor", fds[0]);
@@ -500,6 +690,33 @@ TEST_CASE(nvxx_add_descriptor)
ATF_REQUIRE_EQ('4', buf[3]);
}
+TEST_CASE(nvxx_add_duplicate_descriptor)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_descriptor"sv;
+
+ auto fds = std::array<int, 2>{};
+ auto ret = ::pipe(&fds[0]);
+ ATF_REQUIRE_EQ(0, ret);
+
+ auto guard = std::unique_ptr<int[],
+ decltype([](auto fds) {
+ ::close(fds[0]);
+ ::close(fds[1]);
+ })>(&fds[0]);
+
+ auto nvl = bsd::nv_list{};
+ nvl.add_descriptor(key, fds[0]);
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_exists,
+ "key \"test_descriptor\" already exists",
+ nvl.add_descriptor(key, fds[0]));
+}
+
+/*
+ * binary
+ */
+
TEST_CASE(nvxx_add_binary)
{
auto nvl = bsd::nv_list();
@@ -516,6 +733,41 @@ TEST_CASE(nvxx_add_binary)
ATF_REQUIRE_EQ(true, std::ranges::equal(data, data2));
}
+TEST_CASE(nvxx_add_duplicate_binary)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_binary"sv;
+ auto constexpr value = std::array<std::byte, 16>{};
+
+ auto nvl = bsd::nv_list();
+ nvl.add_binary(key, value);
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_exists,
+ "key \"test_binary\" already exists",
+ nvl.add_binary(key, value));
+}
+
+TEST_CASE(nvxx_take_binary)
+{
+ using namespace std::literals;
+ auto constexpr key = "test_binary"sv;
+ auto nvl = bsd::nv_list();
+
+ auto data = std::array<std::byte, 16>{};
+
+ for (auto i = 0u; i < data.size(); ++i)
+ data[i] = static_cast<std::byte>(i);
+
+ nvl.add_binary(key, std::span(data));
+
+ auto data2 = nvl.take_binary(key);
+ ATF_REQUIRE_EQ(true, std::ranges::equal(data, data2));
+
+ ATF_REQUIRE_THROW_RE(bsd::nv_key_not_found,
+ "key \"test_binary\" not found",
+ (void)nvl.take_binary(key));
+}
+
TEST_CASE(nvxx_add_binary_range)
{
auto nvl = bsd::nv_list();
@@ -538,34 +790,57 @@ ATF_INIT_TEST_CASES(tcs)
ATF_ADD_TEST_CASE(tcs, nvxx_ignore_case);
ATF_ADD_TEST_CASE(tcs, nvxx_add_null);
+ ATF_ADD_TEST_CASE(tcs, nvxx_add_duplicate_null);
+ ATF_ADD_TEST_CASE(tcs, nvxx_free_null);
ATF_ADD_TEST_CASE(tcs, nvxx_add_bool);
+ ATF_ADD_TEST_CASE(tcs, nvxx_add_duplicate_bool);
+ ATF_ADD_TEST_CASE(tcs, nvxx_get_nonexistent_bool);
ATF_ADD_TEST_CASE(tcs, nvxx_take_bool);
ATF_ADD_TEST_CASE(tcs, nvxx_free_bool);
+
ATF_ADD_TEST_CASE(tcs, nvxx_add_bool_array);
+ ATF_ADD_TEST_CASE(tcs, nvxx_add_duplicate_bool_array);
ATF_ADD_TEST_CASE(tcs, nvxx_add_bool_range);
ATF_ADD_TEST_CASE(tcs, nvxx_add_bool_contig_range);
ATF_ADD_TEST_CASE(tcs, nvxx_add_number);
+ ATF_ADD_TEST_CASE(tcs, nvxx_add_duplicate_number);
+ ATF_ADD_TEST_CASE(tcs, nvxx_get_nonexistent_number);
ATF_ADD_TEST_CASE(tcs, nvxx_take_number);
ATF_ADD_TEST_CASE(tcs, nvxx_free_number);
+
ATF_ADD_TEST_CASE(tcs, nvxx_add_number_array);
+ ATF_ADD_TEST_CASE(tcs, nvxx_add_duplicate_number_array);
ATF_ADD_TEST_CASE(tcs, nvxx_add_number_range);
ATF_ADD_TEST_CASE(tcs, nvxx_add_number_contig_range);
ATF_ADD_TEST_CASE(tcs, nvxx_add_string);
+ ATF_ADD_TEST_CASE(tcs, nvxx_add_duplicate_string);
+ ATF_ADD_TEST_CASE(tcs, nvxx_get_nonexistent_string);
ATF_ADD_TEST_CASE(tcs, nvxx_take_string);
ATF_ADD_TEST_CASE(tcs, nvxx_free_string);
+
ATF_ADD_TEST_CASE(tcs, nvxx_add_string_array);
+ ATF_ADD_TEST_CASE(tcs, nvxx_add_duplicate_string_array);
ATF_ADD_TEST_CASE(tcs, nvxx_add_string_range);
ATF_ADD_TEST_CASE(tcs, nvxx_add_string_contig_range);
ATF_ADD_TEST_CASE(tcs, nvxx_add_nvlist);
+ ATF_ADD_TEST_CASE(tcs, nvxx_add_duplicate_nvlist);
+ ATF_ADD_TEST_CASE(tcs, nvxx_get_nonexistent_nvlist);
ATF_ADD_TEST_CASE(tcs, nvxx_take_nvlist);
ATF_ADD_TEST_CASE(tcs, nvxx_free_nvlist);
+
ATF_ADD_TEST_CASE(tcs, nvxx_add_nvlist_array);
+ ATF_ADD_TEST_CASE(tcs, nvxx_add_duplicate_nvlist_array);
ATF_ADD_TEST_CASE(tcs, nvxx_add_descriptor);
+ ATF_ADD_TEST_CASE(tcs, nvxx_add_duplicate_descriptor);
+
ATF_ADD_TEST_CASE(tcs, nvxx_add_binary);
+ ATF_ADD_TEST_CASE(tcs, nvxx_add_duplicate_binary);
+ ATF_ADD_TEST_CASE(tcs, nvxx_take_binary);
+
ATF_ADD_TEST_CASE(tcs, nvxx_add_binary_range);
}