Skip to content

Commit

Permalink
feat: Add ValidationContext
Browse files Browse the repository at this point in the history
Part of #25

It will be used to store context of ValidationVisitor easily. Instead of
creating a new member each time, just store it directly in the context.

The stack/unstack allow to have a different context if we need it
  • Loading branch information
Gashmob committed Aug 28, 2024
1 parent 9bec4f7 commit f4a9511
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 0 deletions.
29 changes: 29 additions & 0 deletions include/filc/validation/ValidationVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,37 @@
#define FILC_VALIDATIONVISITOR_H

#include "filc/grammar/Visitor.h"
#include <memory>
#include <map>
#include <any>
#include <string>
#include <stdexcept>

namespace filc {
class ValidationContext final {
public:
explicit ValidationContext(ValidationContext* parent = nullptr);

[[nodiscard]] auto stack() -> ValidationContext*;

[[nodiscard]] auto unstack() const -> ValidationContext*;

auto set(const std::string &key, const std::any &value) -> void;

template<typename T>
auto get(const std::string &key) const -> T {
if (_values.find(key) == _values.end()) {
throw std::logic_error("There is not value for key: " + key);
}

return std::any_cast<T>(_values.at(key));
}

private:
ValidationContext* _parent;
std::map<std::string, std::any> _values;
};

class ValidationVisitor final : public Visitor {
public:
auto visitProgram(Program *program) -> void override;
Expand Down
34 changes: 34 additions & 0 deletions src/validation/ValidationContext.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* MIT License
*
* Copyright (c) 2024-Present Kevin Traini
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "filc/validation/ValidationVisitor.h"

using namespace filc;

ValidationContext::ValidationContext(ValidationContext *parent) : _parent(parent) {}

auto ValidationContext::stack() -> ValidationContext * { return new ValidationContext(this); }

auto ValidationContext::unstack() const -> ValidationContext * { return _parent; }

auto ValidationContext::set(const std::string &key, const std::any &value) -> void { _values[key] = value; }
86 changes: 86 additions & 0 deletions tests/unit/validation/ValidationContextTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* MIT License
*
* Copyright (c) 2024-Present Kevin Traini
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <filc/validation/ValidationVisitor.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

using namespace ::testing;

TEST(ValidationContext, stack_unstack) {
filc::ValidationContext context;
auto new_context = context.stack();
ASSERT_NE(&context, new_context);
ASSERT_EQ(&context, new_context->unstack());
}

TEST(ValidationContext, get_non_existing) {
filc::ValidationContext context;
ASSERT_THROW(context.get<int>("non-existing"), std::logic_error);
}

TEST(ValidationContext, get_set_scalar) {
filc::ValidationContext context;
context.set("int_value", 2);
ASSERT_EQ(2, context.get<int>("int_value"));
}

TEST(ValidationContext, get_set_string) {
filc::ValidationContext context;
context.set("string_value", std::string("Hello"));
ASSERT_STREQ("Hello", context.get<std::string>("string_value").c_str());
}

typedef struct {
int _a;
std::string _b;
char _c[5];
} SomeStructure;

TEST(ValidationContext, get_set_structure) {
filc::ValidationContext context;
SomeStructure value = {2, "Hello World", {'a', 'b', 'c', 'd', 'e'}};
context.set("struct_value", value);
auto found = context.get<SomeStructure>("struct_value");
ASSERT_EQ(2, found._a);
ASSERT_STREQ("Hello World", found._b.c_str());
ASSERT_THAT(found._c, ElementsAre('a', 'b', 'c', 'd', 'e'));
}

class SomeClass {
public:
SomeClass() : _a(12), _b("foo") {}

[[nodiscard]] auto equals(const SomeClass &other) const -> bool { return _a == other._a && _b == other._b; }

private:
int _a;
std::string _b;
};

TEST(ValidationContext, get_set_object) {
filc::ValidationContext context;
SomeClass value;
context.set("object_value", value);
ASSERT_TRUE(value.equals(context.get<SomeClass>("object_value")));
}

0 comments on commit f4a9511

Please sign in to comment.