JavaClassGenerator_test.cpp revision 74605cd40256ca75b44cc3182eeeb886c92d737c
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 "java/JavaClassGenerator.h"
18#include "util/Util.h"
19
20#include "test/Builders.h"
21
22#include <gtest/gtest.h>
23#include <sstream>
24#include <string>
25
26namespace aapt {
27
28TEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) {
29    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
30            .setPackageId(u"android", 0x01)
31            .addSimple(u"@android:id/class", ResourceId(0x01020000))
32            .build();
33
34    JavaClassGenerator generator(table.get(), {});
35
36    std::stringstream out;
37    EXPECT_FALSE(generator.generate(u"android", &out));
38}
39
40TEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
41    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
42            .setPackageId(u"android", 0x01)
43            .addSimple(u"@android:id/hey-man", ResourceId(0x01020000))
44            .addSimple(u"@android:attr/cool.attr", ResourceId(0x01010000))
45            .addValue(u"@android:styleable/hey.dude", ResourceId(0x01030000),
46                      test::StyleableBuilder()
47                              .addItem(u"@android:attr/cool.attr", ResourceId(0x01010000))
48                              .build())
49            .build();
50
51    JavaClassGenerator generator(table.get(), {});
52
53    std::stringstream out;
54    EXPECT_TRUE(generator.generate(u"android", &out));
55
56    std::string output = out.str();
57
58    EXPECT_NE(std::string::npos,
59              output.find("public static final int hey_man=0x01020000;"));
60
61    EXPECT_NE(std::string::npos,
62              output.find("public static final int[] hey_dude={"));
63
64    EXPECT_NE(std::string::npos,
65              output.find("public static final int hey_dude_cool_attr=0;"));
66}
67
68TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
69    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
70            .setPackageId(u"android", 0x01)
71            .addSimple(u"@android:id/one", ResourceId(0x01020000))
72            .addSimple(u"@android:id/com.foo$two", ResourceId(0x01020001))
73            .build();
74
75    JavaClassGenerator generator(table.get(), {});
76    std::stringstream out;
77    ASSERT_TRUE(generator.generate(u"android", u"com.android.internal", &out));
78
79    std::string output = out.str();
80    EXPECT_NE(std::string::npos, output.find("package com.android.internal;"));
81    EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
82    EXPECT_EQ(std::string::npos, output.find("two"));
83    EXPECT_EQ(std::string::npos, output.find("com_foo$two"));
84}
85
86TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
87    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
88            .setPackageId(u"android", 0x01)
89            .addSimple(u"@android:attr/two", ResourceId(0x01010001))
90            .addSimple(u"@android:^attr-private/one", ResourceId(0x01010000))
91            .build();
92
93    JavaClassGenerator generator(table.get(), {});
94    std::stringstream out;
95    ASSERT_TRUE(generator.generate(u"android", &out));
96
97    std::string output = out.str();
98    EXPECT_NE(std::string::npos, output.find("public static final class attr"));
99    EXPECT_EQ(std::string::npos, output.find("public static final class ^attr-private"));
100}
101
102TEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
103    StdErrDiagnostics diag;
104    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
105            .setPackageId(u"android", 0x01)
106            .addSimple(u"@android:id/one", ResourceId(0x01020000))
107            .addSimple(u"@android:id/two", ResourceId(0x01020001))
108            .addSimple(u"@android:id/three", ResourceId(0x01020002))
109            .setSymbolState(u"@android:id/one", ResourceId(0x01020000), SymbolState::kPublic)
110            .setSymbolState(u"@android:id/two", ResourceId(0x01020001), SymbolState::kPrivate)
111            .build();
112
113    JavaClassGeneratorOptions options;
114    options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
115    {
116        JavaClassGenerator generator(table.get(), options);
117        std::stringstream out;
118        ASSERT_TRUE(generator.generate(u"android", &out));
119        std::string output = out.str();
120        EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
121        EXPECT_EQ(std::string::npos, output.find("two"));
122        EXPECT_EQ(std::string::npos, output.find("three"));
123    }
124
125    options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
126    {
127        JavaClassGenerator generator(table.get(), options);
128        std::stringstream out;
129        ASSERT_TRUE(generator.generate(u"android", &out));
130        std::string output = out.str();
131        EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
132        EXPECT_NE(std::string::npos, output.find("public static final int two=0x01020001;"));
133        EXPECT_EQ(std::string::npos, output.find("three"));
134    }
135
136    options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
137    {
138        JavaClassGenerator generator(table.get(), options);
139        std::stringstream out;
140        ASSERT_TRUE(generator.generate(u"android", &out));
141        std::string output = out.str();
142        EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
143        EXPECT_NE(std::string::npos, output.find("public static final int two=0x01020001;"));
144        EXPECT_NE(std::string::npos, output.find("public static final int three=0x01020002;"));
145    }
146}
147
148/*
149 * TODO(adamlesinski): Re-enable this once we get merging working again.
150 * TEST(JavaClassGeneratorTest, EmitPackageMangledSymbols) {
151    ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kId, u"foo" },
152                            ResourceId{ 0x01, 0x02, 0x0000 }));
153    ResourceTable table;
154    table.setPackage(u"com.lib");
155    ASSERT_TRUE(table.addResource(ResourceName{ {}, ResourceType::kId, u"test" }, {},
156                                  Source{ "lib.xml", 33 }, util::make_unique<Id>()));
157    ASSERT_TRUE(mTable->merge(std::move(table)));
158
159    Linker linker(mTable,
160                  std::make_shared<MockResolver>(mTable, std::map<ResourceName, ResourceId>()),
161                  {});
162    ASSERT_TRUE(linker.linkAndValidate());
163
164    JavaClassGenerator generator(mTable, {});
165
166    std::stringstream out;
167    EXPECT_TRUE(generator.generate(mTable->getPackage(), out));
168    std::string output = out.str();
169    EXPECT_NE(std::string::npos, output.find("int foo ="));
170    EXPECT_EQ(std::string::npos, output.find("int test ="));
171
172    out.str("");
173    EXPECT_TRUE(generator.generate(u"com.lib", out));
174    output = out.str();
175    EXPECT_NE(std::string::npos, output.find("int test ="));
176    EXPECT_EQ(std::string::npos, output.find("int foo ="));
177}*/
178
179TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
180    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
181                .setPackageId(u"android", 0x01)
182                .setPackageId(u"com.lib", 0x02)
183                .addSimple(u"@android:attr/bar", ResourceId(0x01010000))
184                .addSimple(u"@com.lib:attr/bar", ResourceId(0x02010000))
185                .addValue(u"@android:styleable/foo", ResourceId(0x01030000),
186                          test::StyleableBuilder()
187                                  .addItem(u"@android:attr/bar", ResourceId(0x01010000))
188                                  .addItem(u"@com.lib:attr/bar", ResourceId(0x02010000))
189                                  .build())
190                .build();
191
192    JavaClassGenerator generator(table.get(), {});
193
194    std::stringstream out;
195    EXPECT_TRUE(generator.generate(u"android", &out));
196
197    std::string output = out.str();
198    EXPECT_NE(std::string::npos, output.find("int foo_bar="));
199    EXPECT_NE(std::string::npos, output.find("int foo_com_lib_bar="));
200}
201
202TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
203    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
204            .setPackageId(u"android", 0x01)
205            .addSimple(u"@android:id/foo", ResourceId(0x01010000))
206            .build();
207    test::getValue<Id>(table.get(), u"@android:id/foo")
208            ->setComment(std::u16string(u"This is a comment\n@deprecated"));
209
210    JavaClassGenerator generator(table.get(), {});
211
212    std::stringstream out;
213    ASSERT_TRUE(generator.generate(u"android", &out));
214    std::string actual = out.str();
215
216    EXPECT_NE(std::string::npos, actual.find(
217    R"EOF(/**
218     * This is a comment
219     * @deprecated
220     */
221    @Deprecated
222    public static final int foo=0x01010000;)EOF"));
223}
224
225TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {
226
227}
228
229TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) {
230    Attribute attr(false);
231    attr.setComment(StringPiece16(u"This is an attribute"));
232
233    Styleable styleable;
234    styleable.entries.push_back(Reference(test::parseNameOrDie(u"@android:attr/one")));
235    styleable.setComment(StringPiece16(u"This is a styleable"));
236
237    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
238            .setPackageId(u"android", 0x01)
239            .addValue(u"@android:attr/one", util::make_unique<Attribute>(attr))
240            .addValue(u"@android:styleable/Container",
241                      std::unique_ptr<Styleable>(styleable.clone(nullptr)))
242            .build();
243
244    JavaClassGeneratorOptions options;
245    options.useFinal = false;
246    JavaClassGenerator generator(table.get(), options);
247
248    std::stringstream out;
249    ASSERT_TRUE(generator.generate(u"android", &out));
250    std::string actual = out.str();
251
252    EXPECT_NE(std::string::npos, actual.find("@attr name android:one"));
253    EXPECT_NE(std::string::npos, actual.find("@attr description"));
254    EXPECT_NE(std::string::npos, actual.find(util::utf16ToUtf8(attr.getComment())));
255    EXPECT_NE(std::string::npos, actual.find(util::utf16ToUtf8(styleable.getComment())));
256}
257
258} // namespace aapt
259