blob: 0efdbcd5641bcafaedb146a3ee8d6f50f94892d5 [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
Devin Moore53fc99c2020-08-12 08:07:52 -070033// clang-format off
Christopher Wileyf600a552015-09-12 14:07:44 -070034const char kExpectedHeaderOutput[] =
Devin Moore7aaa9cb2020-08-13 14:53:01 -070035 R"(#pragma once
Christopher Wileyf600a552015-09-12 14:07:44 -070036
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
Christopher Wiley11a9d792016-02-24 17:20:33 -080058)";
Christopher Wileyf600a552015-09-12 14:07:44 -070059
Devin Moore53fc99c2020-08-12 08:07:52 -070060const char kExpectedGenericHeaderOutput[] =
61 R"(#pragma once
62
63#include <string>
64#include <memory>
65
66namespace android {
67
68namespace test {
69
70template <typename A, typename B>
71class TestParcelable : public ::android::Parcelable {
72public:
73 int a;
74}; // class TestParcelable
75
76} // namespace test
77
78} // namespace android
79)";
80// clang-format on
81
Christopher Wileyda695992015-10-05 11:31:41 -070082const char kExpectedSwitchOutput[] =
83R"(switch (var) {
84case 2:
85{
Jiyong Parka755dc72018-06-29 13:52:24 +090086 baz;
Christopher Wileyda695992015-10-05 11:31:41 -070087}
88break;
89case 1:
90{
Jiyong Parka755dc72018-06-29 13:52:24 +090091 foo;
92 bar;
Christopher Wileyda695992015-10-05 11:31:41 -070093}
94break;
95}
96)";
97
98const char kExpectedMethodImplOutput[] =
Devin Moore53fc99c2020-08-12 08:07:52 -070099 R"(return_type ClassName::MethodName(int32_t a, int32_t b, int32_t* c) const {
100 foo;
101 bar;
102}
103)";
104const char kExpectedGenericMethodImplOutput[] =
105 R"(template <typename T>
106return_type ClassName<T>::MethodName(int32_t a, int32_t b, int32_t* c) const {
Jiyong Parka755dc72018-06-29 13:52:24 +0900107 foo;
108 bar;
Christopher Wileyda695992015-10-05 11:31:41 -0700109}
110)";
Christopher Wileyf600a552015-09-12 14:07:44 -0700111} // namespace
112
Christopher Wileyda695992015-10-05 11:31:41 -0700113class AstCppTests : public ::testing::Test {
114 protected:
Christopher Wiley23285262015-10-09 15:06:14 -0700115 void CompareGeneratedCode(const AstNode& node,
116 const string& expected_output) {
Christopher Wileyda695992015-10-05 11:31:41 -0700117 string actual_output;
Jiyong Parkb78e15b2018-07-04 20:31:03 +0900118 node.Write(CodeWriter::ForString(&actual_output).get());
Christopher Wileyda695992015-10-05 11:31:41 -0700119 EXPECT_EQ(expected_output, actual_output);
120 }
121}; // class AstCppTests
122
123
124TEST_F(AstCppTests, GeneratesHeader) {
Christopher Wileyade4b452015-10-10 11:06:03 -0700125 unique_ptr<MethodDecl> norm{new MethodDecl(
126 "void", "NormalMethod",
127 ArgList{vector<string>{"int normalarg", "float normal2"}})};
Christopher Wiley0c732db2015-09-29 14:36:44 -0700128 unique_ptr<MethodDecl> sub{
129 new MethodDecl("void", "SubMethod",
Christopher Wileyade4b452015-10-10 11:06:03 -0700130 ArgList{ "int subarg" },
Christopher Wiley0c732db2015-09-29 14:36:44 -0700131 MethodDecl::IS_CONST | MethodDecl::IS_VIRTUAL)};
132 unique_ptr<MethodDecl> sub2{
133 new MethodDecl("void", "SubMethod",
Christopher Wileyade4b452015-10-10 11:06:03 -0700134 ArgList{ "int subarg" },
Christopher Wiley0c732db2015-09-29 14:36:44 -0700135 MethodDecl::IS_CONST | MethodDecl::IS_VIRTUAL)};
Christopher Wileyf944e792015-09-29 10:00:46 -0700136 vector<unique_ptr<Declaration>> test_methods;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700137 test_methods.push_back(std::move(norm));
138 test_methods.push_back(std::move(sub));
139
Christopher Wileyf944e792015-09-29 10:00:46 -0700140 vector<unique_ptr<Declaration>> test_sub_methods;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700141 test_sub_methods.push_back(std::move(sub2));
142
Devin Moore53fc99c2020-08-12 08:07:52 -0700143 unique_ptr<Declaration> test{new ClassDecl{"TestClass", "", {}, std::move(test_methods), {}}};
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700144
Devin Moore53fc99c2020-08-12 08:07:52 -0700145 unique_ptr<Declaration> test_sub{
146 new ClassDecl{"TestSubClass", "TestClass", {}, std::move(test_sub_methods), {}}};
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700147
Christopher Wileyf944e792015-09-29 10:00:46 -0700148 vector<unique_ptr<Declaration>> classes;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700149 classes.push_back(std::move(test));
150 classes.push_back(std::move(test_sub));
151
152 unique_ptr<CppNamespace> test_ns{new CppNamespace {"test",
153 std::move(classes)}};
154
Christopher Wileyf944e792015-09-29 10:00:46 -0700155 vector<unique_ptr<Declaration>> test_ns_vec;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700156 test_ns_vec.push_back(std::move(test_ns));
157
Christopher Wiley23285262015-10-09 15:06:14 -0700158 unique_ptr<CppNamespace> android_ns{new CppNamespace {"android",
159 std::move(test_ns_vec) }};
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700160
Steven Morelandf3da0892018-10-05 14:52:01 -0700161 vector<unique_ptr<Declaration>> test_ns_globals;
162 test_ns_globals.push_back(std::move(android_ns));
163
Devin Moore7aaa9cb2020-08-13 14:53:01 -0700164 CppHeader cpp_header{{"string", "memory"}, std::move(test_ns_globals)};
Christopher Wiley23285262015-10-09 15:06:14 -0700165 CompareGeneratedCode(cpp_header, kExpectedHeaderOutput);
Christopher Wileyf600a552015-09-12 14:07:44 -0700166}
167
Devin Moore53fc99c2020-08-12 08:07:52 -0700168TEST_F(AstCppTests, GeneratesGenericHeader) {
169 const std::vector<std::string> type_params = {"A", "B"};
170 std::vector<std::unique_ptr<Declaration>> publics;
171 publics.emplace_back(new LiteralDecl("int a;\n"));
172 unique_ptr<Declaration> test{new ClassDecl{
173 "TestParcelable", "::android::Parcelable", type_params, std::move(publics), {}}};
174
175 vector<unique_ptr<Declaration>> classes;
176 classes.push_back(std::move(test));
177
178 unique_ptr<CppNamespace> test_ns{new CppNamespace{"test", std::move(classes)}};
179
180 vector<unique_ptr<Declaration>> test_ns_vec;
181 test_ns_vec.push_back(std::move(test_ns));
182
183 unique_ptr<CppNamespace> android_ns{new CppNamespace{"android", std::move(test_ns_vec)}};
184
185 vector<unique_ptr<Declaration>> test_ns_globals;
186 test_ns_globals.push_back(std::move(android_ns));
187
188 CppHeader cpp_header{{"string", "memory"}, std::move(test_ns_globals)};
189 CompareGeneratedCode(cpp_header, kExpectedGenericHeaderOutput);
190}
191
Daniel Norman85aed542019-08-21 12:01:14 -0700192TEST_F(AstCppTests, GeneratesUnscopedEnum) {
193 Enum e("Foo", "", false);
Christopher Wileya7a5c102015-09-29 16:26:52 -0700194 e.AddValue("BAR", "42");
195 e.AddValue("BAZ", "");
Daniel Norman85aed542019-08-21 12:01:14 -0700196
197 string expected =
198 R"(enum Foo {
199 BAR = 42,
200 BAZ,
201};
202)";
203
204 CompareGeneratedCode(e, expected);
205}
206
207TEST_F(AstCppTests, GeneratesScopedEnum) {
208 Enum e("Foo", "int32_t", true);
209 e.AddValue("BAR", "42");
210 e.AddValue("BAZ", "");
211
212 string expected =
213 R"(enum class Foo : int32_t {
214 BAR = 42,
215 BAZ,
216};
217)";
218
219 CompareGeneratedCode(e, expected);
Christopher Wiley23285262015-10-09 15:06:14 -0700220}
221
222TEST_F(AstCppTests, GeneratesArgList) {
223 ArgList simple("foo");
224 CompareGeneratedCode(simple, "(foo)");
225 ArgList compound({"foo", "bar", "baz"});
226 CompareGeneratedCode(compound, "(foo, bar, baz)");
Christopher Wileyf02facf2015-11-12 08:54:08 -0800227 std::vector<unique_ptr<AstNode>> args;
228 args.emplace_back(new LiteralExpression("foo()"));
229 ArgList nested(std::move(args));
230 CompareGeneratedCode(nested, "(foo())");
Christopher Wileyda695992015-10-05 11:31:41 -0700231}
232
Christopher Wiley3c5d28d2015-10-21 09:53:46 -0700233TEST_F(AstCppTests, GeneratesStatement) {
234 Statement s(new LiteralExpression("foo"));
Christopher Wiley23285262015-10-09 15:06:14 -0700235 CompareGeneratedCode(s, "foo;\n");
Christopher Wileyda695992015-10-05 11:31:41 -0700236}
237
Christopher Wileyd55db282015-10-20 18:16:47 -0700238TEST_F(AstCppTests, GeneratesComparison) {
239 Comparison c(
240 new LiteralExpression("lhs"), "&&", new LiteralExpression("rhs"));
241 CompareGeneratedCode(c, "((lhs) && (rhs))");
242}
243
Christopher Wileyda695992015-10-05 11:31:41 -0700244TEST_F(AstCppTests, GeneratesStatementBlock) {
245 StatementBlock block;
Christopher Wiley3c5d28d2015-10-21 09:53:46 -0700246 block.AddStatement(unique_ptr<AstNode>(new Statement("foo")));
247 block.AddStatement(unique_ptr<AstNode>(new Statement("bar")));
Jiyong Parka755dc72018-06-29 13:52:24 +0900248 CompareGeneratedCode(block, "{\n foo;\n bar;\n}\n");
Christopher Wiley23285262015-10-09 15:06:14 -0700249}
250
Christopher Wileyf9688b02015-10-08 17:17:50 -0700251TEST_F(AstCppTests, GeneratesConstructorImpl) {
252 ConstructorImpl c("ClassName", ArgList({"a", "b", "c"}),
253 {"baz_(foo)", "bar_(blah)"});
254 string expected = R"(ClassName::ClassName(a, b, c)
255 : baz_(foo),
256 bar_(blah){
257}
258)";
259 CompareGeneratedCode(c, expected);
260}
261
Christopher Wiley23285262015-10-09 15:06:14 -0700262TEST_F(AstCppTests, GeneratesAssignment) {
263 Assignment simple("foo", "8");
264 CompareGeneratedCode(simple, "foo = 8;\n");
265 Assignment less_simple("foo", new MethodCall("f", "8"));
266 CompareGeneratedCode(less_simple, "foo = f(8);\n");
267}
268
269TEST_F(AstCppTests, GeneratesMethodCall) {
270 MethodCall single("single", "arg");
271 CompareGeneratedCode(single, "single(arg)");
Christopher Wileyade4b452015-10-10 11:06:03 -0700272 MethodCall multi(
273 "multi",
274 ArgList({"has", "some", "args"}));
Christopher Wiley23285262015-10-09 15:06:14 -0700275 CompareGeneratedCode(multi, "multi(has, some, args)");
Christopher Wileyda695992015-10-05 11:31:41 -0700276}
277
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700278TEST_F(AstCppTests, GeneratesIfStatement) {
279 IfStatement s(new LiteralExpression("foo"));
280 s.OnTrue()->AddLiteral("on true1");
281 s.OnFalse()->AddLiteral("on false");
Jiyong Parka755dc72018-06-29 13:52:24 +0900282 CompareGeneratedCode(s, "if (foo) {\n on true1;\n}\nelse {\n on false;\n}\n");
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700283
284 IfStatement s2(new LiteralExpression("bar"));
285 s2.OnTrue()->AddLiteral("on true1");
Jiyong Parka755dc72018-06-29 13:52:24 +0900286 CompareGeneratedCode(s2, "if (bar) {\n on true1;\n}\n");
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700287}
288
Christopher Wileyda695992015-10-05 11:31:41 -0700289TEST_F(AstCppTests, GeneratesSwitchStatement) {
290 SwitchStatement s("var");
291 // These are intentionally out of alphanumeric order. We're testing
292 // that switch respects case addition order.
293 auto case2 = s.AddCase("2");
Christopher Wiley3c5d28d2015-10-21 09:53:46 -0700294 case2->AddStatement(unique_ptr<AstNode>{new Statement{"baz"}});
Christopher Wileyda695992015-10-05 11:31:41 -0700295 auto case1 = s.AddCase("1");
Christopher Wiley3c5d28d2015-10-21 09:53:46 -0700296 case1->AddStatement(unique_ptr<AstNode>{new Statement{"foo"}});
297 case1->AddStatement(unique_ptr<AstNode>{new Statement{"bar"}});
Christopher Wiley23285262015-10-09 15:06:14 -0700298 CompareGeneratedCode(s, kExpectedSwitchOutput);
Christopher Wileyda695992015-10-05 11:31:41 -0700299}
300
301TEST_F(AstCppTests, GeneratesMethodImpl) {
Devin Moore53fc99c2020-08-12 08:07:52 -0700302 MethodImpl m{"return_type",
303 "ClassName",
304 "MethodName",
305 {},
306 ArgList{{"int32_t a", "int32_t b", "int32_t* c"}},
Christopher Wileyade4b452015-10-10 11:06:03 -0700307 true};
Christopher Wileyf9688b02015-10-08 17:17:50 -0700308 auto b = m.GetStatementBlock();
309 b->AddLiteral("foo");
310 b->AddLiteral("bar");
Christopher Wiley23285262015-10-09 15:06:14 -0700311 CompareGeneratedCode(m, kExpectedMethodImplOutput);
Christopher Wileya7a5c102015-09-29 16:26:52 -0700312}
313
Devin Moore53fc99c2020-08-12 08:07:52 -0700314TEST_F(AstCppTests, GeneratesGenericMethodImpl) {
315 MethodImpl m{"return_type",
316 "ClassName",
317 "MethodName",
318 {"T"},
319 ArgList{{"int32_t a", "int32_t b", "int32_t* c"}},
320 true};
321 auto b = m.GetStatementBlock();
322 b->AddLiteral("foo");
323 b->AddLiteral("bar");
324 CompareGeneratedCode(m, kExpectedGenericMethodImplOutput);
325}
326
Jiyong Park176905e2018-07-04 22:29:41 +0900327TEST_F(AstCppTests, ToString) {
328 std::string literal = "void foo() {}";
329 LiteralDecl decl(literal);
330 std::string actual = decl.ToString();
331 EXPECT_EQ(literal, actual);
332 std::string written;
333 decl.Write(CodeWriter::ForString(&written).get());
334 EXPECT_EQ(literal, written);
335}
336
Christopher Wileyf944e792015-09-29 10:00:46 -0700337} // namespace cpp
Christopher Wileyf600a552015-09-12 14:07:44 -0700338} // namespace aidl
339} // namespace android