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 "JavaClassGenerator.h"
18 #include "Linker.h"
19 #include "MockResolver.h"
20 #include "ResourceTable.h"
21 #include "ResourceTableResolver.h"
22 #include "ResourceValues.h"
23 #include "Util.h"
24
25 #include <gtest/gtest.h>
26 #include <sstream>
27 #include <string>
28
29 namespace aapt {
30
31 struct JavaClassGeneratorTest : public ::testing::Test {
SetUpaapt::JavaClassGeneratorTest32 virtual void SetUp() override {
33 mTable = std::make_shared<ResourceTable>();
34 mTable->setPackage(u"android");
35 mTable->setPackageId(0x01);
36 }
37
addResourceaapt::JavaClassGeneratorTest38 bool addResource(const ResourceNameRef& name, ResourceId id) {
39 return mTable->addResource(name, id, {}, SourceLine{ "test.xml", 21 },
40 util::make_unique<Id>());
41 }
42
43 std::shared_ptr<ResourceTable> mTable;
44 };
45
TEST_F(JavaClassGeneratorTest,FailWhenEntryIsJavaKeyword)46 TEST_F(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) {
47 ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kId, u"class" },
48 ResourceId{ 0x01, 0x02, 0x0000 }));
49
50 JavaClassGenerator generator(mTable, {});
51
52 std::stringstream out;
53 EXPECT_FALSE(generator.generate(mTable->getPackage(), out));
54 }
55
TEST_F(JavaClassGeneratorTest,TransformInvalidJavaIdentifierCharacter)56 TEST_F(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
57 ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kId, u"hey-man" },
58 ResourceId{ 0x01, 0x02, 0x0000 }));
59
60 ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kAttr, u"cool.attr" },
61 ResourceId{ 0x01, 0x01, 0x0000 }));
62
63 std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
64 Reference ref(ResourceName{ u"android", ResourceType::kAttr, u"cool.attr"});
65 ref.id = ResourceId{ 0x01, 0x01, 0x0000 };
66 styleable->entries.emplace_back(ref);
67
68 ASSERT_TRUE(mTable->addResource(ResourceName{ {}, ResourceType::kStyleable, u"hey.dude" },
69 ResourceId{ 0x01, 0x03, 0x0000 }, {},
70 SourceLine{ "test.xml", 21 }, std::move(styleable)));
71
72 JavaClassGenerator generator(mTable, {});
73
74 std::stringstream out;
75 EXPECT_TRUE(generator.generate(mTable->getPackage(), out));
76 std::string output = out.str();
77
78 EXPECT_NE(std::string::npos,
79 output.find("public static final int hey_man = 0x01020000;"));
80
81 EXPECT_NE(std::string::npos,
82 output.find("public static final int[] hey_dude = {"));
83
84 EXPECT_NE(std::string::npos,
85 output.find("public static final int hey_dude_cool_attr = 0;"));
86 }
87
88
TEST_F(JavaClassGeneratorTest,EmitPackageMangledSymbols)89 TEST_F(JavaClassGeneratorTest, EmitPackageMangledSymbols) {
90 ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kId, u"foo" },
91 ResourceId{ 0x01, 0x02, 0x0000 }));
92 ResourceTable table;
93 table.setPackage(u"com.lib");
94 ASSERT_TRUE(table.addResource(ResourceName{ {}, ResourceType::kId, u"test" }, {},
95 SourceLine{ "lib.xml", 33 }, util::make_unique<Id>()));
96 ASSERT_TRUE(mTable->merge(std::move(table)));
97
98 Linker linker(mTable,
99 std::make_shared<MockResolver>(mTable, std::map<ResourceName, ResourceId>()),
100 {});
101 ASSERT_TRUE(linker.linkAndValidate());
102
103 JavaClassGenerator generator(mTable, {});
104
105 std::stringstream out;
106 EXPECT_TRUE(generator.generate(mTable->getPackage(), out));
107 std::string output = out.str();
108 EXPECT_NE(std::string::npos, output.find("int foo ="));
109 EXPECT_EQ(std::string::npos, output.find("int test ="));
110
111 out.str("");
112 EXPECT_TRUE(generator.generate(u"com.lib", out));
113 output = out.str();
114 EXPECT_NE(std::string::npos, output.find("int test ="));
115 EXPECT_EQ(std::string::npos, output.find("int foo ="));
116 }
117
TEST_F(JavaClassGeneratorTest,EmitOtherPackagesAttributesInStyleable)118 TEST_F(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
119 std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
120 styleable->entries.emplace_back(ResourceNameRef{ mTable->getPackage(),
121 ResourceType::kAttr,
122 u"bar" });
123 styleable->entries.emplace_back(ResourceNameRef{ u"com.lib", ResourceType::kAttr, u"bar" });
124 ASSERT_TRUE(mTable->addResource(ResourceName{ {}, ResourceType::kStyleable, u"Foo" }, {}, {},
125 std::move(styleable)));
126
127 std::shared_ptr<IResolver> resolver = std::make_shared<MockResolver>(mTable,
128 std::map<ResourceName, ResourceId>({
129 { ResourceName{ u"android", ResourceType::kAttr, u"bar" },
130 ResourceId{ 0x01, 0x01, 0x0000 } },
131 { ResourceName{ u"com.lib", ResourceType::kAttr, u"bar" },
132 ResourceId{ 0x02, 0x01, 0x0000 } }}));
133
134 Linker linker(mTable, resolver, {});
135 ASSERT_TRUE(linker.linkAndValidate());
136
137 JavaClassGenerator generator(mTable, {});
138
139 std::stringstream out;
140 EXPECT_TRUE(generator.generate(mTable->getPackage(), out));
141 std::string output = out.str();
142 EXPECT_NE(std::string::npos, output.find("int Foo_bar ="));
143 EXPECT_NE(std::string::npos, output.find("int Foo_com_lib_bar ="));
144 }
145
146 } // namespace aapt
147