From 5138b51c8af6c85652e8d367c47bba247f3d3073 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Mon, 4 Nov 2019 18:26:40 +0100
Subject: [PATCH] Add tests for FunctionTable/FunctionDescriptor

---
 .../ASTNodeFunctionExpressionBuilder.cpp      |  4 +-
 src/language/FunctionTable.hpp                |  6 +-
 tests/CMakeLists.txt                          |  1 +
 tests/test_FunctionTable.cpp                  | 92 +++++++++++++++++++
 4 files changed, 98 insertions(+), 5 deletions(-)
 create mode 100644 tests/test_FunctionTable.cpp

diff --git a/src/language/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ASTNodeFunctionExpressionBuilder.cpp
index 4a7e09528..90c7559a9 100644
--- a/src/language/ASTNodeFunctionExpressionBuilder.cpp
+++ b/src/language/ASTNodeFunctionExpressionBuilder.cpp
@@ -80,8 +80,8 @@ ASTNodeFunctionExpressionBuilder::_buildArgumentProcessors(FunctionDescriptor& f
                                                            ASTNode& node,
                                                            FunctionProcessor& function_processor)
 {
-  ASTNode& definition_node     = function_descriptor.definitionNode();
-  ASTNode& parameter_variables = *definition_node.children[0];
+  const ASTNode& definition_node = function_descriptor.definitionNode();
+  ASTNode& parameter_variables   = *definition_node.children[0];
 
   ASTNode& argument_nodes = *node.children[1];
 
diff --git a/src/language/FunctionTable.hpp b/src/language/FunctionTable.hpp
index 682a87c4c..451e95aeb 100644
--- a/src/language/FunctionTable.hpp
+++ b/src/language/FunctionTable.hpp
@@ -19,16 +19,16 @@ class FunctionDescriptor
 
  public:
   auto&
-  domainMappingNode()
+  domainMappingNode() const
   {
     Assert(m_domain_mapping_node, "undefined domain mapping node");
     return *m_domain_mapping_node;
   }
 
   auto&
-  definitionNode()
+  definitionNode() const
   {
-    Assert(m_domain_mapping_node, "undefined expression node");
+    Assert(m_definition_node, "undefined expression node");
     return *m_definition_node;
   }
 
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 8d210ede7..7f8cd3eb9 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -47,6 +47,7 @@ add_executable (unit_tests
   test_ExecUntilBreakOrContinue.cpp
   test_FakeProcessor.cpp
   test_ForProcessor.cpp
+  test_FunctionTable.cpp
   test_IfProcessor.cpp
   test_IncDecExpressionProcessor.cpp
   test_INodeProcessor.cpp
diff --git a/tests/test_FunctionTable.cpp b/tests/test_FunctionTable.cpp
new file mode 100644
index 000000000..7a28f1a56
--- /dev/null
+++ b/tests/test_FunctionTable.cpp
@@ -0,0 +1,92 @@
+#include <catch2/catch.hpp>
+
+#include <FunctionTable.hpp>
+
+TEST_CASE("FunctionTable", "[language]")
+{
+  rang::setControlMode(rang::control::Off);
+
+  SECTION("FunctionDescriptor")
+  {
+    std::unique_ptr domain_mapping_node = std::make_unique<ASTNode>();
+    domain_mapping_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+
+    std::unique_ptr definition_node = std::make_unique<ASTNode>();
+    definition_node->m_data_type    = ASTNodeDataType::double_t;
+    FunctionDescriptor f{std::move(domain_mapping_node), std::move(definition_node)};
+
+    REQUIRE(f.domainMappingNode().m_data_type == ASTNodeDataType::unsigned_int_t);
+    REQUIRE(f.definitionNode().m_data_type == ASTNodeDataType::double_t);
+
+    REQUIRE(domain_mapping_node == nullptr);
+    REQUIRE(definition_node == nullptr);
+  }
+
+#ifndef NDEBUG
+  SECTION("uninitialized FunctionDescriptor")
+  {
+    std::unique_ptr domain_mapping_node = std::make_unique<ASTNode>();
+    domain_mapping_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+
+    std::unique_ptr definition_node = std::make_unique<ASTNode>();
+    definition_node->m_data_type    = ASTNodeDataType::double_t;
+
+    SECTION("nothing initialized")
+    {
+      FunctionDescriptor f{nullptr, nullptr};
+      REQUIRE_THROWS_AS(f.domainMappingNode(), AssertError);
+      REQUIRE_THROWS_AS(f.definitionNode(), AssertError);
+    }
+
+    SECTION("domain mapping uninitialized")
+    {
+      FunctionDescriptor f{nullptr, std::move(definition_node)};
+      REQUIRE_THROWS_AS(f.domainMappingNode(), AssertError);
+      REQUIRE(f.definitionNode().m_data_type == ASTNodeDataType::double_t);
+      REQUIRE(definition_node == nullptr);
+    }
+
+    SECTION("definition node uninitialized")
+    {
+      FunctionDescriptor f{std::move(domain_mapping_node), nullptr};
+      REQUIRE_THROWS_AS(f.definitionNode(), AssertError);
+      REQUIRE(f.domainMappingNode().m_data_type == ASTNodeDataType::unsigned_int_t);
+      REQUIRE(domain_mapping_node == nullptr);
+    }
+  }
+#endif   // NDEBUG
+
+  FunctionTable table;
+
+  REQUIRE(table.size() == 0);
+
+  std::unique_ptr domain_mapping_node = std::make_unique<ASTNode>();
+  domain_mapping_node->m_data_type    = ASTNodeDataType::unsigned_int_t;
+
+  std::unique_ptr definition_node = std::make_unique<ASTNode>();
+  definition_node->m_data_type    = ASTNodeDataType::double_t;
+
+  size_t function_id = table.add(FunctionDescriptor{std::move(domain_mapping_node), std::move(definition_node)});
+
+  REQUIRE(domain_mapping_node == nullptr);
+  REQUIRE(definition_node == nullptr);
+
+  REQUIRE(function_id == 0);
+  REQUIRE(table.size() == 1);
+
+  const auto& const_table = table;
+  REQUIRE(const_table.size() == 1);
+
+  auto& f = table[function_id];
+  REQUIRE(f.domainMappingNode().m_data_type == ASTNodeDataType::unsigned_int_t);
+  REQUIRE(f.definitionNode().m_data_type == ASTNodeDataType::double_t);
+
+  const auto& const_f = const_table[function_id];
+  REQUIRE(const_f.domainMappingNode().m_data_type == ASTNodeDataType::unsigned_int_t);
+  REQUIRE(const_f.definitionNode().m_data_type == ASTNodeDataType::double_t);
+
+#ifndef NDEBUG
+  REQUIRE_THROWS_AS(table[table.size()], AssertError);
+  REQUIRE_THROWS_AS(const_table[const_table.size()], AssertError);
+#endif   // NDEBUG
+}
-- 
GitLab