Skip to content

Commit

Permalink
Add more MultiValueProvider tests
Browse files Browse the repository at this point in the history
  • Loading branch information
antis81 committed Jul 16, 2023
1 parent 932064b commit 2c24463
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 15 deletions.
20 changes: 16 additions & 4 deletions src/valueprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ MultiValueProvider::~MultiValueProvider()
}

void MultiValueProvider::setupValues(std::vector<std::string> const& identifiers) {
for (auto sv : identifiers) {
std::string s{sv};
for (auto s : identifiers) {
auto const [it, inserted] = bass_provided_values.insert({s, this});
auto const mvp = it->second;

if (it->second != this) {
if (mvp != this) {
//assert(inserted == false);
throw std::runtime_error(
fmt::format("{} cannot register an already registered identifier '{}' which is already registered by {})",
Expand All @@ -30,11 +29,24 @@ void MultiValueProvider::setupValues(std::vector<std::string> const& identifiers
);
}

// initialize value
// initialize value (always a 'None' value)
vals[s];
}
}

void MultiValueProvider::setupRuntimeValue(std::string const& identifier)
{
auto const [it, inserted] = bass_provided_values.insert({identifier, this});
auto const mvp = it->second;

if (inserted) {
// initialize value (always a 'None' value)
vals[identifier];
} else {
throw std::runtime_error(fmt::format("Symbol '{}' already defined", identifier));
}
}

bool MultiValueProvider::hasAllValues() const
{
for (auto it : bass_provided_values) {
Expand Down
26 changes: 20 additions & 6 deletions src/valueprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class MultiValueProvider
virtual ~MultiValueProvider();

void setupValues(std::vector<std::string> const& identifiers);
void setupRuntimeValue(std::string const& identifier);

inline bool hasValue(std::string_view identifier) const {
std::string s{identifier};
Expand All @@ -113,25 +114,38 @@ class MultiValueProvider

bool hasAllValues() const;


template <typename T = AsmValue>
inline void setValue(std::string_view key, std::optional<T> const& val)
template <typename T>
inline void setValue(std::string_view key, std::optional<T> const& opt_val)
{
// NOTE: prevent (accidental) nested std::optional's (as good as possible)
// TODO: std::optional is a class template (requires our own Optional implementation)
static_assert(false == std::is_same_v<T, std::optional<T>>);

// TODO: std::variant is a class template (requires our own Variant implementation for RTTI)
static_assert(false == std::is_same_v<T, AsmValue>);

std::string s{key};
if (!vals.contains(s)) {
throw std::runtime_error(fmt::format("{} does not register value identifier '{}'", __owner_classname__, key));
}
if (val.has_value()) {
vals[s] = val.value();
if (opt_val.has_value()) {
vals[s] = opt_val.value();
} else if (vals.contains(s)) {
LOGD(fmt::format("Invalidating value {}", key));
vals[s].reset();
}
}

template <typename T = AsmValue>
template <typename T>
inline T getValue(std::string_view key)
{
// NOTE: prevent (accidental) nested std::optional's (as good as possible)
// TODO: std::optional is a class template (requires our own Optional implementation)
static_assert(false == std::is_same_v<T, std::optional<T>>);

// TODO: std::variant is a class template (requires our own Variant implementation for RTTI)
static_assert(false == std::is_same_v<T, AsmValue>);

std::string s{key};
auto const& val = vals[s];
if (val.has_value()) {
Expand Down
40 changes: 35 additions & 5 deletions src/valueprovidertest.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#include "doctest.h"
#include "defines.h"

#ifdef USE_BASS_VALUEPROVIDER

#include "test_utils.h"
#include "doctest.h"
//#include "test_utils.h"
#include "valueprovider.cpp" // FIXME: find better way


Expand All @@ -12,6 +10,7 @@ using namespace std::string_literals;
TEST_CASE("multivalueprovider.base")
{
MultiValueProvider mvp("TestMultiValueProvider"s);

mvp.setupValues({
"valueprovider.example.value_1"s,
"valueprovider.example.value_2"s,
Expand All @@ -23,12 +22,43 @@ TEST_CASE("multivalueprovider.base")
TEST_CASE("multivalueprovider.fails_with_unregistered_value")
{
MultiValueProvider mvp("TestMultiValueProvider"s);

mvp.setupValues({
"valueprovider.example.value_1"s,
"valueprovider.example.value_2"s,
});

REQUIRE_THROWS(mvp.setValue("nope"s, {"i am an unregistered value"}));
REQUIRE_THROWS(
mvp.setValue<std::string>("nope"s, "i am an unregistered value"s)
);
}

TEST_CASE("multivalueprovider.insert_runtime_value")
{
MultiValueProvider mvp("TestMultiValueProvider"s);

mvp.setupValues({
"valueprovider.example.value_1"s,
"valueprovider.example.value_2"s,
});

// simulates an "accessed/undefined" label during parsing
std::string test_symbol_0{"symbol_0"};
mvp.setupRuntimeValue(test_symbol_0); // None

mvp.setValue<int32_t>(test_symbol_0, {}); // still None
REQUIRE_FALSE(mvp.hasValue(test_symbol_0));
REQUIRE_THROWS(mvp.getValue<int32_t>(test_symbol_0));

mvp.setValue<int32_t>(test_symbol_0, 42); // 42 (first assignement)
REQUIRE(mvp.hasValue(test_symbol_0));
REQUIRE_EQ(mvp.getValue<int32_t>(test_symbol_0), 42);

// NOTE: currently re-assigning is allowed to ease transition
// TODO: fail (meaning: "Symbol::finished == true")
int32_t fourty_three = 43;
mvp.setValue(test_symbol_0, std::optional{fourty_three}); // outputs "value runtime.value_0 changed 42 -> 43"
REQUIRE_EQ(mvp.getValue<int32_t>(test_symbol_0), 43);
}

#endif

0 comments on commit 2c24463

Please sign in to comment.