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 29namespace aapt { 30 31struct JavaClassGeneratorTest : public ::testing::Test { 32 virtual void SetUp() override { 33 mTable = std::make_shared<ResourceTable>(); 34 mTable->setPackage(u"android"); 35 mTable->setPackageId(0x01); 36 } 37 38 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 46TEST_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 56TEST_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 89TEST_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 118TEST_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