summaryrefslogtreecommitdiff
path: root/compiler/nnc/unittests/acl_backend/DOMToText.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/nnc/unittests/acl_backend/DOMToText.cpp')
-rw-r--r--compiler/nnc/unittests/acl_backend/DOMToText.cpp497
1 files changed, 497 insertions, 0 deletions
diff --git a/compiler/nnc/unittests/acl_backend/DOMToText.cpp b/compiler/nnc/unittests/acl_backend/DOMToText.cpp
new file mode 100644
index 000000000..be0e6713c
--- /dev/null
+++ b/compiler/nnc/unittests/acl_backend/DOMToText.cpp
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This is test set of text generator from DOM entities
+ * ArtifactEntity, ArtifactNamed, ArtifactExpr and ArtifactClassMember
+ * are not tested since they are abstract classes
+ */
+
+#include <sstream>
+#include <tuple>
+
+#include "ArtifactModel.h"
+#include "ArtifactGeneratorCppCode.h"
+#include "ArtifactGeneratorCppDecl.h"
+
+#include "AclArtifactUtilities.generated.h"
+
+#include "gtest/gtest.h"
+
+using namespace std;
+using namespace nnc;
+
+using AF = ArtifactFactory;
+
+TEST(acl_backend_dom_to_text, ArtifactLiteral)
+{
+ stringstream code_out;
+ stringstream decl_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ ArtifactGeneratorCppDecl decl_gen(decl_out);
+ const char *lit_data = "hello_world";
+ shared_ptr<ArtifactLiteral> lit = AF::lit(lit_data);
+ lit->accept(&code_gen);
+ lit->accept(&decl_gen);
+ ASSERT_EQ(code_out.str(), lit_data);
+ ASSERT_EQ(decl_out.str(), lit_data);
+}
+
+TEST(acl_backend_dom_to_text, ArtifactId)
+{
+ stringstream code_out;
+ stringstream decl_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ ArtifactGeneratorCppDecl decl_gen(decl_out);
+ const char *id_data = "some_id";
+ shared_ptr<ArtifactId> id = AF::id(id_data);
+ id->accept(&code_gen);
+ id->accept(&decl_gen);
+ ASSERT_EQ(code_out.str(), id_data);
+ ASSERT_EQ(decl_out.str(), id_data);
+}
+
+TEST(acl_backend_dom_to_text, ArtifactRef)
+{
+ stringstream code_out;
+ stringstream decl_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ ArtifactGeneratorCppDecl decl_gen(decl_out);
+ const char *id_data = "some_id";
+ shared_ptr<ArtifactId> id = AF::id(id_data);
+ shared_ptr<ArtifactRef> ref = AF::ref(id);
+ ref->accept(&code_gen);
+ ref->accept(&decl_gen);
+ string ref_data = string("&") + id_data;
+ ASSERT_EQ(code_out.str(), ref_data);
+ ASSERT_EQ(decl_out.str(), ref_data);
+}
+
+TEST(acl_backend_dom_to_text, ArtifactDeref)
+{
+ stringstream code_out;
+ stringstream decl_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ ArtifactGeneratorCppDecl decl_gen(decl_out);
+ const char *id_data = "some_id";
+ shared_ptr<ArtifactId> id = AF::id(id_data);
+ shared_ptr<ArtifactDeref> deref = AF::deref(id);
+ deref->accept(&code_gen);
+ deref->accept(&decl_gen);
+ string ref_data = string("*") + id_data;
+ ASSERT_EQ(code_out.str(), ref_data);
+ ASSERT_EQ(decl_out.str(), ref_data);
+}
+
+static void checkCall(ArtifactCallType type, const char *call_name,
+ const list<shared_ptr<ArtifactExpr>> &args, shared_ptr<ArtifactExpr> obj,
+ const char *ref_data)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ shared_ptr<ArtifactFunctionCall> call = AF::call(call_name, args, obj, type);
+ call->accept(&code_gen);
+ ASSERT_EQ(code_out.str(), ref_data);
+}
+
+TEST(acl_backend_dom_to_text, ArtifactFunctionCall)
+{
+ const char *lit_data = "123";
+ const char *id_data = "some_id";
+ shared_ptr<ArtifactExpr> id = AF::id(id_data);
+ shared_ptr<ArtifactExpr> lit = AF::lit(lit_data);
+ const list<shared_ptr<ArtifactExpr>> args{id, lit};
+
+ shared_ptr<ArtifactId> obj = AF::id("obj");
+
+ using TestCase = tuple<ArtifactCallType, shared_ptr<ArtifactExpr>, const char *>;
+ TestCase test_cases[] = {TestCase{ArtifactCallType::scope, nullptr, "foo(some_id, 123)"},
+ TestCase{ArtifactCallType::obj, obj, "obj.foo(some_id, 123)"},
+ TestCase{ArtifactCallType::ref, obj, "obj->foo(some_id, 123)"},
+ TestCase{ArtifactCallType::scope, obj, "obj::foo(some_id, 123)"}};
+
+ for (const auto &test : test_cases)
+ {
+ ArtifactCallType call_type = get<0>(test);
+ shared_ptr<ArtifactExpr> obj = get<1>(test);
+ const char *ref_output = get<2>(test);
+ checkCall(call_type, "foo", args, obj, ref_output);
+ }
+}
+
+static void checkUnaryExpression(ArtifactUnOp op, shared_ptr<ArtifactExpr> var,
+ const char *ref_data)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+
+ shared_ptr<ArtifactUnaryExpr> expr = AF::un(op, var);
+ expr->accept(&code_gen);
+ ASSERT_EQ(code_out.str(), ref_data);
+}
+
+TEST(acl_backend_dom_to_text, ArtifactUnaryExpr)
+{
+ const char *var_name = "id";
+ shared_ptr<ArtifactId> var = AF::id(var_name);
+ pair<ArtifactUnOp, const char *> test_cases[] = {
+ {ArtifactUnOp::preIncr, "++id"}, {ArtifactUnOp::preDecr, "--id"},
+ {ArtifactUnOp::heapNew, "new id"}, {ArtifactUnOp::heapFree, "delete id"},
+ {ArtifactUnOp::postIncr, "id++"}, {ArtifactUnOp::postDecr, "id--"}};
+
+ for (auto test : test_cases)
+ {
+ auto op_type = test.first;
+ auto ref_output = test.second;
+ checkUnaryExpression(op_type, var, ref_output);
+ }
+}
+
+static void checkBinaryExpression(ArtifactBinOp op, shared_ptr<ArtifactExpr> op1,
+ shared_ptr<ArtifactExpr> op2, const char *ref_data)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+
+ shared_ptr<ArtifactBinaryExpr> expr = AF::bin(op, op1, op2);
+ expr->accept(&code_gen);
+ ASSERT_EQ(code_out.str(), ref_data);
+}
+
+TEST(acl_backend_dom_to_text, ArtifactBinaryExpr)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ const char *op1_name = "a";
+ const char *op2_name = "b";
+ shared_ptr<ArtifactId> op1 = AF::id(op1_name);
+ shared_ptr<ArtifactId> op2 = AF::id(op2_name);
+
+ pair<ArtifactBinOp, const char *> test_cases[] = {
+ {ArtifactBinOp::eq, "a == b"}, {ArtifactBinOp::notEq, "a != b"},
+ {ArtifactBinOp::less, "a < b"}, {ArtifactBinOp::lessOrEq, "a <= b"},
+ {ArtifactBinOp::great, "a > b"}, {ArtifactBinOp::greatOrEq, "a >= b"},
+ {ArtifactBinOp::assign, "a = b"}, {ArtifactBinOp::plus, "a + b"},
+ {ArtifactBinOp::minus, "a - b"}, {ArtifactBinOp::mult, "a * b"},
+ {ArtifactBinOp::div, "a / b"}, {ArtifactBinOp::plusAssign, "a += b"},
+ {ArtifactBinOp::minusAssign, "a -= b"}, {ArtifactBinOp::multAssign, "a *= b"},
+ {ArtifactBinOp::divAssign, "a /= b"}};
+
+ for (auto test : test_cases)
+ {
+ auto op_type = test.first;
+ auto ref_output = test.second;
+ checkBinaryExpression(op_type, op1, op2, ref_output);
+ }
+}
+
+TEST(acl_backend_dom_to_text, ArtifactIndex)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ const char *arr_name = "a";
+ const char *idx_name = "b";
+ shared_ptr<ArtifactId> arr = AF::id(arr_name);
+ shared_ptr<ArtifactId> idx = AF::id(idx_name);
+ shared_ptr<ArtifactIndex> indexing = AF::ind(arr, idx);
+ indexing->accept(&code_gen);
+ ASSERT_EQ(code_out.str(), "a[b]");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactRet)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ const char *result_name = "a";
+ shared_ptr<ArtifactId> result = AF::id(result_name);
+ ArtifactRet ret(result);
+ ret.accept(&code_gen);
+ ASSERT_EQ(code_out.str(), "return a");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactBreak)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ ArtifactBreak brk;
+ brk.accept(&code_gen);
+ ASSERT_EQ(code_out.str(), "break");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactCont)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ ArtifactCont cont;
+ cont.accept(&code_gen);
+ ASSERT_EQ(code_out.str(), "continue");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactVariable)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ const char *var_type = "int";
+ const char *var_name = "data";
+ shared_ptr<ArtifactLiteral> dim1 = AF::lit("2");
+ shared_ptr<ArtifactLiteral> dim2 = AF::lit("3");
+ list<shared_ptr<ArtifactExpr>> dims{dim1, dim2};
+ list<shared_ptr<ArtifactExpr>> initializers{AF::lit("123")};
+ shared_ptr<ArtifactVariable> var_decl = AF::var(var_type, var_name, dims, initializers);
+ var_decl->accept(&code_gen);
+ // TODO generate initializers in braces
+ ASSERT_EQ(code_out.str(), "int data[2][3](123)");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactBlock)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ const char *var_name = "var";
+ const char *lit_val = "123";
+
+ shared_ptr<ArtifactExpr> id = AF::id(var_name);
+ shared_ptr<ArtifactExpr> lit = AF::lit(lit_val);
+ const list<shared_ptr<ArtifactExpr>> args{id, lit};
+
+ shared_ptr<ArtifactFunctionCall> call = AF::call("foo", args);
+
+ ArtifactBlock block;
+
+ block.addStatement(call);
+
+ block.accept(&code_gen);
+ ASSERT_EQ(code_out.str(), " {\n foo(var, 123);\n}\n");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactForLoop)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ const char *var_name = "i";
+ const char *var_type = "int";
+
+ shared_ptr<ArtifactVariable> iter = AF::var(var_type, var_name, {}, {AF::lit("0")});
+ shared_ptr<ArtifactExpr> step =
+ AF::bin(ArtifactBinOp::plusAssign, AF::id(var_name), AF::lit("1"));
+ shared_ptr<ArtifactExpr> cond =
+ AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
+
+ shared_ptr<ArtifactBinaryExpr> expr =
+ AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
+
+ ArtifactForLoop loop(iter, cond, step);
+
+ loop.getBlock()->addStatement(expr);
+
+ loop.accept(&code_gen);
+ ASSERT_EQ(code_out.str(), "for(int i(0); i <= 123; i += 1) {\n hello += world;\n}\n");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactIf)
+{
+ stringstream code_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ const char *var_name = "i";
+
+ shared_ptr<ArtifactExpr> cond =
+ AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
+
+ shared_ptr<ArtifactBinaryExpr> expr =
+ AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
+
+ ArtifactIf if_stmt(cond);
+
+ if_stmt.getBlock()->addStatement(expr);
+
+ if_stmt.accept(&code_gen);
+ ASSERT_EQ(code_out.str(), "if(i <= 123) {\n hello += world;\n}\n");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactFunction)
+{
+ stringstream code_out;
+ stringstream decl_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ ArtifactGeneratorCppDecl decl_gen(decl_out);
+ const char *ret_type = "int";
+ const char *func_name = "foo";
+ shared_ptr<ArtifactVariable> arg1 = AF::var("int", "a");
+ shared_ptr<ArtifactVariable> arg2 = AF::var("bool", "b");
+ list<shared_ptr<ArtifactVariable>> args{arg1, arg2};
+
+ // test public class variable
+ ArtifactFunction func_decl(ret_type, func_name, args);
+
+ func_decl.accept(&code_gen);
+ ASSERT_EQ(code_out.str(), "");
+ func_decl.accept(&decl_gen);
+
+ ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactClassVariable)
+{
+ stringstream code_out;
+ stringstream decl_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ ArtifactGeneratorCppDecl decl_gen(decl_out);
+
+ const char *var_type = "int";
+ const char *var_name = "data";
+
+ ArtifactClass cls("Class");
+
+ shared_ptr<ArtifactLiteral> dim1 = AF::lit("2");
+ shared_ptr<ArtifactLiteral> dim2 = AF::lit("3");
+ list<shared_ptr<ArtifactExpr>> dims{dim1, dim2};
+ list<shared_ptr<ArtifactExpr>> list_of_initializer{AF::lit("123")};
+ ArtifactClassVariable var_decl(&cls, var_type, var_name, dims, list_of_initializer);
+
+ var_decl.accept(&code_gen);
+ ASSERT_EQ(code_out.str(), "data(123)");
+ var_decl.accept(&decl_gen);
+ // fixme dimensions are not taken into account, remove ';'
+ ASSERT_EQ(decl_out.str(), "int data;\n");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactClassFunction)
+{
+ stringstream code_out;
+ stringstream decl_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ ArtifactGeneratorCppDecl decl_gen(decl_out);
+ const char *ret_type = "int";
+ const char *func_name = "foo";
+ shared_ptr<ArtifactVariable> arg1 = AF::var("int", "a");
+ shared_ptr<ArtifactVariable> arg2 = AF::var("bool", "b");
+ list<shared_ptr<ArtifactVariable>> args{arg1, arg2};
+
+ ArtifactClass cls("Class");
+
+ // test public class variable
+ shared_ptr<ArtifactClassFunction> cls_func_decl = cls.func(true, ret_type, func_name, args);
+
+ cls_func_decl->accept(&code_gen);
+ // FIXME do not print new line in this visitor
+ ASSERT_EQ(code_out.str(), "int Class::foo(int a, bool b) {\n}\n\n");
+ cls_func_decl->accept(&decl_gen);
+
+ ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);\n");
+
+ decl_out.str("");
+ code_out.str("");
+
+ // test private class variable
+ cls_func_decl = cls.func(false, ret_type, func_name, args);
+
+ cls_func_decl->accept(&code_gen);
+ // FIXME do not print new line in this visitor
+ ASSERT_EQ(code_out.str(), "int Class::foo(int a, bool b) {\n}\n\n");
+ cls_func_decl->accept(&decl_gen);
+
+ ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);\n");
+}
+
+static shared_ptr<ArtifactClassVariable> createClsVariable(ArtifactClass &cls, const char *var_name,
+ bool is_public)
+{
+ const char *var_type = "int";
+ shared_ptr<ArtifactLiteral> dim1 = AF::lit("2");
+ shared_ptr<ArtifactLiteral> dim2 = AF::lit("3");
+ list<shared_ptr<ArtifactExpr>> dims{dim1, dim2};
+ list<shared_ptr<ArtifactExpr>> initializers{AF::lit("123")};
+ shared_ptr<ArtifactClassVariable> var_decl =
+ cls.var(is_public, var_type, var_name, dims, initializers);
+ return var_decl;
+}
+
+static shared_ptr<ArtifactClassFunction> createClsFunction(ArtifactClass &cls,
+ const char *func_name, bool is_public)
+{
+ const char *var_type = "int";
+ const char *func_type = "void";
+ shared_ptr<ArtifactVariable> var1 = AF::var(var_type, "a");
+ shared_ptr<ArtifactVariable> var2 = AF::var(var_type, "b");
+ list<shared_ptr<ArtifactVariable>> args{var1, var2};
+ shared_ptr<ArtifactClassFunction> func_decl = cls.func(is_public, func_type, func_name, args);
+ return func_decl;
+}
+
+TEST(acl_backend_dom_to_text, ArtifactClass)
+{
+ stringstream code_out;
+ stringstream decl_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ ArtifactGeneratorCppDecl decl_gen(decl_out);
+
+ ArtifactClass cls("Class");
+
+ createClsFunction(cls, "public_foo", true);
+ createClsFunction(cls, "private_bar", false);
+
+ createClsVariable(cls, "visible", true);
+ createClsVariable(cls, "invisible", false);
+
+ // Test cpp file generation
+ cls.accept(&code_gen);
+ ASSERT_EQ(code_out.str(), "Class::Class() : invisible(123) {\n}\n\n"
+ "void Class::public_foo(int a, int b) {\n}\n\n"
+ "void Class::private_bar(int a, int b) {\n}\n\n");
+
+ // Test header file generation
+ cls.accept(&decl_gen);
+
+ ASSERT_EQ(decl_out.str(), "class Class {\npublic:\n Class();\n"
+ " void public_foo(int a, int b);"
+ "\n\nprivate:\n void private_bar(int a, int b);\n\n"
+ " int invisible;\n};\n");
+}
+
+TEST(acl_backend_dom_to_text, ArtifactModule)
+{
+ stringstream code_out;
+ stringstream decl_out;
+ ArtifactGeneratorCppCode code_gen(code_out);
+ ArtifactGeneratorCppDecl decl_gen(decl_out);
+
+ ArtifactModule m("module");
+
+ m.addHeaderInclude("foo.h");
+ m.addHeaderSysInclude("vector");
+ m.addSourceInclude("bar.h");
+ m.addSourceSysInclude("list");
+
+ shared_ptr<ArtifactClass> cls = m.createClass("Class");
+
+ // test cpp file generation
+ // We use snippet code to encode some common functions
+ // This snippet is wrapped in prefix and postfix code
+ const char *code_prefix = "#include \"module.h\"\n\n#include <list>\n\n#include \"bar.h\"\n\n";
+ const char *code_suffix = "\nClass::Class() {\n}\n\n";
+
+ string ref_data = string(code_prefix) +
+ string(AclArtifactUtilities, sizeof(AclArtifactUtilities)) + code_suffix;
+ m.accept(&code_gen);
+ ASSERT_EQ(code_out.str(), ref_data);
+
+ // test header code generation
+ const char *ref_decl_data = "#include <vector>\n\n#include \"foo.h\"\n\nclass Class {\npublic:\n "
+ " Class();\n\nprivate:\n};\n";
+ m.accept(&decl_gen);
+
+ ASSERT_EQ(decl_out.str(), ref_decl_data);
+}