blob: 6c3442426aca19438621369e1c6441550fb450c1 [file] [log] [blame]
Christopher Wileyf600a552015-09-12 14:07:44 -07001/*
2 * Copyright (C) 2015, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <string>
18
19#include <gtest/gtest.h>
20
21#include "ast_cpp.h"
22#include "code_writer.h"
23
24using std::string;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -070025using std::vector;
26using std::unique_ptr;
Christopher Wileyf600a552015-09-12 14:07:44 -070027
28namespace android {
29namespace aidl {
Christopher Wileyf944e792015-09-29 10:00:46 -070030namespace cpp {
Christopher Wileyf600a552015-09-12 14:07:44 -070031namespace {
32
33const char kExpectedHeaderOutput[] =
34R"(#ifndef HEADER_INCLUDE_GUARD_H_
35#define HEADER_INCLUDE_GUARD_H_
36
37#include <string>
38#include <memory>
39
40namespace android {
Casey Dahlin34b86102015-09-16 16:03:06 -070041
Christopher Wileyf600a552015-09-12 14:07:44 -070042namespace test {
43
Casey Dahlin60a49162015-09-17 14:23:10 -070044class TestClass {
Casey Dahlin88924d62015-09-17 16:28:24 -070045public:
Jiyong Parka755dc72018-06-29 13:52:24 +090046 void NormalMethod(int normalarg, float normal2);
47 virtual void SubMethod(int subarg) const;
Casey Dahlin88924d62015-09-17 16:28:24 -070048}; // class TestClass
Casey Dahlin60a49162015-09-17 14:23:10 -070049
50class TestSubClass : public TestClass {
Casey Dahlin88924d62015-09-17 16:28:24 -070051public:
Jiyong Parka755dc72018-06-29 13:52:24 +090052 virtual void SubMethod(int subarg) const;
Casey Dahlin88924d62015-09-17 16:28:24 -070053}; // class TestSubClass
Casey Dahlin34b86102015-09-16 16:03:06 -070054
Christopher Wileyf600a552015-09-12 14:07:44 -070055} // namespace test
Casey Dahlin34b86102015-09-16 16:03:06 -070056
Christopher Wileyf600a552015-09-12 14:07:44 -070057} // namespace android
58
Christopher Wiley11a9d792016-02-24 17:20:33 -080059#endif // HEADER_INCLUDE_GUARD_H_
60)";
Christopher Wileyf600a552015-09-12 14:07:44 -070061
Christopher Wileya7a5c102015-09-29 16:26:52 -070062const char kExpectedEnumOutput[] =
63R"(enum Foo {
64 BAR = 42,
65 BAZ,
Christopher Wiley3bb6bc12015-10-14 10:58:27 -070066};
Christopher Wileya7a5c102015-09-29 16:26:52 -070067)";
68
Christopher Wileyda695992015-10-05 11:31:41 -070069const char kExpectedSwitchOutput[] =
70R"(switch (var) {
71case 2:
72{
Jiyong Parka755dc72018-06-29 13:52:24 +090073 baz;
Christopher Wileyda695992015-10-05 11:31:41 -070074}
75break;
76case 1:
77{
Jiyong Parka755dc72018-06-29 13:52:24 +090078 foo;
79 bar;
Christopher Wileyda695992015-10-05 11:31:41 -070080}
81break;
82}
83)";
84
85const char kExpectedMethodImplOutput[] =
Christopher Wileyade4b452015-10-10 11:06:03 -070086R"(return_type ClassName::MethodName(arg 1, arg 2, arg 3) const {
Jiyong Parka755dc72018-06-29 13:52:24 +090087 foo;
88 bar;
Christopher Wileyda695992015-10-05 11:31:41 -070089}
90)";
Christopher Wileyf600a552015-09-12 14:07:44 -070091} // namespace
92
Christopher Wileyda695992015-10-05 11:31:41 -070093class AstCppTests : public ::testing::Test {
94 protected:
Christopher Wiley23285262015-10-09 15:06:14 -070095 void CompareGeneratedCode(const AstNode& node,
96 const string& expected_output) {
Christopher Wileyda695992015-10-05 11:31:41 -070097 string actual_output;
Jiyong Parkb78e15b2018-07-04 20:31:03 +090098 node.Write(CodeWriter::ForString(&actual_output).get());
Christopher Wileyda695992015-10-05 11:31:41 -070099 EXPECT_EQ(expected_output, actual_output);
100 }
101}; // class AstCppTests
102
103
104TEST_F(AstCppTests, GeneratesHeader) {
Christopher Wileyade4b452015-10-10 11:06:03 -0700105 unique_ptr<MethodDecl> norm{new MethodDecl(
106 "void", "NormalMethod",
107 ArgList{vector<string>{"int normalarg", "float normal2"}})};
Christopher Wiley0c732db2015-09-29 14:36:44 -0700108 unique_ptr<MethodDecl> sub{
109 new MethodDecl("void", "SubMethod",
Christopher Wileyade4b452015-10-10 11:06:03 -0700110 ArgList{ "int subarg" },
Christopher Wiley0c732db2015-09-29 14:36:44 -0700111 MethodDecl::IS_CONST | MethodDecl::IS_VIRTUAL)};
112 unique_ptr<MethodDecl> sub2{
113 new MethodDecl("void", "SubMethod",
Christopher Wileyade4b452015-10-10 11:06:03 -0700114 ArgList{ "int subarg" },
Christopher Wiley0c732db2015-09-29 14:36:44 -0700115 MethodDecl::IS_CONST | MethodDecl::IS_VIRTUAL)};
Christopher Wileyf944e792015-09-29 10:00:46 -0700116 vector<unique_ptr<Declaration>> test_methods;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700117 test_methods.push_back(std::move(norm));
118 test_methods.push_back(std::move(sub));
119
Christopher Wileyf944e792015-09-29 10:00:46 -0700120 vector<unique_ptr<Declaration>> test_sub_methods;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700121 test_sub_methods.push_back(std::move(sub2));
122
Christopher Wileyf944e792015-09-29 10:00:46 -0700123 unique_ptr<Declaration> test{new ClassDecl { "TestClass", "",
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700124 std::move(test_methods), {} }};
125
Christopher Wileyf944e792015-09-29 10:00:46 -0700126 unique_ptr<Declaration> test_sub{new ClassDecl { "TestSubClass",
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700127 "TestClass", std::move(test_sub_methods), {} }};
128
Christopher Wileyf944e792015-09-29 10:00:46 -0700129 vector<unique_ptr<Declaration>> classes;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700130 classes.push_back(std::move(test));
131 classes.push_back(std::move(test_sub));
132
133 unique_ptr<CppNamespace> test_ns{new CppNamespace {"test",
134 std::move(classes)}};
135
Christopher Wileyf944e792015-09-29 10:00:46 -0700136 vector<unique_ptr<Declaration>> test_ns_vec;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700137 test_ns_vec.push_back(std::move(test_ns));
138
Christopher Wiley23285262015-10-09 15:06:14 -0700139 unique_ptr<CppNamespace> android_ns{new CppNamespace {"android",
140 std::move(test_ns_vec) }};
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700141
Steven Morelandf3da0892018-10-05 14:52:01 -0700142 vector<unique_ptr<Declaration>> test_ns_globals;
143 test_ns_globals.push_back(std::move(android_ns));
144
145 CppHeader cpp_header{"HEADER_INCLUDE_GUARD_H_", {"string", "memory"}, std::move(test_ns_globals)};
Christopher Wiley23285262015-10-09 15:06:14 -0700146 CompareGeneratedCode(cpp_header, kExpectedHeaderOutput);
Christopher Wileyf600a552015-09-12 14:07:44 -0700147}
148
Christopher Wileyda695992015-10-05 11:31:41 -0700149TEST_F(AstCppTests, GeneratesEnum) {
Christopher Wileya7a5c102015-09-29 16:26:52 -0700150 Enum e("Foo");
151 e.AddValue("BAR", "42");
152 e.AddValue("BAZ", "");
Christopher Wiley23285262015-10-09 15:06:14 -0700153 CompareGeneratedCode(e, kExpectedEnumOutput);
154}
155
156TEST_F(AstCppTests, GeneratesArgList) {
157 ArgList simple("foo");
158 CompareGeneratedCode(simple, "(foo)");
159 ArgList compound({"foo", "bar", "baz"});
160 CompareGeneratedCode(compound, "(foo, bar, baz)");
Christopher Wileyf02facf2015-11-12 08:54:08 -0800161 std::vector<unique_ptr<AstNode>> args;
162 args.emplace_back(new LiteralExpression("foo()"));
163 ArgList nested(std::move(args));
164 CompareGeneratedCode(nested, "(foo())");
Christopher Wileyda695992015-10-05 11:31:41 -0700165}
166
Christopher Wiley3c5d28d2015-10-21 09:53:46 -0700167TEST_F(AstCppTests, GeneratesStatement) {
168 Statement s(new LiteralExpression("foo"));
Christopher Wiley23285262015-10-09 15:06:14 -0700169 CompareGeneratedCode(s, "foo;\n");
Christopher Wileyda695992015-10-05 11:31:41 -0700170}
171
Christopher Wileyd55db282015-10-20 18:16:47 -0700172TEST_F(AstCppTests, GeneratesComparison) {
173 Comparison c(
174 new LiteralExpression("lhs"), "&&", new LiteralExpression("rhs"));
175 CompareGeneratedCode(c, "((lhs) && (rhs))");
176}
177
Christopher Wileyda695992015-10-05 11:31:41 -0700178TEST_F(AstCppTests, GeneratesStatementBlock) {
179 StatementBlock block;
Christopher Wiley3c5d28d2015-10-21 09:53:46 -0700180 block.AddStatement(unique_ptr<AstNode>(new Statement("foo")));
181 block.AddStatement(unique_ptr<AstNode>(new Statement("bar")));
Jiyong Parka755dc72018-06-29 13:52:24 +0900182 CompareGeneratedCode(block, "{\n foo;\n bar;\n}\n");
Christopher Wiley23285262015-10-09 15:06:14 -0700183}
184
Christopher Wileyf9688b02015-10-08 17:17:50 -0700185TEST_F(AstCppTests, GeneratesConstructorImpl) {
186 ConstructorImpl c("ClassName", ArgList({"a", "b", "c"}),
187 {"baz_(foo)", "bar_(blah)"});
188 string expected = R"(ClassName::ClassName(a, b, c)
189 : baz_(foo),
190 bar_(blah){
191}
192)";
193 CompareGeneratedCode(c, expected);
194}
195
Christopher Wiley23285262015-10-09 15:06:14 -0700196TEST_F(AstCppTests, GeneratesAssignment) {
197 Assignment simple("foo", "8");
198 CompareGeneratedCode(simple, "foo = 8;\n");
199 Assignment less_simple("foo", new MethodCall("f", "8"));
200 CompareGeneratedCode(less_simple, "foo = f(8);\n");
201}
202
203TEST_F(AstCppTests, GeneratesMethodCall) {
204 MethodCall single("single", "arg");
205 CompareGeneratedCode(single, "single(arg)");
Christopher Wileyade4b452015-10-10 11:06:03 -0700206 MethodCall multi(
207 "multi",
208 ArgList({"has", "some", "args"}));
Christopher Wiley23285262015-10-09 15:06:14 -0700209 CompareGeneratedCode(multi, "multi(has, some, args)");
Christopher Wileyda695992015-10-05 11:31:41 -0700210}
211
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700212TEST_F(AstCppTests, GeneratesIfStatement) {
213 IfStatement s(new LiteralExpression("foo"));
214 s.OnTrue()->AddLiteral("on true1");
215 s.OnFalse()->AddLiteral("on false");
Jiyong Parka755dc72018-06-29 13:52:24 +0900216 CompareGeneratedCode(s, "if (foo) {\n on true1;\n}\nelse {\n on false;\n}\n");
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700217
218 IfStatement s2(new LiteralExpression("bar"));
219 s2.OnTrue()->AddLiteral("on true1");
Jiyong Parka755dc72018-06-29 13:52:24 +0900220 CompareGeneratedCode(s2, "if (bar) {\n on true1;\n}\n");
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700221}
222
Christopher Wileyda695992015-10-05 11:31:41 -0700223TEST_F(AstCppTests, GeneratesSwitchStatement) {
224 SwitchStatement s("var");
225 // These are intentionally out of alphanumeric order. We're testing
226 // that switch respects case addition order.
227 auto case2 = s.AddCase("2");
Christopher Wiley3c5d28d2015-10-21 09:53:46 -0700228 case2->AddStatement(unique_ptr<AstNode>{new Statement{"baz"}});
Christopher Wileyda695992015-10-05 11:31:41 -0700229 auto case1 = s.AddCase("1");
Christopher Wiley3c5d28d2015-10-21 09:53:46 -0700230 case1->AddStatement(unique_ptr<AstNode>{new Statement{"foo"}});
231 case1->AddStatement(unique_ptr<AstNode>{new Statement{"bar"}});
Christopher Wiley23285262015-10-09 15:06:14 -0700232 CompareGeneratedCode(s, kExpectedSwitchOutput);
Christopher Wileyda695992015-10-05 11:31:41 -0700233}
234
235TEST_F(AstCppTests, GeneratesMethodImpl) {
236 MethodImpl m{"return_type", "ClassName", "MethodName",
Christopher Wileyade4b452015-10-10 11:06:03 -0700237 ArgList{{"arg 1", "arg 2", "arg 3"}},
238 true};
Christopher Wileyf9688b02015-10-08 17:17:50 -0700239 auto b = m.GetStatementBlock();
240 b->AddLiteral("foo");
241 b->AddLiteral("bar");
Christopher Wiley23285262015-10-09 15:06:14 -0700242 CompareGeneratedCode(m, kExpectedMethodImplOutput);
Christopher Wileya7a5c102015-09-29 16:26:52 -0700243}
244
Jiyong Park176905e2018-07-04 22:29:41 +0900245TEST_F(AstCppTests, ToString) {
246 std::string literal = "void foo() {}";
247 LiteralDecl decl(literal);
248 std::string actual = decl.ToString();
249 EXPECT_EQ(literal, actual);
250 std::string written;
251 decl.Write(CodeWriter::ForString(&written).get());
252 EXPECT_EQ(literal, written);
253}
254
Christopher Wileyf944e792015-09-29 10:00:46 -0700255} // namespace cpp
Christopher Wileyf600a552015-09-12 14:07:44 -0700256} // namespace aidl
257} // namespace android