blob: 271279ff5e92af759164c7e6fcf50f74d9b98f23 [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
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
Adam Lesinskica5638f2015-10-21 14:42:43 -070017#include "java/JavaClassGenerator.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070018
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080019#include <sstream>
20#include <string>
21
Adam Lesinskice5e56e2016-10-21 17:56:45 -070022#include "test/Test.h"
23#include "util/Util.h"
24
Adam Lesinskid5083f62017-01-16 15:07:21 -080025using android::StringPiece;
26
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080027namespace aapt {
28
Adam Lesinski1ab598f2015-08-14 14:26:04 -070029TEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070030 std::unique_ptr<ResourceTable> table =
31 test::ResourceTableBuilder()
32 .SetPackageId("android", 0x01)
33 .AddSimple("android:id/class", ResourceId(0x01020000))
34 .Build();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080035
Adam Lesinskice5e56e2016-10-21 17:56:45 -070036 std::unique_ptr<IAaptContext> context =
37 test::ContextBuilder()
38 .AddSymbolSource(
39 util::make_unique<ResourceTableSymbolSource>(table.get()))
40 .SetNameManglerPolicy(NameManglerPolicy{"android"})
41 .Build();
42 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080043
Adam Lesinskice5e56e2016-10-21 17:56:45 -070044 std::stringstream out;
45 EXPECT_FALSE(generator.Generate("android", &out));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080046}
47
Adam Lesinski1ab598f2015-08-14 14:26:04 -070048TEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070049 std::unique_ptr<ResourceTable> table =
50 test::ResourceTableBuilder()
51 .SetPackageId("android", 0x01)
52 .AddSimple("android:id/hey-man", ResourceId(0x01020000))
53 .AddValue("android:attr/cool.attr", ResourceId(0x01010000),
54 test::AttributeBuilder(false).Build())
55 .AddValue(
56 "android:styleable/hey.dude", ResourceId(0x01030000),
57 test::StyleableBuilder()
58 .AddItem("android:attr/cool.attr", ResourceId(0x01010000))
59 .Build())
60 .Build();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080061
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062 std::unique_ptr<IAaptContext> context =
63 test::ContextBuilder()
64 .AddSymbolSource(
65 util::make_unique<ResourceTableSymbolSource>(table.get()))
66 .SetNameManglerPolicy(NameManglerPolicy{"android"})
67 .Build();
68 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080069
Adam Lesinskice5e56e2016-10-21 17:56:45 -070070 std::stringstream out;
71 EXPECT_TRUE(generator.Generate("android", &out));
Adam Lesinski1ab598f2015-08-14 14:26:04 -070072
Adam Lesinskice5e56e2016-10-21 17:56:45 -070073 std::string output = out.str();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080074
Adam Lesinskice5e56e2016-10-21 17:56:45 -070075 EXPECT_NE(std::string::npos,
76 output.find("public static final int hey_man=0x01020000;"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080077
Adam Lesinskice5e56e2016-10-21 17:56:45 -070078 EXPECT_NE(std::string::npos,
79 output.find("public static final int[] hey_dude={"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080080
Adam Lesinskice5e56e2016-10-21 17:56:45 -070081 EXPECT_NE(std::string::npos,
82 output.find("public static final int hey_dude_cool_attr=0;"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080083}
84
Adam Lesinski9e10ac72015-10-16 14:37:48 -070085TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070086 std::unique_ptr<ResourceTable> table =
87 test::ResourceTableBuilder()
88 .SetPackageId("android", 0x01)
89 .AddSimple("android:id/one", ResourceId(0x01020000))
90 .AddSimple("android:id/com.foo$two", ResourceId(0x01020001))
91 .Build();
Adam Lesinski9e10ac72015-10-16 14:37:48 -070092
Adam Lesinskice5e56e2016-10-21 17:56:45 -070093 std::unique_ptr<IAaptContext> context =
94 test::ContextBuilder()
95 .AddSymbolSource(
96 util::make_unique<ResourceTableSymbolSource>(table.get()))
97 .SetNameManglerPolicy(NameManglerPolicy{"android"})
98 .Build();
99 JavaClassGenerator generator(context.get(), table.get(), {});
100 std::stringstream out;
101 ASSERT_TRUE(generator.Generate("android", "com.android.internal", &out));
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700102
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700103 std::string output = out.str();
104 EXPECT_NE(std::string::npos, output.find("package com.android.internal;"));
105 EXPECT_NE(std::string::npos,
106 output.find("public static final int one=0x01020000;"));
107 EXPECT_EQ(std::string::npos, output.find("two"));
108 EXPECT_EQ(std::string::npos, output.find("com_foo$two"));
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700109}
110
111TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700112 std::unique_ptr<ResourceTable> table =
113 test::ResourceTableBuilder()
114 .SetPackageId("android", 0x01)
115 .AddSimple("android:attr/two", ResourceId(0x01010001))
116 .AddSimple("android:^attr-private/one", ResourceId(0x01010000))
117 .Build();
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700118
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700119 std::unique_ptr<IAaptContext> context =
120 test::ContextBuilder()
121 .AddSymbolSource(
122 util::make_unique<ResourceTableSymbolSource>(table.get()))
123 .SetNameManglerPolicy(NameManglerPolicy{"android"})
124 .Build();
125 JavaClassGenerator generator(context.get(), table.get(), {});
126 std::stringstream out;
127 ASSERT_TRUE(generator.Generate("android", &out));
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700128
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700129 std::string output = out.str();
130 EXPECT_NE(std::string::npos, output.find("public static final class attr"));
131 EXPECT_EQ(std::string::npos,
132 output.find("public static final class ^attr-private"));
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700133}
134
135TEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700136 StdErrDiagnostics diag;
137 std::unique_ptr<ResourceTable> table =
138 test::ResourceTableBuilder()
139 .SetPackageId("android", 0x01)
140 .AddSimple("android:id/one", ResourceId(0x01020000))
141 .AddSimple("android:id/two", ResourceId(0x01020001))
142 .AddSimple("android:id/three", ResourceId(0x01020002))
143 .SetSymbolState("android:id/one", ResourceId(0x01020000),
144 SymbolState::kPublic)
145 .SetSymbolState("android:id/two", ResourceId(0x01020001),
146 SymbolState::kPrivate)
147 .Build();
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700148
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700149 std::unique_ptr<IAaptContext> context =
150 test::ContextBuilder()
151 .AddSymbolSource(
152 util::make_unique<ResourceTableSymbolSource>(table.get()))
153 .SetNameManglerPolicy(NameManglerPolicy{"android"})
154 .Build();
Adam Lesinski76565542016-03-10 21:55:04 -0800155
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700156 JavaClassGeneratorOptions options;
157 options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
158 {
159 JavaClassGenerator generator(context.get(), table.get(), options);
160 std::stringstream out;
161 ASSERT_TRUE(generator.Generate("android", &out));
162 std::string output = out.str();
163 EXPECT_NE(std::string::npos,
164 output.find("public static final int one=0x01020000;"));
165 EXPECT_EQ(std::string::npos, output.find("two"));
166 EXPECT_EQ(std::string::npos, output.find("three"));
167 }
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700168
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700169 options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
170 {
171 JavaClassGenerator generator(context.get(), table.get(), options);
172 std::stringstream out;
173 ASSERT_TRUE(generator.Generate("android", &out));
174 std::string output = out.str();
175 EXPECT_NE(std::string::npos,
176 output.find("public static final int one=0x01020000;"));
177 EXPECT_NE(std::string::npos,
178 output.find("public static final int two=0x01020001;"));
179 EXPECT_EQ(std::string::npos, output.find("three"));
180 }
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700181
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700182 options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
183 {
184 JavaClassGenerator generator(context.get(), table.get(), options);
185 std::stringstream out;
186 ASSERT_TRUE(generator.Generate("android", &out));
187 std::string output = out.str();
188 EXPECT_NE(std::string::npos,
189 output.find("public static final int one=0x01020000;"));
190 EXPECT_NE(std::string::npos,
191 output.find("public static final int two=0x01020001;"));
192 EXPECT_NE(std::string::npos,
193 output.find("public static final int three=0x01020002;"));
194 }
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700195}
196
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700197/*
198 * TODO(adamlesinski): Re-enable this once we get merging working again.
199 * TEST(JavaClassGeneratorTest, EmitPackageMangledSymbols) {
Adam Lesinski769de982015-04-10 19:43:55 -0700200 ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kId, u"foo" },
201 ResourceId{ 0x01, 0x02, 0x0000 }));
202 ResourceTable table;
203 table.setPackage(u"com.lib");
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700204 ASSERT_TRUE(table.addResource(ResourceName{ {}, ResourceType::kId, u"test"
205}, {},
206 Source{ "lib.xml", 33 },
207util::make_unique<Id>()));
Adam Lesinski769de982015-04-10 19:43:55 -0700208 ASSERT_TRUE(mTable->merge(std::move(table)));
209
Adam Lesinski330edcd2015-05-04 17:40:56 -0700210 Linker linker(mTable,
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700211 std::make_shared<MockResolver>(mTable, std::map<ResourceName,
212ResourceId>()),
Adam Lesinski330edcd2015-05-04 17:40:56 -0700213 {});
Adam Lesinski769de982015-04-10 19:43:55 -0700214 ASSERT_TRUE(linker.linkAndValidate());
215
216 JavaClassGenerator generator(mTable, {});
217
218 std::stringstream out;
219 EXPECT_TRUE(generator.generate(mTable->getPackage(), out));
220 std::string output = out.str();
221 EXPECT_NE(std::string::npos, output.find("int foo ="));
222 EXPECT_EQ(std::string::npos, output.find("int test ="));
223
224 out.str("");
225 EXPECT_TRUE(generator.generate(u"com.lib", out));
226 output = out.str();
227 EXPECT_NE(std::string::npos, output.find("int test ="));
228 EXPECT_EQ(std::string::npos, output.find("int foo ="));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700229}*/
Adam Lesinski838a6872015-05-01 13:14:05 -0700230
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700231TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700232 std::unique_ptr<ResourceTable> table =
233 test::ResourceTableBuilder()
234 .SetPackageId("android", 0x01)
235 .SetPackageId("com.lib", 0x02)
236 .AddValue("android:attr/bar", ResourceId(0x01010000),
237 test::AttributeBuilder(false).Build())
238 .AddValue("com.lib:attr/bar", ResourceId(0x02010000),
239 test::AttributeBuilder(false).Build())
240 .AddValue("android:styleable/foo", ResourceId(0x01030000),
241 test::StyleableBuilder()
242 .AddItem("android:attr/bar", ResourceId(0x01010000))
243 .AddItem("com.lib:attr/bar", ResourceId(0x02010000))
244 .Build())
245 .Build();
Adam Lesinski838a6872015-05-01 13:14:05 -0700246
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700247 std::unique_ptr<IAaptContext> context =
248 test::ContextBuilder()
249 .AddSymbolSource(
250 util::make_unique<ResourceTableSymbolSource>(table.get()))
251 .SetNameManglerPolicy(NameManglerPolicy{"android"})
252 .Build();
253 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski838a6872015-05-01 13:14:05 -0700254
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700255 std::stringstream out;
256 EXPECT_TRUE(generator.Generate("android", &out));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700257
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700258 std::string output = out.str();
259 EXPECT_NE(std::string::npos, output.find("int foo_bar="));
260 EXPECT_NE(std::string::npos, output.find("int foo_com_lib_bar="));
Adam Lesinski838a6872015-05-01 13:14:05 -0700261}
Adam Lesinski769de982015-04-10 19:43:55 -0700262
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700263TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700264 std::unique_ptr<ResourceTable> table =
265 test::ResourceTableBuilder()
266 .SetPackageId("android", 0x01)
267 .AddSimple("android:id/foo", ResourceId(0x01010000))
268 .Build();
269 test::GetValue<Id>(table.get(), "android:id/foo")
270 ->SetComment(std::string("This is a comment\n@deprecated"));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700271
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700272 std::unique_ptr<IAaptContext> context =
273 test::ContextBuilder()
274 .AddSymbolSource(
275 util::make_unique<ResourceTableSymbolSource>(table.get()))
276 .SetNameManglerPolicy(NameManglerPolicy{"android"})
277 .Build();
278 JavaClassGenerator generator(context.get(), table.get(), {});
279 std::stringstream out;
280 ASSERT_TRUE(generator.Generate("android", &out));
281 std::string actual = out.str();
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700282
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700283 const char* expectedText =
284 R"EOF(/**
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700285 * This is a comment
286 * @deprecated
287 */
288 @Deprecated
Adam Lesinski803c7c82016-04-06 16:09:43 -0700289 public static final int foo=0x01010000;)EOF";
290
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700291 EXPECT_NE(std::string::npos, actual.find(expectedText));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700292}
293
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700294TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {}
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700295
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800296TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700297 Attribute attr(false);
298 attr.SetComment(StringPiece("This is an attribute"));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700299
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700300 Styleable styleable;
301 styleable.entries.push_back(
302 Reference(test::ParseNameOrDie("android:attr/one")));
303 styleable.SetComment(StringPiece("This is a styleable"));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700304
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700305 std::unique_ptr<ResourceTable> table =
306 test::ResourceTableBuilder()
307 .SetPackageId("android", 0x01)
308 .AddValue("android:attr/one", util::make_unique<Attribute>(attr))
309 .AddValue("android:styleable/Container",
310 std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
311 .Build();
Adam Lesinski74605cd2016-03-03 15:39:50 -0800312
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700313 std::unique_ptr<IAaptContext> context =
314 test::ContextBuilder()
315 .AddSymbolSource(
316 util::make_unique<ResourceTableSymbolSource>(table.get()))
317 .SetNameManglerPolicy(NameManglerPolicy{"android"})
318 .Build();
319 JavaClassGeneratorOptions options;
320 options.use_final = false;
321 JavaClassGenerator generator(context.get(), table.get(), options);
322 std::stringstream out;
323 ASSERT_TRUE(generator.Generate("android", &out));
324 std::string actual = out.str();
Adam Lesinski74605cd2016-03-03 15:39:50 -0800325
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700326 EXPECT_NE(std::string::npos, actual.find("attr name android:one"));
327 EXPECT_NE(std::string::npos, actual.find("attr description"));
328 EXPECT_NE(std::string::npos, actual.find(attr.GetComment().data()));
329 EXPECT_NE(std::string::npos, actual.find(styleable.GetComment().data()));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700330}
331
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100332TEST(JavaClassGeneratorTest, CommentsForRemovedAttributesAreNotPresentInClass) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700333 Attribute attr(false);
334 attr.SetComment(StringPiece("removed"));
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100335
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700336 std::unique_ptr<ResourceTable> table =
337 test::ResourceTableBuilder()
338 .SetPackageId("android", 0x01)
339 .AddValue("android:attr/one", util::make_unique<Attribute>(attr))
340 .Build();
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100341
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700342 std::unique_ptr<IAaptContext> context =
343 test::ContextBuilder()
344 .AddSymbolSource(
345 util::make_unique<ResourceTableSymbolSource>(table.get()))
346 .SetNameManglerPolicy(NameManglerPolicy{"android"})
347 .Build();
348 JavaClassGeneratorOptions options;
349 options.use_final = false;
350 JavaClassGenerator generator(context.get(), table.get(), options);
351 std::stringstream out;
352 ASSERT_TRUE(generator.Generate("android", &out));
353 std::string actual = out.str();
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100354
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700355 EXPECT_EQ(std::string::npos, actual.find("@attr name android:one"));
356 EXPECT_EQ(std::string::npos, actual.find("@attr description"));
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100357
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700358 // We should find @removed only in the attribute javadoc and not anywhere else
359 // (i.e. the class
360 // javadoc).
361 const size_t pos = actual.find("removed");
362 EXPECT_NE(std::string::npos, pos);
363 EXPECT_EQ(std::string::npos, actual.find("removed", pos + 1));
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100364}
365
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800366TEST(JavaClassGeneratorTest, GenerateOnResourcesLoadedCallbackForSharedLibrary) {
367 std::unique_ptr<ResourceTable> table =
368 test::ResourceTableBuilder()
369 .SetPackageId("android", 0x00)
370 .AddValue("android:attr/foo", ResourceId(0x00010000), util::make_unique<Attribute>(false))
371 .AddValue("android:id/foo", ResourceId(0x00020000), util::make_unique<Id>())
372 .AddValue(
373 "android:style/foo", ResourceId(0x00030000),
374 test::StyleBuilder()
375 .AddItem("android:attr/foo", ResourceId(0x00010000), util::make_unique<Id>())
376 .Build())
377 .Build();
378
379 std::unique_ptr<IAaptContext> context =
380 test::ContextBuilder().SetPackageId(0x00).SetCompilationPackage("android").Build();
381
382 JavaClassGeneratorOptions options;
383 options.use_final = false;
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800384 options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{
385 {"com.foo", "com.boo"},
386 };
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800387 JavaClassGenerator generator(context.get(), table.get(), options);
388
389 std::stringstream out;
390 ASSERT_TRUE(generator.Generate("android", &out));
391
392 std::string actual = out.str();
393
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800394 EXPECT_NE(std::string::npos, actual.find("void onResourcesLoaded"));
395 EXPECT_NE(std::string::npos, actual.find("com.foo.R.onResourcesLoaded"));
396 EXPECT_NE(std::string::npos, actual.find("com.boo.R.onResourcesLoaded"));
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800397}
398
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700399} // namespace aapt