From 44e8452664bc97c81bee88c57859c4667e2c100f Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Mon, 2 Sep 2019 18:25:20 +0200
Subject: [PATCH] Add tests for AffectationProcessor

Also made few clean-up
---
 .../node_processor/AffectationProcessor.hpp   |  15 +-
 tests/CMakeLists.txt                          |   1 +
 tests/test_AffectationProcessor.cpp           | 232 ++++++++++++++++++
 3 files changed, 235 insertions(+), 13 deletions(-)
 create mode 100644 tests/test_AffectationProcessor.cpp

diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp
index 6ed12a1d3..fbede35c8 100644
--- a/src/language/node_processor/AffectationProcessor.hpp
+++ b/src/language/node_processor/AffectationProcessor.hpp
@@ -10,17 +10,6 @@
 template <typename Op>
 struct AffOp;
 
-template <>
-struct AffOp<language::eq_op>
-{
-  template <typename A, typename B>
-  PUGS_INLINE void
-  eval(A& a, const B& b)
-  {
-    a = b;
-  }
-};
-
 template <>
 struct AffOp<language::multiplyeq_op>
 {
@@ -114,9 +103,9 @@ class AffectationProcessor final : public INodeProcessor
       Assert(found);
       p_value = &i_symbol->second.value();
     } else {
-      throw parse_error("invalid operands to binary expression", std::vector{m_node.begin()});
+      throw parse_error("invalid operands to affectation expression", std::vector{m_node.begin()});
     }
   }
 };
 
