JavaClassGenerator_test.cpp revision 58a20a6482a56a262fd83a617482641e3a981db1
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 "test/Test.h" 19#include "util/Util.h" 20 21#include <sstream> 22#include <string> 23 24namespace aapt { 25 26TEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) { 27 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() 28 .setPackageId("android", 0x01) 29 .addSimple("android:id/class", ResourceId(0x01020000)) 30 .build(); 31 32 std::unique_ptr<IAaptContext> context = test::ContextBuilder() 33 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get())) 34 .setNameManglerPolicy(NameManglerPolicy{ "android" }) 35 .build(); 36 JavaClassGenerator generator(context.get(), table.get(), {}); 37 38 std::stringstream out; 39 EXPECT_FALSE(generator.generate("android", &out)); 40} 41 42TEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) { 43 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() 44 .setPackageId("android", 0x01) 45 .addSimple("android:id/hey-man", ResourceId(0x01020000)) 46 .addValue("android:attr/cool.attr", ResourceId(0x01010000), 47 test::AttributeBuilder(false).build()) 48 .addValue("android:styleable/hey.dude", ResourceId(0x01030000), 49 test::StyleableBuilder() 50 .addItem("android:attr/cool.attr", ResourceId(0x01010000)) 51 .build()) 52 .build(); 53 54 std::unique_ptr<IAaptContext> context = test::ContextBuilder() 55 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get())) 56 .setNameManglerPolicy(NameManglerPolicy{ "android" }) 57 .build(); 58 JavaClassGenerator generator(context.get(), table.get(), {}); 59 60 std::stringstream out; 61 EXPECT_TRUE(generator.generate("android", &out)); 62 63 std::string output = out.str(); 64 65 EXPECT_NE(std::string::npos, 66 output.find("public static final int hey_man=0x01020000;")); 67 68 EXPECT_NE(std::string::npos, 69 output.find("public static final int[] hey_dude={")); 70 71 EXPECT_NE(std::string::npos, 72 output.find("public static final int hey_dude_cool_attr=0;")); 73} 74 75TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) { 76 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() 77 .setPackageId("android", 0x01) 78 .addSimple("android:id/one", ResourceId(0x01020000)) 79 .addSimple("android:id/com.foo$two", ResourceId(0x01020001)) 80 .build(); 81 82 std::unique_ptr<IAaptContext> context = test::ContextBuilder() 83 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get())) 84 .setNameManglerPolicy(NameManglerPolicy{ "android" }) 85 .build(); 86 JavaClassGenerator generator(context.get(), table.get(), {}); 87 std::stringstream out; 88 ASSERT_TRUE(generator.generate("android", "com.android.internal", &out)); 89 90 std::string output = out.str(); 91 EXPECT_NE(std::string::npos, output.find("package com.android.internal;")); 92 EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;")); 93 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("android", 0x01) 100 .addSimple("android:attr/two", ResourceId(0x01010001)) 101 .addSimple("android:^attr-private/one", ResourceId(0x01010000)) 102 .build(); 103 104 std::unique_ptr<IAaptContext> context = test::ContextBuilder() 105 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get())) 106 .setNameManglerPolicy(NameManglerPolicy{ "android" }) 107 .build(); 108 JavaClassGenerator generator(context.get(), table.get(), {}); 109 std::stringstream out; 110 ASSERT_TRUE(generator.generate("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("android", 0x01) 121 .addSimple("android:id/one", ResourceId(0x01020000)) 122 .addSimple("android:id/two", ResourceId(0x01020001)) 123 .addSimple("android:id/three", ResourceId(0x01020002)) 124 .setSymbolState("android:id/one", ResourceId(0x01020000), SymbolState::kPublic) 125 .setSymbolState("android:id/two", ResourceId(0x01020001), SymbolState::kPrivate) 126 .build(); 127 128 std::unique_ptr<IAaptContext> context = test::ContextBuilder() 129 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get())) 130 .setNameManglerPolicy(NameManglerPolicy{ "android" }) 131 .build(); 132 133 JavaClassGeneratorOptions options; 134 options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic; 135 { 136 JavaClassGenerator generator(context.get(), table.get(), options); 137 std::stringstream out; 138 ASSERT_TRUE(generator.generate("android", &out)); 139 std::string output = out.str(); 140 EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;")); 141 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 { 147 JavaClassGenerator generator(context.get(), table.get(), options); 148 std::stringstream out; 149 ASSERT_TRUE(generator.generate("android", &out)); 150 std::string output = out.str(); 151 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;")); 153 EXPECT_EQ(std::string::npos, output.find("three")); 154 } 155 156 options.types = JavaClassGeneratorOptions::SymbolTypes::kAll; 157 { 158 JavaClassGenerator generator(context.get(), table.get(), options); 159 std::stringstream out; 160 ASSERT_TRUE(generator.generate("android", &out)); 161 std::string output = out.str(); 162 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;")); 165 } 166} 167 168/* 169 * TODO(adamlesinski): Re-enable this once we get merging working again. 170 * TEST(JavaClassGeneratorTest, EmitPackageMangledSymbols) { 171 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" }, {}, 176 Source{ "lib.xml", 33 }, util::make_unique<Id>())); 177 ASSERT_TRUE(mTable->merge(std::move(table))); 178 179 Linker linker(mTable, 180 std::make_shared<MockResolver>(mTable, std::map<ResourceName, ResourceId>()), 181 {}); 182 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 =")); 197}*/ 198 199TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) { 200 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() 201 .setPackageId("android", 0x01) 202 .setPackageId("com.lib", 0x02) 203 .addValue("android:attr/bar", ResourceId(0x01010000), 204 test::AttributeBuilder(false).build()) 205 .addValue("com.lib:attr/bar", ResourceId(0x02010000), 206 test::AttributeBuilder(false).build()) 207 .addValue("android:styleable/foo", ResourceId(0x01030000), 208 test::StyleableBuilder() 209 .addItem("android:attr/bar", ResourceId(0x01010000)) 210 .addItem("com.lib:attr/bar", ResourceId(0x02010000)) 211 .build()) 212 .build(); 213 214 std::unique_ptr<IAaptContext> context = test::ContextBuilder() 215 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get())) 216 .setNameManglerPolicy(NameManglerPolicy{ "android" }) 217 .build(); 218 JavaClassGenerator generator(context.get(), table.get(), {}); 219 220 std::stringstream out; 221 EXPECT_TRUE(generator.generate("android", &out)); 222 223 std::string output = out.str(); 224 EXPECT_NE(std::string::npos, output.find("int foo_bar=")); 225 EXPECT_NE(std::string::npos, output.find("int foo_com_lib_bar=")); 226} 227 228TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) { 229 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() 230 .setPackageId("android", 0x01) 231 .addSimple("android:id/foo", ResourceId(0x01010000)) 232 .build(); 233 test::getValue<Id>(table.get(), "android:id/foo") 234 ->setComment(std::string("This is a comment\n@deprecated")); 235 236 std::unique_ptr<IAaptContext> context = test::ContextBuilder() 237 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get())) 238 .setNameManglerPolicy(NameManglerPolicy{ "android" }) 239 .build(); 240 JavaClassGenerator generator(context.get(), table.get(), {}); 241 std::stringstream out; 242 ASSERT_TRUE(generator.generate("android", &out)); 243 std::string actual = out.str(); 244 245 const char* expectedText = 246R"EOF(/** 247 * This is a comment 248 * @deprecated 249 */ 250 @Deprecated 251 public static final int foo=0x01010000;)EOF"; 252 253 EXPECT_NE(std::string::npos, actual.find(expectedText)); 254} 255 256TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) { 257 258} 259 260TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) { 261 Attribute attr(false); 262 attr.setComment(StringPiece("This is an attribute")); 263 264 Styleable styleable; 265 styleable.entries.push_back(Reference(test::parseNameOrDie("android:attr/one"))); 266 styleable.setComment(StringPiece("This is a styleable")); 267 268 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() 269 .setPackageId("android", 0x01) 270 .addValue("android:attr/one", util::make_unique<Attribute>(attr)) 271 .addValue("android:styleable/Container", 272 std::unique_ptr<Styleable>(styleable.clone(nullptr))) 273 .build(); 274 275 std::unique_ptr<IAaptContext> context = test::ContextBuilder() 276 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get())) 277 .setNameManglerPolicy(NameManglerPolicy{ "android" }) 278 .build(); 279 JavaClassGeneratorOptions options; 280 options.useFinal = false; 281 JavaClassGenerator generator(context.get(), table.get(), options); 282 std::stringstream out; 283 ASSERT_TRUE(generator.generate("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(attr.getComment().data())); 289 EXPECT_NE(std::string::npos, actual.find(styleable.getComment().data())); 290} 291 292TEST(JavaClassGeneratorTest, CommentsForRemovedAttributesAreNotPresentInClass) { 293 Attribute attr(false); 294 attr.setComment(StringPiece("removed")); 295 296 std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() 297 .setPackageId("android", 0x01) 298 .addValue("android:attr/one", util::make_unique<Attribute>(attr)) 299 .build(); 300 301 std::unique_ptr<IAaptContext> context = test::ContextBuilder() 302 .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get())) 303 .setNameManglerPolicy(NameManglerPolicy{ "android" }) 304 .build(); 305 JavaClassGeneratorOptions options; 306 options.useFinal = false; 307 JavaClassGenerator generator(context.get(), table.get(), options); 308 std::stringstream out; 309 ASSERT_TRUE(generator.generate("android", &out)); 310 std::string actual = out.str(); 311 312 EXPECT_EQ(std::string::npos, actual.find("@attr name android:one")); 313 EXPECT_EQ(std::string::npos, actual.find("@attr description")); 314 315 // We should find @removed only in the attribute javadoc and not anywhere else (i.e. the class 316 // javadoc). 317 const size_t pos = actual.find("removed"); 318 EXPECT_NE(std::string::npos, pos); 319 EXPECT_EQ(std::string::npos, actual.find("removed", pos + 1)); 320} 321 322} // namespace aapt 323