blob: 46266b3f3e89fc2e1a735d1e598beeb969942548 [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 Lesinski76565542016-03-10 21:55:04 -080018#include "test/Test.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070019#include "util/Util.h"
20
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080021#include <sstream>
22#include <string>
23
24namespace aapt {
25
Adam Lesinski1ab598f2015-08-14 14:26:04 -070026TEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) {
27 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
28 .setPackageId(u"android", 0x01)
29 .addSimple(u"@android:id/class", ResourceId(0x01020000))
30 .build();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080031
Adam Lesinski76565542016-03-10 21:55:04 -080032 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
33 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
34 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
35 .build();
36 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080037
38 std::stringstream out;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070039 EXPECT_FALSE(generator.generate(u"android", &out));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080040}
41
Adam Lesinski1ab598f2015-08-14 14:26:04 -070042TEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
43 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
44 .setPackageId(u"android", 0x01)
45 .addSimple(u"@android:id/hey-man", ResourceId(0x01020000))
Adam Lesinski626b3db2016-04-07 13:24:59 -070046 .addValue(u"@android:attr/cool.attr", ResourceId(0x01010000),
47 test::AttributeBuilder(false).build())
Adam Lesinski1ab598f2015-08-14 14:26:04 -070048 .addValue(u"@android:styleable/hey.dude", ResourceId(0x01030000),
49 test::StyleableBuilder()
50 .addItem(u"@android:attr/cool.attr", ResourceId(0x01010000))
51 .build())
52 .build();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080053
Adam Lesinski76565542016-03-10 21:55:04 -080054 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
55 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
56 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
57 .build();
58 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080059
60 std::stringstream out;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070061 EXPECT_TRUE(generator.generate(u"android", &out));
62
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080063 std::string output = out.str();
64
65 EXPECT_NE(std::string::npos,
Adam Lesinskib274e352015-11-06 15:14:35 -080066 output.find("public static final int hey_man=0x01020000;"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080067
68 EXPECT_NE(std::string::npos,
Adam Lesinskib274e352015-11-06 15:14:35 -080069 output.find("public static final int[] hey_dude={"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080070
71 EXPECT_NE(std::string::npos,
Adam Lesinskib274e352015-11-06 15:14:35 -080072 output.find("public static final int hey_dude_cool_attr=0;"));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080073}
74
Adam Lesinski9e10ac72015-10-16 14:37:48 -070075TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
76 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
77 .setPackageId(u"android", 0x01)
78 .addSimple(u"@android:id/one", ResourceId(0x01020000))
79 .addSimple(u"@android:id/com.foo$two", ResourceId(0x01020001))
80 .build();
81
Adam Lesinski76565542016-03-10 21:55:04 -080082 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
83 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
84 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
85 .build();
86 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski9e10ac72015-10-16 14:37:48 -070087 std::stringstream out;
88 ASSERT_TRUE(generator.generate(u"android", u"com.android.internal", &out));
89
90 std::string output = out.str();
91 EXPECT_NE(std::string::npos, output.find("package com.android.internal;"));
Adam Lesinskib274e352015-11-06 15:14:35 -080092 EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
Adam Lesinski9e10ac72015-10-16 14:37:48 -070093 EXPECT_EQ(std::string::npos, output.find("two"));
94 EXPECT_EQ(std::string::npos, output.find("com_foo$two"));
95}
96
97TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
98 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
99 .setPackageId(u"android", 0x01)
Adam Lesinskib274e352015-11-06 15:14:35 -0800100 .addSimple(u"@android:attr/two", ResourceId(0x01010001))
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700101 .addSimple(u"@android:^attr-private/one", ResourceId(0x01010000))
102 .build();
103
Adam Lesinski76565542016-03-10 21:55:04 -0800104 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
105 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
106 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
107 .build();
108 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700109 std::stringstream out;
110 ASSERT_TRUE(generator.generate(u"android", &out));
111
112 std::string output = out.str();
113 EXPECT_NE(std::string::npos, output.find("public static final class attr"));
114 EXPECT_EQ(std::string::npos, output.find("public static final class ^attr-private"));
115}
116
117TEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
118 StdErrDiagnostics diag;
119 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
120 .setPackageId(u"android", 0x01)
121 .addSimple(u"@android:id/one", ResourceId(0x01020000))
122 .addSimple(u"@android:id/two", ResourceId(0x01020001))
123 .addSimple(u"@android:id/three", ResourceId(0x01020002))
Adam Lesinskie78fd612015-10-22 12:48:43 -0700124 .setSymbolState(u"@android:id/one", ResourceId(0x01020000), SymbolState::kPublic)
125 .setSymbolState(u"@android:id/two", ResourceId(0x01020001), SymbolState::kPrivate)
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700126 .build();
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700127
Adam Lesinski76565542016-03-10 21:55:04 -0800128 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
129 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
130 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
131 .build();
132
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700133 JavaClassGeneratorOptions options;
134 options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
135 {
Adam Lesinski76565542016-03-10 21:55:04 -0800136 JavaClassGenerator generator(context.get(), table.get(), options);
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700137 std::stringstream out;
138 ASSERT_TRUE(generator.generate(u"android", &out));
139 std::string output = out.str();
Adam Lesinskib274e352015-11-06 15:14:35 -0800140 EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700141 EXPECT_EQ(std::string::npos, output.find("two"));
142 EXPECT_EQ(std::string::npos, output.find("three"));
143 }
144
145 options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
146 {
Adam Lesinski76565542016-03-10 21:55:04 -0800147 JavaClassGenerator generator(context.get(), table.get(), options);
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700148 std::stringstream out;
149 ASSERT_TRUE(generator.generate(u"android", &out));
150 std::string output = out.str();
Adam Lesinskib274e352015-11-06 15:14:35 -0800151 EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
152 EXPECT_NE(std::string::npos, output.find("public static final int two=0x01020001;"));
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700153 EXPECT_EQ(std::string::npos, output.find("three"));
154 }
155
156 options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
157 {
Adam Lesinski76565542016-03-10 21:55:04 -0800158 JavaClassGenerator generator(context.get(), table.get(), options);
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700159 std::stringstream out;
160 ASSERT_TRUE(generator.generate(u"android", &out));
161 std::string output = out.str();
Adam Lesinskib274e352015-11-06 15:14:35 -0800162 EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
163 EXPECT_NE(std::string::npos, output.find("public static final int two=0x01020001;"));
164 EXPECT_NE(std::string::npos, output.find("public static final int three=0x01020002;"));
Adam Lesinski9e10ac72015-10-16 14:37:48 -0700165 }
166}
167
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700168/*
169 * TODO(adamlesinski): Re-enable this once we get merging working again.
170 * TEST(JavaClassGeneratorTest, EmitPackageMangledSymbols) {
Adam Lesinski769de982015-04-10 19:43:55 -0700171 ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kId, u"foo" },
172 ResourceId{ 0x01, 0x02, 0x0000 }));
173 ResourceTable table;
174 table.setPackage(u"com.lib");
175 ASSERT_TRUE(table.addResource(ResourceName{ {}, ResourceType::kId, u"test" }, {},
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700176 Source{ "lib.xml", 33 }, util::make_unique<Id>()));
Adam Lesinski769de982015-04-10 19:43:55 -0700177 ASSERT_TRUE(mTable->merge(std::move(table)));
178
Adam Lesinski330edcd2015-05-04 17:40:56 -0700179 Linker linker(mTable,
180 std::make_shared<MockResolver>(mTable, std::map<ResourceName, ResourceId>()),
181 {});
Adam Lesinski769de982015-04-10 19:43:55 -0700182 ASSERT_TRUE(linker.linkAndValidate());
183
184 JavaClassGenerator generator(mTable, {});
185
186 std::stringstream out;
187 EXPECT_TRUE(generator.generate(mTable->getPackage(), out));
188 std::string output = out.str();
189 EXPECT_NE(std::string::npos, output.find("int foo ="));
190 EXPECT_EQ(std::string::npos, output.find("int test ="));
191
192 out.str("");
193 EXPECT_TRUE(generator.generate(u"com.lib", out));
194 output = out.str();
195 EXPECT_NE(std::string::npos, output.find("int test ="));
196 EXPECT_EQ(std::string::npos, output.find("int foo ="));
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700197}*/
Adam Lesinski838a6872015-05-01 13:14:05 -0700198
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700199TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
200 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
201 .setPackageId(u"android", 0x01)
202 .setPackageId(u"com.lib", 0x02)
Adam Lesinski626b3db2016-04-07 13:24:59 -0700203 .addValue(u"@android:attr/bar", ResourceId(0x01010000),
204 test::AttributeBuilder(false).build())
205 .addValue(u"@com.lib:attr/bar", ResourceId(0x02010000),
206 test::AttributeBuilder(false).build())
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700207 .addValue(u"@android:styleable/foo", ResourceId(0x01030000),
208 test::StyleableBuilder()
209 .addItem(u"@android:attr/bar", ResourceId(0x01010000))
210 .addItem(u"@com.lib:attr/bar", ResourceId(0x02010000))
211 .build())
212 .build();
Adam Lesinski838a6872015-05-01 13:14:05 -0700213
Adam Lesinski76565542016-03-10 21:55:04 -0800214 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
215 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
216 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
217 .build();
218 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski838a6872015-05-01 13:14:05 -0700219
220 std::stringstream out;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700221 EXPECT_TRUE(generator.generate(u"android", &out));
222
Adam Lesinski838a6872015-05-01 13:14:05 -0700223 std::string output = out.str();
Adam Lesinskib274e352015-11-06 15:14:35 -0800224 EXPECT_NE(std::string::npos, output.find("int foo_bar="));
225 EXPECT_NE(std::string::npos, output.find("int foo_com_lib_bar="));
Adam Lesinski838a6872015-05-01 13:14:05 -0700226}
Adam Lesinski769de982015-04-10 19:43:55 -0700227
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700228TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
229 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
230 .setPackageId(u"android", 0x01)
231 .addSimple(u"@android:id/foo", ResourceId(0x01010000))
232 .build();
233 test::getValue<Id>(table.get(), u"@android:id/foo")
234 ->setComment(std::u16string(u"This is a comment\n@deprecated"));
235
Adam Lesinski76565542016-03-10 21:55:04 -0800236 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
237 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
238 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
239 .build();
240 JavaClassGenerator generator(context.get(), table.get(), {});
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700241 std::stringstream out;
242 ASSERT_TRUE(generator.generate(u"android", &out));
243 std::string actual = out.str();
244
Adam Lesinski803c7c82016-04-06 16:09:43 -0700245 const char* expectedText =
246R"EOF(/**
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700247 * This is a comment
248 * @deprecated
249 */
250 @Deprecated
Adam Lesinski803c7c82016-04-06 16:09:43 -0700251 public static final int foo=0x01010000;)EOF";
252
253 EXPECT_NE(std::string::npos, actual.find(expectedText));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700254}
255
256TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {
257
258}
259
260TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) {
Adam Lesinski74605cd2016-03-03 15:39:50 -0800261 Attribute attr(false);
262 attr.setComment(StringPiece16(u"This is an attribute"));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700263
Adam Lesinski74605cd2016-03-03 15:39:50 -0800264 Styleable styleable;
265 styleable.entries.push_back(Reference(test::parseNameOrDie(u"@android:attr/one")));
266 styleable.setComment(StringPiece16(u"This is a styleable"));
267
268 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
269 .setPackageId(u"android", 0x01)
270 .addValue(u"@android:attr/one", util::make_unique<Attribute>(attr))
271 .addValue(u"@android:styleable/Container",
272 std::unique_ptr<Styleable>(styleable.clone(nullptr)))
273 .build();
274
Adam Lesinski76565542016-03-10 21:55:04 -0800275 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
276 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
277 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
278 .build();
Adam Lesinski74605cd2016-03-03 15:39:50 -0800279 JavaClassGeneratorOptions options;
280 options.useFinal = false;
Adam Lesinski76565542016-03-10 21:55:04 -0800281 JavaClassGenerator generator(context.get(), table.get(), options);
Adam Lesinski74605cd2016-03-03 15:39:50 -0800282 std::stringstream out;
283 ASSERT_TRUE(generator.generate(u"android", &out));
284 std::string actual = out.str();
285
286 EXPECT_NE(std::string::npos, actual.find("@attr name android:one"));
287 EXPECT_NE(std::string::npos, actual.find("@attr description"));
288 EXPECT_NE(std::string::npos, actual.find(util::utf16ToUtf8(attr.getComment())));
289 EXPECT_NE(std::string::npos, actual.find(util::utf16ToUtf8(styleable.getComment())));
Adam Lesinski3b4cd942015-10-30 16:31:42 -0700290}
291
Michael Wrightfeaf99f2016-05-06 17:16:06 +0100292TEST(JavaClassGeneratorTest, CommentsForRemovedAttributesAreNotPresentInClass) {
293 Attribute attr(false);
294 attr.setComment(StringPiece16(u"@removed"));
295
296
297 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
298 .setPackageId(u"android", 0x01)
299 .addValue(u"@android:attr/one", util::make_unique<Attribute>(attr))
300 .build();
301
302 std::unique_ptr<IAaptContext> context = test::ContextBuilder()
303 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
304 .setNameManglerPolicy(NameManglerPolicy{ u"android" })
305 .build();
306 JavaClassGeneratorOptions options;
307 options.useFinal = false;
308 JavaClassGenerator generator(context.get(), table.get(), options);
309 std::stringstream out;
310 ASSERT_TRUE(generator.generate(u"android", &out));
311 std::string actual = out.str();
312
313 std::cout << actual << std::endl;
314
315 EXPECT_EQ(std::string::npos, actual.find("@attr name android:one"));
316 EXPECT_EQ(std::string::npos, actual.find("@attr description"));
317
318 // We should find @removed only in the attribute javadoc and not anywhere else (i.e. the class
319 // javadoc).
320 const size_t pos = actual.find("@removed");
321 EXPECT_NE(std::string::npos, pos);
322 EXPECT_EQ(std::string::npos, actual.find("@removed", pos + 1));
323}
324
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800325} // namespace aapt