blob: 4f51fc48c80e31915954aeb6c4e7d9590ae2f5c4 [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 <string>
20
Adam Lesinskia693c4a2017-11-09 11:29:39 -080021#include "io/StringStream.h"
Adam Lesinskice5e56e22016-10-21 17:56:45 -070022#include "test/Test.h"
23#include "util/Util.h"
24
Adam Lesinskia693c4a2017-11-09 11:29:39 -080025using ::aapt::io::StringOutputStream;
Adam Lesinski09f4d702017-08-08 10:39:55 -070026using ::android::StringPiece;
27using ::testing::HasSubstr;
Adam Lesinski761d4342017-09-29 11:15:17 -070028using ::testing::Lt;
29using ::testing::Ne;
Adam Lesinski09f4d702017-08-08 10:39:55 -070030using ::testing::Not;
Adam Lesinskid5083f62017-01-16 15:07:21 -080031
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080032namespace aapt {
33
Adam Lesinski1ab598f2015-08-14 14:26:04 -070034TEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) {
Adam Lesinskice5e56e22016-10-21 17:56:45 -070035 std::unique_ptr<ResourceTable> table =
36 test::ResourceTableBuilder()
37 .SetPackageId("android", 0x01)
38 .AddSimple("android:id/class", ResourceId(0x01020000))
39 .Build();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080040
Adam Lesinskice5e56e22016-10-21 17:56:45 -070041 std::unique_ptr<IAaptContext> context =
42 test::ContextBuilder()
43 .AddSymbolSource(
44 util::make_unique<ResourceTableSymbolSource>(table.get()))
45 .SetNameManglerPolicy(NameManglerPolicy{"android"})
46 .Build();
47 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080048
Adam Lesinskia693c4a2017-11-09 11:29:39 -080049 std::string result;
50 StringOutputStream out(&result);
Adam Lesinskice5e56e22016-10-21 17:56:45 -070051 EXPECT_FALSE(generator.Generate("android", &out));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080052}
53
Adam Lesinski1ab598f2015-08-14 14:26:04 -070054TEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
Adam Lesinskice5e56e22016-10-21 17:56:45 -070055 std::unique_ptr<ResourceTable> table =
56 test::ResourceTableBuilder()
57 .SetPackageId("android", 0x01)
58 .AddSimple("android:id/hey-man", ResourceId(0x01020000))
59 .AddValue("android:attr/cool.attr", ResourceId(0x01010000),
Adam Lesinski73bff1e2017-12-08 16:06:10 -080060 test::AttributeBuilder().Build())
Adam Lesinski09f4d702017-08-08 10:39:55 -070061 .AddValue("android:styleable/hey.dude", ResourceId(0x01030000),
62 test::StyleableBuilder()
63 .AddItem("android:attr/cool.attr", ResourceId(0x01010000))
64 .Build())
Adam Lesinskice5e56e22016-10-21 17:56:45 -070065 .Build();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080066
Adam Lesinskice5e56e22016-10-21 17:56:45 -070067 std::unique_ptr<IAaptContext> context =
68 test::ContextBuilder()
Adam Lesinski09f4d702017-08-08 10:39:55 -070069 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
Adam Lesinskice5e56e22016-10-21 17:56:45 -070070 .SetNameManglerPolicy(NameManglerPolicy{"android"})
71 .Build();
72 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080073
Adam Lesinskia693c4a2017-11-09 11:29:39 -080074 std::string output;
75 StringOutputStream out(&output);
Adam Lesinskice5e56e22016-10-21 17:56:45 -070076 EXPECT_TRUE(generator.Generate("android", &out));
Adam Lesinskia693c4a2017-11-09 11:29:39 -080077 out.Flush();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080078
Adam Lesinski09f4d702017-08-08 10:39:55 -070079 EXPECT_THAT(output, HasSubstr("public static final int hey_man=0x01020000;"));
80 EXPECT_THAT(output, HasSubstr("public static final int[] hey_dude={"));
81 EXPECT_THAT(output, HasSubstr("public static final int hey_dude_cool_attr=0;"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080082}
83
Adam Lesinski9e10ac72015-10-16 14:37:48 -070084TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
Adam Lesinskice5e56e22016-10-21 17:56:45 -070085 std::unique_ptr<ResourceTable> table =
86 test::ResourceTableBuilder()
87 .SetPackageId("android", 0x01)
88 .AddSimple("android:id/one", ResourceId(0x01020000))
89 .AddSimple("android:id/com.foo$two", ResourceId(0x01020001))
90 .Build();
Adam Lesinski9e10ac72015-10-16 14:37:48 -070091
Adam Lesinskice5e56e22016-10-21 17:56:45 -070092 std::unique_ptr<IAaptContext> context =
93 test::ContextBuilder()
Adam Lesinski09f4d702017-08-08 10:39:55 -070094 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
Adam Lesinskice5e56e22016-10-21 17:56:45 -070095 .SetNameManglerPolicy(NameManglerPolicy{"android"})
96 .Build();
97 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski9e10ac72015-10-16 14:37:48 -070098
Adam Lesinskia693c4a2017-11-09 11:29:39 -080099 std::string output;
100 StringOutputStream out(&output);
101 ASSERT_TRUE(generator.Generate("android", "com.android.internal", &out));
102 out.Flush();
103
Adam Lesinski09f4d702017-08-08 10:39:55 -0700104 EXPECT_THAT(output, HasSubstr("package com.android.internal;"));
105 EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
106 EXPECT_THAT(output, Not(HasSubstr("two")));
107 EXPECT_THAT(output, Not(HasSubstr("com_foo$two")));
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700108}
109
Ryan Mitchell23cc5d52018-07-12 17:16:40 -0700110TEST(JavaClassGeneratorTest, StyleableAttributesWithDifferentPackageName) {
111 std::unique_ptr<ResourceTable> table =
112 test::ResourceTableBuilder()
113 .SetPackageId("android", 0x01)
114 .SetPackageId("app", 0x7f)
115 .AddValue("app:attr/foo", ResourceId(0x7f010000),
116 test::AttributeBuilder().Build())
117 .AddValue("app:attr/bar", ResourceId(0x7f010001),
118 test::AttributeBuilder().Build())
119 .AddValue("android:attr/baz", ResourceId(0x01010000),
120 test::AttributeBuilder().Build())
121 .AddValue("app:styleable/MyStyleable", ResourceId(0x7f030000),
122 test::StyleableBuilder()
123 .AddItem("app:attr/foo", ResourceId(0x7f010000))
124 .AddItem("attr/bar", ResourceId(0x7f010001))
125 .AddItem("android:attr/baz", ResourceId(0x01010000))
126 .Build())
127 .Build();
128
129 std::unique_ptr<IAaptContext> context =
130 test::ContextBuilder()
131 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
132 .SetNameManglerPolicy(NameManglerPolicy{"custom"})
133 .SetCompilationPackage("custom")
134 .Build();
135 JavaClassGenerator generator(context.get(), table.get(), {});
136
137 std::string output;
138 StringOutputStream out(&output);
139 EXPECT_TRUE(generator.Generate("app", &out));
140 out.Flush();
141
142 EXPECT_THAT(output, Not(HasSubstr("public static final int baz=0x01010000;")));
143 EXPECT_THAT(output, HasSubstr("public static final int foo=0x7f010000;"));
144 EXPECT_THAT(output, HasSubstr("public static final int bar=0x7f010001;"));
145
146 EXPECT_THAT(output, HasSubstr("public static final int MyStyleable_android_baz=0;"));
147 EXPECT_THAT(output, HasSubstr("public static final int MyStyleable_foo=1;"));
148 EXPECT_THAT(output, HasSubstr("public static final int MyStyleable_bar=2;"));
149
150 EXPECT_THAT(output, HasSubstr("@link #MyStyleable_android_baz android:baz"));
151 EXPECT_THAT(output, HasSubstr("@link #MyStyleable_foo app:foo"));
152 EXPECT_THAT(output, HasSubstr("@link #MyStyleable_bar app:bar"));
153
154 EXPECT_THAT(output, HasSubstr("@link android.R.attr#baz"));
155 EXPECT_THAT(output, HasSubstr("@link app.R.attr#foo"));
156 EXPECT_THAT(output, HasSubstr("@link app.R.attr#bar"));
157}
158
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700159TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700160 std::unique_ptr<ResourceTable> table =
161 test::ResourceTableBuilder()
162 .SetPackageId("android", 0x01)
163 .AddSimple("android:attr/two", ResourceId(0x01010001))
164 .AddSimple("android:^attr-private/one", ResourceId(0x01010000))
165 .Build();
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700166
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700167 std::unique_ptr<IAaptContext> context =
168 test::ContextBuilder()
Adam Lesinski09f4d702017-08-08 10:39:55 -0700169 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700170 .SetNameManglerPolicy(NameManglerPolicy{"android"})
171 .Build();
172 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700173
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800174 std::string output;
175 StringOutputStream out(&output);
176 ASSERT_TRUE(generator.Generate("android", &out));
177 out.Flush();
178
Adam Lesinski09f4d702017-08-08 10:39:55 -0700179 EXPECT_THAT(output, HasSubstr("public static final class attr"));
180 EXPECT_THAT(output, Not(HasSubstr("public static final class ^attr-private")));
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700181}
182
183TEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700184 StdErrDiagnostics diag;
185 std::unique_ptr<ResourceTable> table =
186 test::ResourceTableBuilder()
187 .SetPackageId("android", 0x01)
188 .AddSimple("android:id/one", ResourceId(0x01020000))
189 .AddSimple("android:id/two", ResourceId(0x01020001))
190 .AddSimple("android:id/three", ResourceId(0x01020002))
Adam Lesinski71be7052017-12-12 16:48:07 -0800191 .SetSymbolState("android:id/one", ResourceId(0x01020000), Visibility::Level::kPublic)
192 .SetSymbolState("android:id/two", ResourceId(0x01020001), Visibility::Level::kPrivate)
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700193 .Build();
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700194
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700195 std::unique_ptr<IAaptContext> context =
196 test::ContextBuilder()
Adam Lesinski09f4d702017-08-08 10:39:55 -0700197 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700198 .SetNameManglerPolicy(NameManglerPolicy{"android"})
199 .Build();
Adam Lesinski76565542016-03-10 21:55:04 -0800200
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700201 JavaClassGeneratorOptions options;
202 options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
203 {
204 JavaClassGenerator generator(context.get(), table.get(), options);
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800205 std::string output;
206 StringOutputStream out(&output);
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700207 ASSERT_TRUE(generator.Generate("android", &out));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800208 out.Flush();
209
Adam Lesinski09f4d702017-08-08 10:39:55 -0700210 EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
211 EXPECT_THAT(output, Not(HasSubstr("two")));
212 EXPECT_THAT(output, Not(HasSubstr("three")));
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700213 }
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700214
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700215 options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
216 {
217 JavaClassGenerator generator(context.get(), table.get(), options);
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800218 std::string output;
219 StringOutputStream out(&output);
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700220 ASSERT_TRUE(generator.Generate("android", &out));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800221 out.Flush();
222
Adam Lesinski09f4d702017-08-08 10:39:55 -0700223 EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
224 EXPECT_THAT(output, HasSubstr("public static final int two=0x01020001;"));
225 EXPECT_THAT(output, Not(HasSubstr("three")));
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700226 }
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700227
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700228 options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
229 {
230 JavaClassGenerator generator(context.get(), table.get(), options);
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800231 std::string output;
232 StringOutputStream out(&output);
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700233 ASSERT_TRUE(generator.Generate("android", &out));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800234 out.Flush();
235
Adam Lesinski09f4d702017-08-08 10:39:55 -0700236 EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
237 EXPECT_THAT(output, HasSubstr("public static final int two=0x01020001;"));
238 EXPECT_THAT(output, HasSubstr("public static final int three=0x01020002;"));
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700239 }
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700240}
241
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700242/*
243 * TODO(adamlesinski): Re-enable this once we get merging working again.
244 * TEST(JavaClassGeneratorTest, EmitPackageMangledSymbols) {
Adam Lesinski769de982015-04-10 19:43:55 -0700245 ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kId, u"foo" },
246 ResourceId{ 0x01, 0x02, 0x0000 }));
247 ResourceTable table;
248 table.setPackage(u"com.lib");
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700249 ASSERT_TRUE(table.addResource(ResourceName{ {}, ResourceType::kId, u"test"
250}, {},
251 Source{ "lib.xml", 33 },
252util::make_unique<Id>()));
Adam Lesinski769de982015-04-10 19:43:55 -0700253 ASSERT_TRUE(mTable->merge(std::move(table)));
254
Adam Lesinski330edcd2015-05-04 17:40:56 -0700255 Linker linker(mTable,
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700256 std::make_shared<MockResolver>(mTable, std::map<ResourceName,
257ResourceId>()),
Adam Lesinski330edcd2015-05-04 17:40:56 -0700258 {});
Adam Lesinski769de982015-04-10 19:43:55 -0700259 ASSERT_TRUE(linker.linkAndValidate());
260
261 JavaClassGenerator generator(mTable, {});
262
263 std::stringstream out;
264 EXPECT_TRUE(generator.generate(mTable->getPackage(), out));
265 std::string output = out.str();
266 EXPECT_NE(std::string::npos, output.find("int foo ="));
267 EXPECT_EQ(std::string::npos, output.find("int test ="));
268
269 out.str("");
270 EXPECT_TRUE(generator.generate(u"com.lib", out));
271 output = out.str();
272 EXPECT_NE(std::string::npos, output.find("int test ="));
273 EXPECT_EQ(std::string::npos, output.find("int foo ="));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700274}*/
Adam Lesinski838a6872015-05-01 13:14:05 -0700275
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700276TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700277 std::unique_ptr<ResourceTable> table =
278 test::ResourceTableBuilder()
279 .SetPackageId("android", 0x01)
280 .SetPackageId("com.lib", 0x02)
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800281 .AddValue("android:attr/bar", ResourceId(0x01010000), test::AttributeBuilder().Build())
282 .AddValue("com.lib:attr/bar", ResourceId(0x02010000), test::AttributeBuilder().Build())
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700283 .AddValue("android:styleable/foo", ResourceId(0x01030000),
284 test::StyleableBuilder()
285 .AddItem("android:attr/bar", ResourceId(0x01010000))
286 .AddItem("com.lib:attr/bar", ResourceId(0x02010000))
287 .Build())
288 .Build();
Adam Lesinski838a6872015-05-01 13:14:05 -0700289
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700290 std::unique_ptr<IAaptContext> context =
291 test::ContextBuilder()
Adam Lesinski09f4d702017-08-08 10:39:55 -0700292 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700293 .SetNameManglerPolicy(NameManglerPolicy{"android"})
294 .Build();
295 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski838a6872015-05-01 13:14:05 -0700296
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800297 std::string output;
298 StringOutputStream out(&output);
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700299 EXPECT_TRUE(generator.Generate("android", &out));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800300 out.Flush();
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700301
Adam Lesinski09f4d702017-08-08 10:39:55 -0700302 EXPECT_THAT(output, HasSubstr("int foo_bar="));
303 EXPECT_THAT(output, HasSubstr("int foo_com_lib_bar="));
Adam Lesinski838a6872015-05-01 13:14:05 -0700304}
Adam Lesinski769de982015-04-10 19:43:55 -0700305
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700306TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700307 std::unique_ptr<ResourceTable> table =
308 test::ResourceTableBuilder()
309 .SetPackageId("android", 0x01)
310 .AddSimple("android:id/foo", ResourceId(0x01010000))
311 .Build();
312 test::GetValue<Id>(table.get(), "android:id/foo")
313 ->SetComment(std::string("This is a comment\n@deprecated"));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700314
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700315 std::unique_ptr<IAaptContext> context =
316 test::ContextBuilder()
Adam Lesinski09f4d702017-08-08 10:39:55 -0700317 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700318 .SetNameManglerPolicy(NameManglerPolicy{"android"})
319 .Build();
320 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800321
322 std::string output;
323 StringOutputStream out(&output);
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700324 ASSERT_TRUE(generator.Generate("android", &out));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800325 out.Flush();
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700326
Adam Lesinski09f4d702017-08-08 10:39:55 -0700327 const char* expected_text =
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700328 R"EOF(/**
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700329 * This is a comment
330 * @deprecated
331 */
332 @Deprecated
Adam Lesinski803c7c82016-04-06 16:09:43 -0700333 public static final int foo=0x01010000;)EOF";
Adam Lesinski09f4d702017-08-08 10:39:55 -0700334 EXPECT_THAT(output, HasSubstr(expected_text));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700335}
336
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700337TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {}
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700338
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800339TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) {
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800340 Attribute attr;
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700341 attr.SetComment(StringPiece("This is an attribute"));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700342
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700343 Styleable styleable;
Adam Lesinski09f4d702017-08-08 10:39:55 -0700344 styleable.entries.push_back(Reference(test::ParseNameOrDie("android:attr/one")));
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700345 styleable.SetComment(StringPiece("This is a styleable"));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700346
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700347 std::unique_ptr<ResourceTable> table =
348 test::ResourceTableBuilder()
349 .SetPackageId("android", 0x01)
350 .AddValue("android:attr/one", util::make_unique<Attribute>(attr))
351 .AddValue("android:styleable/Container",
352 std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
353 .Build();
Adam Lesinski74605cd2016-03-03 15:39:50 -0800354
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700355 std::unique_ptr<IAaptContext> context =
356 test::ContextBuilder()
Adam Lesinski09f4d702017-08-08 10:39:55 -0700357 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700358 .SetNameManglerPolicy(NameManglerPolicy{"android"})
359 .Build();
360 JavaClassGeneratorOptions options;
361 options.use_final = false;
362 JavaClassGenerator generator(context.get(), table.get(), options);
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800363
364 std::string output;
365 StringOutputStream out(&output);
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700366 ASSERT_TRUE(generator.Generate("android", &out));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800367 out.Flush();
Adam Lesinski74605cd2016-03-03 15:39:50 -0800368
Ryan Mitchellbe8607d2018-12-03 11:28:42 -0800369 EXPECT_THAT(output, HasSubstr("#Container_one android:one"));
370 EXPECT_THAT(output, HasSubstr("@see #Container_one"));
371 EXPECT_THAT(output, HasSubstr("attr name android:one"));
372 EXPECT_THAT(output, HasSubstr("attr description"));
373 EXPECT_THAT(output, HasSubstr(attr.GetComment()));
374 EXPECT_THAT(output, HasSubstr(styleable.GetComment()));
375}
376
377TEST(JavaClassGeneratorTest, CommentsForStyleableHiddenAttributesAreNotPresent) {
378 Attribute attr;
379 attr.SetComment(StringPiece("This is an attribute @hide"));
380
381 Styleable styleable;
382 styleable.entries.push_back(Reference(test::ParseNameOrDie("android:attr/one")));
383 styleable.SetComment(StringPiece("This is a styleable"));
384
385 std::unique_ptr<ResourceTable> table =
386 test::ResourceTableBuilder()
387 .SetPackageId("android", 0x01)
388 .AddValue("android:attr/one", util::make_unique<Attribute>(attr))
389 .AddValue("android:styleable/Container",
390 std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
391 .Build();
392
393 std::unique_ptr<IAaptContext> context =
394 test::ContextBuilder()
395 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
396 .SetNameManglerPolicy(NameManglerPolicy{"android"})
397 .Build();
398 JavaClassGeneratorOptions options;
399 options.use_final = false;
400 JavaClassGenerator generator(context.get(), table.get(), options);
401
402 std::string output;
403 StringOutputStream out(&output);
404 ASSERT_TRUE(generator.Generate("android", &out));
405 out.Flush();
406
407 EXPECT_THAT(output, Not(HasSubstr("#Container_one android:one")));
408 EXPECT_THAT(output, Not(HasSubstr("@see #Container_one")));
Adam Lesinski09f4d702017-08-08 10:39:55 -0700409 EXPECT_THAT(output, HasSubstr("attr name android:one"));
410 EXPECT_THAT(output, HasSubstr("attr description"));
411 EXPECT_THAT(output, HasSubstr(attr.GetComment()));
412 EXPECT_THAT(output, HasSubstr(styleable.GetComment()));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700413}
414
Adam Lesinski761d4342017-09-29 11:15:17 -0700415TEST(JavaClassGeneratorTest, StyleableAndIndicesAreColocated) {
416 std::unique_ptr<ResourceTable> table =
417 test::ResourceTableBuilder()
418 .SetPackageId("android", 0x01)
419 .AddValue("android:attr/layout_gravity", util::make_unique<Attribute>())
420 .AddValue("android:attr/background", util::make_unique<Attribute>())
421 .AddValue("android:styleable/ActionBar",
422 test::StyleableBuilder()
423 .AddItem("android:attr/background", ResourceId(0x01010000))
424 .Build())
425 .AddValue("android:styleable/ActionBar.LayoutParams",
426 test::StyleableBuilder()
427 .AddItem("android:attr/layout_gravity", ResourceId(0x01010001))
428 .Build())
429 .Build();
430
431 std::unique_ptr<IAaptContext> context =
432 test::ContextBuilder()
433 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
434 .SetNameManglerPolicy(NameManglerPolicy{"android"})
435 .Build();
436
437 JavaClassGeneratorOptions options;
438 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800439
440 std::string output;
441 StringOutputStream out(&output);
Adam Lesinski761d4342017-09-29 11:15:17 -0700442 ASSERT_TRUE(generator.Generate("android", &out));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800443 out.Flush();
Adam Lesinski761d4342017-09-29 11:15:17 -0700444
445 std::string::size_type actionbar_pos = output.find("int[] ActionBar");
446 ASSERT_THAT(actionbar_pos, Ne(std::string::npos));
447
448 std::string::size_type actionbar_background_pos = output.find("int ActionBar_background");
449 ASSERT_THAT(actionbar_background_pos, Ne(std::string::npos));
450
451 std::string::size_type actionbar_layout_params_pos = output.find("int[] ActionBar_LayoutParams");
452 ASSERT_THAT(actionbar_layout_params_pos, Ne(std::string::npos));
453
454 std::string::size_type actionbar_layout_params_layout_gravity_pos =
455 output.find("int ActionBar_LayoutParams_layout_gravity");
456 ASSERT_THAT(actionbar_layout_params_layout_gravity_pos, Ne(std::string::npos));
457
458 EXPECT_THAT(actionbar_pos, Lt(actionbar_background_pos));
459 EXPECT_THAT(actionbar_pos, Lt(actionbar_layout_params_pos));
460 EXPECT_THAT(actionbar_background_pos, Lt(actionbar_layout_params_pos));
461 EXPECT_THAT(actionbar_layout_params_pos, Lt(actionbar_layout_params_layout_gravity_pos));
462}
463
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100464TEST(JavaClassGeneratorTest, CommentsForRemovedAttributesAreNotPresentInClass) {
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800465 Attribute attr;
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700466 attr.SetComment(StringPiece("removed"));
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100467
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700468 std::unique_ptr<ResourceTable> table =
469 test::ResourceTableBuilder()
470 .SetPackageId("android", 0x01)
471 .AddValue("android:attr/one", util::make_unique<Attribute>(attr))
472 .Build();
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100473
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700474 std::unique_ptr<IAaptContext> context =
475 test::ContextBuilder()
Adam Lesinski09f4d702017-08-08 10:39:55 -0700476 .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700477 .SetNameManglerPolicy(NameManglerPolicy{"android"})
478 .Build();
479 JavaClassGeneratorOptions options;
480 options.use_final = false;
481 JavaClassGenerator generator(context.get(), table.get(), options);
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800482
483 std::string output;
484 StringOutputStream out(&output);
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700485 ASSERT_TRUE(generator.Generate("android", &out));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800486 out.Flush();
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100487
Adam Lesinski09f4d702017-08-08 10:39:55 -0700488 EXPECT_THAT(output, Not(HasSubstr("@attr name android:one")));
489 EXPECT_THAT(output, Not(HasSubstr("@attr description")));
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100490
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700491 // We should find @removed only in the attribute javadoc and not anywhere else
Adam Lesinski09f4d702017-08-08 10:39:55 -0700492 // (i.e. the class javadoc).
493 const std::string kRemoved("removed");
494 ASSERT_THAT(output, HasSubstr(kRemoved));
495 std::string after_first_match = output.substr(output.find(kRemoved) + kRemoved.size());
496 EXPECT_THAT(after_first_match, Not(HasSubstr(kRemoved)));
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100497}
498
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800499TEST(JavaClassGeneratorTest, GenerateOnResourcesLoadedCallbackForSharedLibrary) {
500 std::unique_ptr<ResourceTable> table =
501 test::ResourceTableBuilder()
502 .SetPackageId("android", 0x00)
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800503 .AddValue("android:attr/foo", ResourceId(0x00010000), util::make_unique<Attribute>())
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800504 .AddValue("android:id/foo", ResourceId(0x00020000), util::make_unique<Id>())
505 .AddValue(
506 "android:style/foo", ResourceId(0x00030000),
507 test::StyleBuilder()
508 .AddItem("android:attr/foo", ResourceId(0x00010000), util::make_unique<Id>())
509 .Build())
510 .Build();
511
512 std::unique_ptr<IAaptContext> context =
513 test::ContextBuilder().SetPackageId(0x00).SetCompilationPackage("android").Build();
514
515 JavaClassGeneratorOptions options;
516 options.use_final = false;
Adam Lesinski09f4d702017-08-08 10:39:55 -0700517 options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{{"com.foo", "com.boo"}};
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800518 JavaClassGenerator generator(context.get(), table.get(), options);
519
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800520 std::string output;
521 StringOutputStream out(&output);
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800522 ASSERT_TRUE(generator.Generate("android", &out));
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800523 out.Flush();
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800524
Adam Lesinski09f4d702017-08-08 10:39:55 -0700525 EXPECT_THAT(output, HasSubstr("void onResourcesLoaded"));
526 EXPECT_THAT(output, HasSubstr("com.foo.R.onResourcesLoaded"));
527 EXPECT_THAT(output, HasSubstr("com.boo.R.onResourcesLoaded"));
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800528}
529
Todd Kennedy949b62532018-03-02 14:19:45 -0800530TEST(JavaClassGeneratorTest, OnlyGenerateRText) {
531 std::unique_ptr<ResourceTable> table =
532 test::ResourceTableBuilder()
533 .SetPackageId("android", 0x01)
534 .AddValue("android:attr/foo", ResourceId(0x01010000), util::make_unique<Attribute>())
535 .AddValue("android:styleable/hey.dude", ResourceId(0x01020000),
536 test::StyleableBuilder()
537 .AddItem("android:attr/foo", ResourceId(0x01010000))
538 .Build())
539 .Build();
540
541 std::unique_ptr<IAaptContext> context =
542 test::ContextBuilder().SetPackageId(0x01).SetCompilationPackage("android").Build();
543 JavaClassGenerator generator(context.get(), table.get(), {});
544
545 ASSERT_TRUE(generator.Generate("android", nullptr));
546}
547
Adam Lesinskice5e56e22016-10-21 17:56:45 -0700548} // namespace aapt