16f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/*
26f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copyright (C) 2015 The Android Open Source Project
36f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
46f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
56f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * you may not use this file except in compliance with the License.
66f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * You may obtain a copy of the License at
76f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
86f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
96f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Unless required by applicable law or agreed to in writing, software
116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * See the License for the specific language governing permissions and
146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * limitations under the License.
156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
17ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "java/JavaClassGenerator.h"
181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <sstream>
206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <string>
216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
22ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "test/Test.h"
23ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "util/Util.h"
24ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
25d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinskiusing android::StringPiece;
26d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt {
286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
291ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) {
30ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> table =
31ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ResourceTableBuilder()
32ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetPackageId("android", 0x01)
33ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSimple("android:id/class", ResourceId(0x01020000))
34ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
35ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
36ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context =
37ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ContextBuilder()
38ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSymbolSource(
39ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              util::make_unique<ResourceTableSymbolSource>(table.get()))
40ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetNameManglerPolicy(NameManglerPolicy{"android"})
41ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
42ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  JavaClassGenerator generator(context.get(), table.get(), {});
43ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
44ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stringstream out;
45ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_FALSE(generator.Generate("android", &out));
466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
481ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
49ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> table =
50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ResourceTableBuilder()
51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetPackageId("android", 0x01)
52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSimple("android:id/hey-man", ResourceId(0x01020000))
53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddValue("android:attr/cool.attr", ResourceId(0x01010000),
54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                    test::AttributeBuilder(false).Build())
55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddValue(
56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              "android:styleable/hey.dude", ResourceId(0x01030000),
57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              test::StyleableBuilder()
58ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                  .AddItem("android:attr/cool.attr", ResourceId(0x01010000))
59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                  .Build())
60ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
61ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
62ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context =
63ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ContextBuilder()
64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSymbolSource(
65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              util::make_unique<ResourceTableSymbolSource>(table.get()))
66ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetNameManglerPolicy(NameManglerPolicy{"android"})
67ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
68ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  JavaClassGenerator generator(context.get(), table.get(), {});
69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
70ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stringstream out;
71ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_TRUE(generator.Generate("android", &out));
72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
73ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string output = out.str();
74ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
75ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos,
76ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            output.find("public static final int hey_man=0x01020000;"));
77ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos,
79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            output.find("public static final int[] hey_dude={"));
80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos,
82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            output.find("public static final int hey_dude_cool_attr=0;"));
83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}
846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiTEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> table =
87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ResourceTableBuilder()
88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetPackageId("android", 0x01)
89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSimple("android:id/one", ResourceId(0x01020000))
90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSimple("android:id/com.foo$two", ResourceId(0x01020001))
91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
92ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context =
94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ContextBuilder()
95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSymbolSource(
96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              util::make_unique<ResourceTableSymbolSource>(table.get()))
97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetNameManglerPolicy(NameManglerPolicy{"android"})
98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  JavaClassGenerator generator(context.get(), table.get(), {});
100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stringstream out;
101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(generator.Generate("android", "com.android.internal", &out));
102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string output = out.str();
104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos, output.find("package com.android.internal;"));
105ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos,
106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            output.find("public static final int one=0x01020000;"));
107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(std::string::npos, output.find("two"));
108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(std::string::npos, output.find("com_foo$two"));
109ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}
1106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiTEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> table =
113ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ResourceTableBuilder()
114ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetPackageId("android", 0x01)
115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSimple("android:attr/two", ResourceId(0x01010001))
116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSimple("android:^attr-private/one", ResourceId(0x01010000))
117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context =
120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ContextBuilder()
121ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSymbolSource(
122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              util::make_unique<ResourceTableSymbolSource>(table.get()))
123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetNameManglerPolicy(NameManglerPolicy{"android"})
124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
125ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  JavaClassGenerator generator(context.get(), table.get(), {});
126ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stringstream out;
127ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(generator.Generate("android", &out));
128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
129ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string output = out.str();
130ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos, output.find("public static final class attr"));
131ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(std::string::npos,
132ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            output.find("public static final class ^attr-private"));
1336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
135ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiTEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
136ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  StdErrDiagnostics diag;
137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> table =
138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ResourceTableBuilder()
139ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetPackageId("android", 0x01)
140ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSimple("android:id/one", ResourceId(0x01020000))
141ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSimple("android:id/two", ResourceId(0x01020001))
142ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSimple("android:id/three", ResourceId(0x01020002))
143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetSymbolState("android:id/one", ResourceId(0x01020000),
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          SymbolState::kPublic)
145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetSymbolState("android:id/two", ResourceId(0x01020001),
146ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          SymbolState::kPrivate)
147ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
149ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context =
150ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ContextBuilder()
151ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSymbolSource(
152ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              util::make_unique<ResourceTableSymbolSource>(table.get()))
153ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetNameManglerPolicy(NameManglerPolicy{"android"})
154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  JavaClassGeneratorOptions options;
157ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
158ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  {
159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    JavaClassGenerator generator(context.get(), table.get(), options);
1609e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski    std::stringstream out;
161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ASSERT_TRUE(generator.Generate("android", &out));
1629e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski    std::string output = out.str();
163ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    EXPECT_NE(std::string::npos,
164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              output.find("public static final int one=0x01020000;"));
1659e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski    EXPECT_EQ(std::string::npos, output.find("two"));
166ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    EXPECT_EQ(std::string::npos, output.find("three"));
167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
1689e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski
169ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
170ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  {
171ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    JavaClassGenerator generator(context.get(), table.get(), options);
1729e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski    std::stringstream out;
173ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ASSERT_TRUE(generator.Generate("android", &out));
1749e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski    std::string output = out.str();
175ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    EXPECT_NE(std::string::npos,
176ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              output.find("public static final int one=0x01020000;"));
177ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    EXPECT_NE(std::string::npos,
178ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              output.find("public static final int two=0x01020001;"));
179ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    EXPECT_EQ(std::string::npos, output.find("three"));
180ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
1819e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski
182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  {
184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    JavaClassGenerator generator(context.get(), table.get(), options);
185ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::stringstream out;
186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ASSERT_TRUE(generator.Generate("android", &out));
187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string output = out.str();
188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    EXPECT_NE(std::string::npos,
189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              output.find("public static final int one=0x01020000;"));
190ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    EXPECT_NE(std::string::npos,
191ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              output.find("public static final int two=0x01020001;"));
192ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    EXPECT_NE(std::string::npos,
193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              output.find("public static final int three=0x01020002;"));
194ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
1959e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski}
1969e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski
1971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/*
1981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * TODO(adamlesinski): Re-enable this once we get merging working again.
1991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * TEST(JavaClassGeneratorTest, EmitPackageMangledSymbols) {
200769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kId, u"foo" },
201769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski                            ResourceId{ 0x01, 0x02, 0x0000 }));
202769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    ResourceTable table;
203769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    table.setPackage(u"com.lib");
204ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ASSERT_TRUE(table.addResource(ResourceName{ {}, ResourceType::kId, u"test"
205ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}, {},
206ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                  Source{ "lib.xml", 33 },
207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiutil::make_unique<Id>()));
208769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    ASSERT_TRUE(mTable->merge(std::move(table)));
209769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski
210330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski    Linker linker(mTable,
211ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                  std::make_shared<MockResolver>(mTable, std::map<ResourceName,
212ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiResourceId>()),
213330edcdf1316ed599fe0eb16a64330821fd92f18Adam Lesinski                  {});
214769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    ASSERT_TRUE(linker.linkAndValidate());
215769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski
216769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    JavaClassGenerator generator(mTable, {});
217769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski
218769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    std::stringstream out;
219769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    EXPECT_TRUE(generator.generate(mTable->getPackage(), out));
220769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    std::string output = out.str();
221769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    EXPECT_NE(std::string::npos, output.find("int foo ="));
222769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    EXPECT_EQ(std::string::npos, output.find("int test ="));
223769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski
224769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    out.str("");
225769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    EXPECT_TRUE(generator.generate(u"com.lib", out));
226769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    output = out.str();
227769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    EXPECT_NE(std::string::npos, output.find("int test ="));
228769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski    EXPECT_EQ(std::string::npos, output.find("int foo ="));
2291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}*/
2301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2311ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiTEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> table =
233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ResourceTableBuilder()
234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetPackageId("android", 0x01)
235ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetPackageId("com.lib", 0x02)
236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddValue("android:attr/bar", ResourceId(0x01010000),
237ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                    test::AttributeBuilder(false).Build())
238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddValue("com.lib:attr/bar", ResourceId(0x02010000),
239ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                    test::AttributeBuilder(false).Build())
240ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddValue("android:styleable/foo", ResourceId(0x01030000),
241ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                    test::StyleableBuilder()
242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        .AddItem("android:attr/bar", ResourceId(0x01010000))
243ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        .AddItem("com.lib:attr/bar", ResourceId(0x02010000))
244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        .Build())
245ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context =
248ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ContextBuilder()
249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSymbolSource(
250ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              util::make_unique<ResourceTableSymbolSource>(table.get()))
251ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetNameManglerPolicy(NameManglerPolicy{"android"})
252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  JavaClassGenerator generator(context.get(), table.get(), {});
254ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
255ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stringstream out;
256ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_TRUE(generator.Generate("android", &out));
257ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
258ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string output = out.str();
259ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos, output.find("int foo_bar="));
260ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos, output.find("int foo_com_lib_bar="));
261838a68705bc79527e592265371cbe4d8e888d9d9Adam Lesinski}
262769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski
2633b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam LesinskiTEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
264ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> table =
265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ResourceTableBuilder()
266ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetPackageId("android", 0x01)
267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSimple("android:id/foo", ResourceId(0x01010000))
268ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
269ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  test::GetValue<Id>(table.get(), "android:id/foo")
270ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      ->SetComment(std::string("This is a comment\n@deprecated"));
271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context =
273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ContextBuilder()
274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSymbolSource(
275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              util::make_unique<ResourceTableSymbolSource>(table.get()))
276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetNameManglerPolicy(NameManglerPolicy{"android"})
277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  JavaClassGenerator generator(context.get(), table.get(), {});
279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stringstream out;
280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(generator.Generate("android", &out));
281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string actual = out.str();
282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char* expectedText =
284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      R"EOF(/**
2853b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam Lesinski     * This is a comment
2863b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam Lesinski     * @deprecated
2873b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam Lesinski     */
2883b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam Lesinski    @Deprecated
289803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski    public static final int foo=0x01010000;)EOF";
290803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski
291ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos, actual.find(expectedText));
2923b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam Lesinski}
2933b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam Lesinski
294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiTEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {}
295ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
296ceb9b2f80f853059233cdd29057f39a5960a74aeAdam LesinskiTEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) {
297ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Attribute attr(false);
298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  attr.SetComment(StringPiece("This is an attribute"));
299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Styleable styleable;
301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  styleable.entries.push_back(
302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Reference(test::ParseNameOrDie("android:attr/one")));
303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  styleable.SetComment(StringPiece("This is a styleable"));
304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> table =
306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ResourceTableBuilder()
307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetPackageId("android", 0x01)
308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddValue("android:attr/one", util::make_unique<Attribute>(attr))
309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddValue("android:styleable/Container",
310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                    std::unique_ptr<Styleable>(styleable.Clone(nullptr)))
311ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
312ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
313ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context =
314ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ContextBuilder()
315ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSymbolSource(
316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              util::make_unique<ResourceTableSymbolSource>(table.get()))
317ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetNameManglerPolicy(NameManglerPolicy{"android"})
318ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  JavaClassGeneratorOptions options;
320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.use_final = false;
321ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  JavaClassGenerator generator(context.get(), table.get(), options);
322ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stringstream out;
323ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(generator.Generate("android", &out));
324ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string actual = out.str();
325ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
326ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos, actual.find("attr name android:one"));
327ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos, actual.find("attr description"));
328ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos, actual.find(attr.GetComment().data()));
329ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos, actual.find(styleable.GetComment().data()));
3303b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam Lesinski}
3313b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam Lesinski
332feaf99fa1b7563f15dbd4211718a6cfb7a3cc3c8Michael WrightTEST(JavaClassGeneratorTest, CommentsForRemovedAttributesAreNotPresentInClass) {
333ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Attribute attr(false);
334ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  attr.SetComment(StringPiece("removed"));
335ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
336ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> table =
337ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ResourceTableBuilder()
338ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetPackageId("android", 0x01)
339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddValue("android:attr/one", util::make_unique<Attribute>(attr))
340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
341ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IAaptContext> context =
343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      test::ContextBuilder()
344ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .AddSymbolSource(
345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              util::make_unique<ResourceTableSymbolSource>(table.get()))
346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .SetNameManglerPolicy(NameManglerPolicy{"android"})
347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .Build();
348ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  JavaClassGeneratorOptions options;
349ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.use_final = false;
350ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  JavaClassGenerator generator(context.get(), table.get(), options);
351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stringstream out;
352ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ASSERT_TRUE(generator.Generate("android", &out));
353ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string actual = out.str();
354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(std::string::npos, actual.find("@attr name android:one"));
356ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(std::string::npos, actual.find("@attr description"));
357ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
358ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // We should find @removed only in the attribute javadoc and not anywhere else
359ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // (i.e. the class
360ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // javadoc).
361ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const size_t pos = actual.find("removed");
362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_NE(std::string::npos, pos);
363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  EXPECT_EQ(std::string::npos, actual.find("removed", pos + 1));
364feaf99fa1b7563f15dbd4211718a6cfb7a3cc3c8Michael Wright}
365feaf99fa1b7563f15dbd4211718a6cfb7a3cc3c8Michael Wright
366ceb9b2f80f853059233cdd29057f39a5960a74aeAdam LesinskiTEST(JavaClassGeneratorTest, GenerateOnResourcesLoadedCallbackForSharedLibrary) {
367ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  std::unique_ptr<ResourceTable> table =
368ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      test::ResourceTableBuilder()
369ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski          .SetPackageId("android", 0x00)
370ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski          .AddValue("android:attr/foo", ResourceId(0x00010000), util::make_unique<Attribute>(false))
371ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski          .AddValue("android:id/foo", ResourceId(0x00020000), util::make_unique<Id>())
372ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski          .AddValue(
373ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski              "android:style/foo", ResourceId(0x00030000),
374ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski              test::StyleBuilder()
375ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski                  .AddItem("android:attr/foo", ResourceId(0x00010000), util::make_unique<Id>())
376ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski                  .Build())
377ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski          .Build();
378ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
379ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  std::unique_ptr<IAaptContext> context =
380ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      test::ContextBuilder().SetPackageId(0x00).SetCompilationPackage("android").Build();
381ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
382ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  JavaClassGeneratorOptions options;
383ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  options.use_final = false;
384b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski  options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{
385b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      {"com.foo", "com.boo"},
386b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski  };
387ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  JavaClassGenerator generator(context.get(), table.get(), options);
388ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
389ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  std::stringstream out;
390ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  ASSERT_TRUE(generator.Generate("android", &out));
391ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
392ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  std::string actual = out.str();
393ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
394b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski  EXPECT_NE(std::string::npos, actual.find("void onResourcesLoaded"));
395b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski  EXPECT_NE(std::string::npos, actual.find("com.foo.R.onResourcesLoaded"));
396b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski  EXPECT_NE(std::string::npos, actual.find("com.boo.R.onResourcesLoaded"));
397ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski}
398ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace aapt
400