-#endif // AFFECTATION_PROCESSOR_HPP
+#endif   // AFFECTATION_PROCESSOR_HPP
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index a54bd439c..469eeabbe 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -3,6 +3,7 @@ set(EXECUTABLE_OUTPUT_PATH ${PUGS_BINARY_DIR})
 
 add_executable (unit_tests
   test_main.cpp
+  test_AffectationProcessor.cpp
   test_Array.cpp
   test_ArrayUtils.cpp
   test_ASTBuilder.cpp
diff --git a/tests/test_AffectationProcessor.cpp b/tests/test_AffectationProcessor.cpp
new file mode 100644
index 000000000..351a3af9d
--- /dev/null
+++ b/tests/test_AffectationProcessor.cpp
@@ -0,0 +1,232 @@
+#include <catch2/catch.hpp>
+
+#include <ASTNodeValueBuilder.hpp>
+
+#include <ASTBuilder.hpp>
+#include <ASTNodeDataTypeBuilder.hpp>
+
+#include <ASTNodeDeclarationCleaner.hpp>
+#include <ASTNodeDeclarationToAffectationConverter.hpp>
+
+#include <ASTNodeExpressionBuilder.hpp>
+
+#include <ASTNodeAffectationExpressionBuilder.hpp>
+
+#include <ASTSymbolTableBuilder.hpp>
+
+#include <ASTPrinter.hpp>
+
+#include <Demangle.hpp>
+
+#include <PEGGrammar.hpp>
+
+#include <sstream>
+
+#define CHECK_AFFECTATION_RESULT(data, variable_name, expected_value)       \
+  {                                                                         \
+    string_input input{data, "test.pgs"};                                   \
+    auto ast = ASTBuilder::build(input);                                    \
+                                                                            \
+    ASTSymbolTableBuilder{*ast};                                            \
+    ASTNodeDataTypeBuilder{*ast};                                           \
+    ASTNodeValueBuilder{*ast};                                              \
+                                                                            \
+    ASTNodeDeclarationToAffectationConverter{*ast};                         \
+    ASTNodeDeclarationCleaner{*ast};                                        \
+                                                                            \
+    ASTNodeExpressionBuilder{*ast};                                         \
+    ExecUntilBreakOrContinue exec_policy;                                   \
+    ast->execute(exec_policy);                                              \
+                                                                            \
+    auto symbol_table = ast->m_symbol_table;                                \
+                                                                            \
+    using namespace TAO_PEGTL_NAMESPACE;                                    \
+    position use_position{internal::iterator{"fixture"}, "fixture"};        \
+    use_position.byte    = 10000;                                           \
+    auto [symbol, found] = symbol_table->find(variable_name, use_position); \
+                                                                            \
+    auto attribute = symbol->second;                                        \
+    auto value     = std::get<decltype(expected_value)>(attribute.value()); \
+                                                                            \
+    REQUIRE(value == expected_value);                                       \
+  }
+
+#define CHECK_AFFECTATION_THROWS(data)                                                       \
+  {                                                                                          \
+    string_input input{data, "test.pgs"};                                                    \
+    auto ast = ASTBuilder::build(input);                                                     \
+                                                                                             \
+    ASTSymbolTableBuilder{*ast};                                                             \
+    ASTNodeDataTypeBuilder{*ast};                                                            \
+    ASTNodeValueBuilder{*ast};                                                               \
+                                                                                             \
+    ASTNodeDeclarationToAffectationConverter{*ast};                                          \
+    ASTNodeDeclarationCleaner{*ast};                                                         \
+                                                                                             \
+    REQUIRE_THROWS(ASTNodeExpressionBuilder{*ast},                                           \
+                   Catch::Matchers::Contains("invalid operands to affectation expression")); \
+  }
+
+TEST_CASE("ASTAffectationProcessor", "[language]")
+{
+  SECTION("Affectations")
+  {
+    SECTION("B")
+    {
+      CHECK_AFFECTATION_RESULT("B b; b = true;", "b", true);
+      CHECK_AFFECTATION_RESULT("N n = 1; B b; b = n;", "b", true);
+      CHECK_AFFECTATION_RESULT("B b; b = 1;", "b", true);
+      CHECK_AFFECTATION_RESULT("B b; b = 2.3;", "b", true);
+    }
+
+    SECTION("N")
+    {
+      CHECK_AFFECTATION_RESULT("N n = 1;", "n", 1ul);
+      CHECK_AFFECTATION_RESULT("N m = 2; N n = m;", "n", 2ul);
+      CHECK_AFFECTATION_RESULT("N n = true;", "n", 1ul);
+      CHECK_AFFECTATION_RESULT("N n = false;", "n", 0ul);
+      CHECK_AFFECTATION_RESULT("N n = 2.3;", "n", 2ul);
+    }
+
+    SECTION("Z")
+    {
+      CHECK_AFFECTATION_RESULT("Z z = -1;", "z", -1l);
+      CHECK_AFFECTATION_RESULT("Z z = true;", "z", 1l);
+      CHECK_AFFECTATION_RESULT("Z z = false;", "z", 0l);
+      CHECK_AFFECTATION_RESULT("Z z = -2.3;", "z", -2l);
+    }
+
+    SECTION("R")
+    {
+      CHECK_AFFECTATION_RESULT("R r = -1;", "r", -1.);
+      CHECK_AFFECTATION_RESULT("R r = true;", "r", 1.);
+      CHECK_AFFECTATION_RESULT("R r = false;", "r", 0.);
+      CHECK_AFFECTATION_RESULT("R r = -2.3;", "r", -2.3);
+    }
+  }
+
+  SECTION("+=")
+  {
+    SECTION("N")
+    {
+      CHECK_AFFECTATION_RESULT("N n = 1; n += 3;", "n", 4ul);
+      CHECK_AFFECTATION_RESULT("N m = 2; N n = 1; n += m;", "n", 3ul);
+      CHECK_AFFECTATION_RESULT("N n = 1; n += true;", "n", 2ul);
+      CHECK_AFFECTATION_RESULT("N n = 3; n += false;", "n", 3ul);
+      CHECK_AFFECTATION_RESULT("N n = 2; n += 1.1;", "n", 3ul);
+    }
+
+    SECTION("Z")
+    {
+      CHECK_AFFECTATION_RESULT("Z z = 1; z += 3;", "z", 4l);
+      CHECK_AFFECTATION_RESULT("N m = 2; Z z = 1; z += m;", "z", 3l);
+      CHECK_AFFECTATION_RESULT("Z z = 1; z += true;", "z", 2l);
+      CHECK_AFFECTATION_RESULT("Z z = 3; z += false;", "z", 3l);
+      CHECK_AFFECTATION_RESULT("Z z = 2; z += 1.1;", "z", 3l);
+    }
+
+    SECTION("R")
+    {
+      CHECK_AFFECTATION_RESULT("R r = 1.2; r += 2.3;", "r", 3.5);
+      CHECK_AFFECTATION_RESULT("N m = 2; R r = 1.3; r += m;", "r", 3.3);
+      CHECK_AFFECTATION_RESULT("R r = 1.1; r += true;", "r", 2.1);
+      CHECK_AFFECTATION_RESULT("R r = 3.3; r += false;", "r", 3.3);
+      CHECK_AFFECTATION_RESULT("R r = 2; r += 1.1;", "r", 3.1);
+    }
+  }
+
+  SECTION("-=")
+  {
+    SECTION("N")
+    {
+      CHECK_AFFECTATION_RESULT("N n = 3; n -= 2;", "n", 1ul);
+      CHECK_AFFECTATION_RESULT("N m = 2; N n = 4; n -= m;", "n", 2ul);
+      CHECK_AFFECTATION_RESULT("N n = 1; n -= true;", "n", 0ul);
+      CHECK_AFFECTATION_RESULT("N n = 3; n -= false;", "n", 3ul);
+      CHECK_AFFECTATION_RESULT("N n = 2; n -= 1.1;", "n", 0ul);
+    }
+
+    SECTION("Z")
+    {
+      CHECK_AFFECTATION_RESULT("Z z = 1; z -= 3;", "z", -2l);
+      CHECK_AFFECTATION_RESULT("N m = 2; Z z = 1; z -= m;", "z", -1l);
+      CHECK_AFFECTATION_RESULT("Z z = 1; z -= true;", "z", 0l);
+      CHECK_AFFECTATION_RESULT("Z z = 3; z -= false;", "z", 3l);
+      CHECK_AFFECTATION_RESULT("Z z = 2; z -= 2.1;", "z", 0l);
+    }
+
+    SECTION("R")
+    {
+      CHECK_AFFECTATION_RESULT("R r = 1.1; r -= 2;", "r", (1.1 - 2l));
+      CHECK_AFFECTATION_RESULT("N m = 2; R r = 1.3; r -= m;", "r", (1.3 - 2ul));
+      CHECK_AFFECTATION_RESULT("R r = 1.1; r -= true;", "r", (1.1 - true));
+      CHECK_AFFECTATION_RESULT("R r = 3.3; r -= false;", "r", 3.3);
+      CHECK_AFFECTATION_RESULT("R r = 2; r -= 1.1;", "r", (2. - 1.1));
+    }
+  }
+
+  SECTION("*=")
+  {
+    SECTION("N")
+    {
+      CHECK_AFFECTATION_RESULT("N n = 3; n *= 2;", "n", 6ul);
+      CHECK_AFFECTATION_RESULT("N m = 2; N n = 4; n *= m;", "n", 8ul);
+      CHECK_AFFECTATION_RESULT("N n = 1; n *= true;", "n", 1ul);
+      CHECK_AFFECTATION_RESULT("N n = 3; n *= false;", "n", 0ul);
+      CHECK_AFFECTATION_RESULT("N n = 2; n *= 2.51;", "n", 5ul);
+    }
+
+    SECTION("Z")
+    {
+      CHECK_AFFECTATION_RESULT("Z z = 1; z *= 3;", "z", 3l);
+      CHECK_AFFECTATION_RESULT("N m = 2; Z z = -2; z *= m;", "z", -4l);
+      CHECK_AFFECTATION_RESULT("Z z = 1; z *= true;", "z", 1l);
+      CHECK_AFFECTATION_RESULT("Z z = 3; z *= false;", "z", 0l);
+      CHECK_AFFECTATION_RESULT("Z z = 2; z *= -2.51;", "z", -5l);
+    }
+
+    SECTION("R")
+    {
+      CHECK_AFFECTATION_RESULT("R r = 1.1; r *= 2;", "r", (1.1 * 2l));
+      CHECK_AFFECTATION_RESULT("N m = 2; R r = 1.3; r *= m;", "r", (1.3 * 2ul));
+      CHECK_AFFECTATION_RESULT("R r = 1.1; r *= true;", "r", (1.1 * true));
+      CHECK_AFFECTATION_RESULT("R r = 3.3; r *= false;", "r", (3.3 * false));
+      CHECK_AFFECTATION_RESULT("R r = 2; r *= 1.1;", "r", (2. * 1.1));
+    }
+  }
+
+  SECTION("/=")
+  {
+    SECTION("N")
+    {
+      CHECK_AFFECTATION_RESULT("N n = 4; n /= 2;", "n", 2ul);
+      CHECK_AFFECTATION_RESULT("N m = 2; N n = 6; n /= m;", "n", 3ul);
+      CHECK_AFFECTATION_RESULT("N n = 1; n /= true;", "n", 1ul);
+      CHECK_AFFECTATION_RESULT("N n = 2; n /= 2.51;", "n", 0ul);
+    }
+
+    SECTION("Z")
+    {
+      CHECK_AFFECTATION_RESULT("Z z = 7; z /= -3;", "z", -2l);
+      CHECK_AFFECTATION_RESULT("N m = 3; Z z = 6; z /= m;", "z", 2l);
+      CHECK_AFFECTATION_RESULT("Z z = 6; z /= true;", "z", 6l);
+      CHECK_AFFECTATION_RESULT("Z z = 4; z /= -2.;", "z", -2l);
+    }
+
+    SECTION("R")
+    {
+      CHECK_AFFECTATION_RESULT("R r = 1.1; r /= 2;", "r", (1.1 / 2l));
+      CHECK_AFFECTATION_RESULT("N m = 2; R r = 1.3; r /= m;", "r", (1.3 / 2ul));
+      CHECK_AFFECTATION_RESULT("R r = 1.1; r /= true;", "r", (1.1 / true));
+      CHECK_AFFECTATION_RESULT("R r = 2; r /= 1.1;", "r", (2. / 1.1));
+    }
+  }
+
+  SECTION("errors")
+  {
+    CHECK_AFFECTATION_THROWS("B b = true; b += 1;");
+    CHECK_AFFECTATION_THROWS("B b = true; b *= 1;");
+    CHECK_AFFECTATION_THROWS("B b = true; b -= 1;");
+    CHECK_AFFECTATION_THROWS("B b = true; b /= 1;");
+  }
+}
-- 
GitLab