diff options
Diffstat (limited to 'compiler/nnc/unittests/acl_backend/DOMToText.cpp')
-rw-r--r-- | compiler/nnc/unittests/acl_backend/DOMToText.cpp | 497 |
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); +} |