• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
24 using std::string;
25 using std::vector;
26 using std::unique_ptr;
27 
28 namespace android {
29 namespace aidl {
30 namespace cpp {
31 namespace {
32 
33 // clang-format off
34 const char kExpectedHeaderOutput[] =
35     R"(#pragma once
36 
37 #include <string>
38 #include <memory>
39 
40 namespace android {
41 
42 namespace test {
43 
44 class TestClass {
45 public:
46   void NormalMethod(int normalarg, float normal2);
47   virtual void SubMethod(int subarg) const;
48 };  // class TestClass
49 
50 class TestSubClass : public TestClass {
51 public:
52   virtual void SubMethod(int subarg) const;
53 };  // class TestSubClass
54 
55 }  // namespace test
56 
57 }  // namespace android
58 )";
59 
60 const char kExpectedGenericHeaderOutput[] =
61     R"(#pragma once
62 
63 #include <string>
64 #include <memory>
65 
66 namespace android {
67 
68 namespace test {
69 
70 template <typename A, typename B>
71 class TestParcelable : public ::android::Parcelable {
72 public:
73   int a;
74 };  // class TestParcelable
75 
76 }  // namespace test
77 
78 }  // namespace android
79 )";
80 // clang-format on
81 
82 const char kExpectedSwitchOutput[] =
83 R"(switch (var) {
84 case 2:
85 {
86   baz;
87 }
88 break;
89 case 1:
90 {
91   foo;
92   bar;
93 }
94 break;
95 }
96 )";
97 
98 const char kExpectedMethodImplOutput[] =
99     R"(return_type ClassName::MethodName(int32_t a, int32_t b, int32_t* c) const {
100   foo;
101   bar;
102 }
103 )";
104 const char kExpectedGenericMethodImplOutput[] =
105     R"(template <typename T>
106 return_type ClassName<T>::MethodName(int32_t a, int32_t b, int32_t* c) const {
107   foo;
108   bar;
109 }
110 )";
111 }  // namespace
112 
113 class AstCppTests : public ::testing::Test {
114  protected:
CompareGeneratedCode(const AstNode & node,const string & expected_output)115   void CompareGeneratedCode(const AstNode& node,
116                             const string& expected_output) {
117     string actual_output;
118     node.Write(CodeWriter::ForString(&actual_output).get());
119     EXPECT_EQ(expected_output, actual_output);
120   }
121 };  // class AstCppTests
122 
123 
TEST_F(AstCppTests,GeneratesHeader)124 TEST_F(AstCppTests, GeneratesHeader) {
125   unique_ptr<MethodDecl> norm{new MethodDecl(
126       "void", "NormalMethod",
127       ArgList{vector<string>{"int normalarg", "float normal2"}})};
128   unique_ptr<MethodDecl> sub{
129       new MethodDecl("void", "SubMethod",
130                      ArgList{ "int subarg" },
131                      MethodDecl::IS_CONST | MethodDecl::IS_VIRTUAL)};
132   unique_ptr<MethodDecl> sub2{
133       new MethodDecl("void", "SubMethod",
134                      ArgList{ "int subarg" },
135                      MethodDecl::IS_CONST | MethodDecl::IS_VIRTUAL)};
136   vector<unique_ptr<Declaration>> test_methods;
137   test_methods.push_back(std::move(norm));
138   test_methods.push_back(std::move(sub));
139 
140   vector<unique_ptr<Declaration>> test_sub_methods;
141   test_sub_methods.push_back(std::move(sub2));
142 
143   unique_ptr<Declaration> test{new ClassDecl{"TestClass", "", {}, std::move(test_methods), {}}};
144 
145   unique_ptr<Declaration> test_sub{
146       new ClassDecl{"TestSubClass", "TestClass", {}, std::move(test_sub_methods), {}}};
147 
148   vector<unique_ptr<Declaration>> classes;
149   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 
155   vector<unique_ptr<Declaration>> test_ns_vec;
156   test_ns_vec.push_back(std::move(test_ns));
157 
158   unique_ptr<CppNamespace> android_ns{new CppNamespace {"android",
159       std::move(test_ns_vec) }};
160 
161   vector<unique_ptr<Declaration>> test_ns_globals;
162   test_ns_globals.push_back(std::move(android_ns));
163 
164   CppHeader cpp_header{{"string", "memory"}, std::move(test_ns_globals)};
165   CompareGeneratedCode(cpp_header, kExpectedHeaderOutput);
166 }
167 
TEST_F(AstCppTests,GeneratesGenericHeader)168 TEST_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 
TEST_F(AstCppTests,GeneratesUnscopedEnum)192 TEST_F(AstCppTests, GeneratesUnscopedEnum) {
193   Enum e("Foo", "", false);
194   e.AddValue("BAR", "42");
195   e.AddValue("BAZ", "");
196 
197   string expected =
198       R"(enum Foo {
199   BAR = 42,
200   BAZ,
201 };
202 )";
203 
204   CompareGeneratedCode(e, expected);
205 }
206 
TEST_F(AstCppTests,GeneratesScopedEnum)207 TEST_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);
220 }
221 
TEST_F(AstCppTests,GeneratesArgList)222 TEST_F(AstCppTests, GeneratesArgList) {
223   ArgList simple("foo");
224   CompareGeneratedCode(simple, "(foo)");
225   ArgList compound({"foo", "bar", "baz"});
226   CompareGeneratedCode(compound, "(foo, bar, baz)");
227   std::vector<unique_ptr<AstNode>> args;
228   args.emplace_back(new LiteralExpression("foo()"));
229   ArgList nested(std::move(args));
230   CompareGeneratedCode(nested, "(foo())");
231 }
232 
TEST_F(AstCppTests,GeneratesStatement)233 TEST_F(AstCppTests, GeneratesStatement) {
234   Statement s(new LiteralExpression("foo"));
235   CompareGeneratedCode(s, "foo;\n");
236 }
237 
TEST_F(AstCppTests,GeneratesComparison)238 TEST_F(AstCppTests, GeneratesComparison) {
239   Comparison c(
240       new LiteralExpression("lhs"), "&&", new LiteralExpression("rhs"));
241   CompareGeneratedCode(c, "((lhs) && (rhs))");
242 }
243 
TEST_F(AstCppTests,GeneratesStatementBlock)244 TEST_F(AstCppTests, GeneratesStatementBlock) {
245   StatementBlock block;
246   block.AddStatement(unique_ptr<AstNode>(new Statement("foo")));
247   block.AddStatement(unique_ptr<AstNode>(new Statement("bar")));
248   CompareGeneratedCode(block, "{\n  foo;\n  bar;\n}\n");
249 }
250 
TEST_F(AstCppTests,GeneratesConstructorImpl)251 TEST_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 
TEST_F(AstCppTests,GeneratesAssignment)262 TEST_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 
TEST_F(AstCppTests,GeneratesMethodCall)269 TEST_F(AstCppTests, GeneratesMethodCall) {
270   MethodCall single("single", "arg");
271   CompareGeneratedCode(single, "single(arg)");
272   MethodCall multi(
273       "multi",
274       ArgList({"has", "some", "args"}));
275   CompareGeneratedCode(multi, "multi(has, some, args)");
276 }
277 
TEST_F(AstCppTests,GeneratesIfStatement)278 TEST_F(AstCppTests, GeneratesIfStatement) {
279   IfStatement s(new LiteralExpression("foo"));
280   s.OnTrue()->AddLiteral("on true1");
281   s.OnFalse()->AddLiteral("on false");
282   CompareGeneratedCode(s, "if (foo) {\n  on true1;\n}\nelse {\n  on false;\n}\n");
283 
284   IfStatement s2(new LiteralExpression("bar"));
285   s2.OnTrue()->AddLiteral("on true1");
286   CompareGeneratedCode(s2, "if (bar) {\n  on true1;\n}\n");
287 }
288 
TEST_F(AstCppTests,GeneratesSwitchStatement)289 TEST_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");
294   case2->AddStatement(unique_ptr<AstNode>{new Statement{"baz"}});
295   auto case1 = s.AddCase("1");
296   case1->AddStatement(unique_ptr<AstNode>{new Statement{"foo"}});
297   case1->AddStatement(unique_ptr<AstNode>{new Statement{"bar"}});
298   CompareGeneratedCode(s, kExpectedSwitchOutput);
299 }
300 
TEST_F(AstCppTests,GeneratesMethodImpl)301 TEST_F(AstCppTests, GeneratesMethodImpl) {
302   MethodImpl m{"return_type",
303                "ClassName",
304                "MethodName",
305                {},
306                ArgList{{"int32_t a", "int32_t b", "int32_t* c"}},
307                true};
308   auto b = m.GetStatementBlock();
309   b->AddLiteral("foo");
310   b->AddLiteral("bar");
311   CompareGeneratedCode(m, kExpectedMethodImplOutput);
312 }
313 
TEST_F(AstCppTests,GeneratesGenericMethodImpl)314 TEST_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 
TEST_F(AstCppTests,ToString)327 TEST_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 
337 }  // namespace cpp
338 }  // namespace aidl
339 }  // namespace android
340