1 /*
2  * Copyright (C) 2017 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 "ResourceValues.h"
18 
19 #include "test/Test.h"
20 
21 namespace aapt {
22 
TEST(ResourceValuesTest,PluralEquals)23 TEST(ResourceValuesTest, PluralEquals) {
24   StringPool pool;
25 
26   Plural a;
27   a.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one"));
28   a.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other"));
29 
30   Plural b;
31   b.values[Plural::One] = util::make_unique<String>(pool.MakeRef("une"));
32   b.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("autre"));
33 
34   Plural c;
35   c.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one"));
36   c.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other"));
37 
38   EXPECT_FALSE(a.Equals(&b));
39   EXPECT_TRUE(a.Equals(&c));
40 }
41 
TEST(ResourceValuesTest,PluralClone)42 TEST(ResourceValuesTest, PluralClone) {
43   StringPool pool;
44 
45   Plural a;
46   a.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one"));
47   a.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other"));
48 
49   std::unique_ptr<Plural> b(a.Clone(&pool));
50   EXPECT_TRUE(a.Equals(b.get()));
51 }
52 
TEST(ResourceValuesTest,ArrayEquals)53 TEST(ResourceValuesTest, ArrayEquals) {
54   StringPool pool;
55 
56   Array a;
57   a.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
58   a.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
59 
60   Array b;
61   b.items.push_back(util::make_unique<String>(pool.MakeRef("une")));
62   b.items.push_back(util::make_unique<String>(pool.MakeRef("deux")));
63 
64   Array c;
65   c.items.push_back(util::make_unique<String>(pool.MakeRef("uno")));
66 
67   Array d;
68   d.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
69   d.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
70 
71   EXPECT_FALSE(a.Equals(&b));
72   EXPECT_FALSE(a.Equals(&c));
73   EXPECT_FALSE(b.Equals(&c));
74   EXPECT_TRUE(a.Equals(&d));
75 }
76 
TEST(ResourceValuesTest,ArrayClone)77 TEST(ResourceValuesTest, ArrayClone) {
78   StringPool pool;
79 
80   Array a;
81   a.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
82   a.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
83 
84   std::unique_ptr<Array> b(a.Clone(&pool));
85   EXPECT_TRUE(a.Equals(b.get()));
86 }
87 
TEST(ResourceValuesTest,StyleEquals)88 TEST(ResourceValuesTest, StyleEquals) {
89   StringPool pool;
90 
91   std::unique_ptr<Style> a = test::StyleBuilder()
92       .SetParent("android:style/Parent")
93       .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
94       .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
95       .Build();
96 
97   std::unique_ptr<Style> b = test::StyleBuilder()
98       .SetParent("android:style/Parent")
99       .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
100       .AddItem("android:attr/bar", ResourceUtils::TryParseInt("3"))
101       .Build();
102 
103   std::unique_ptr<Style> c = test::StyleBuilder()
104       .SetParent("android:style/NoParent")
105       .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
106       .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
107       .Build();
108 
109   std::unique_ptr<Style> d = test::StyleBuilder()
110       .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
111       .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
112       .Build();
113 
114   std::unique_ptr<Style> e = test::StyleBuilder()
115       .SetParent("android:style/Parent")
116       .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
117       .AddItem("android:attr/bat", ResourceUtils::TryParseInt("2"))
118       .Build();
119 
120   std::unique_ptr<Style> f = test::StyleBuilder()
121       .SetParent("android:style/Parent")
122       .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
123       .Build();
124 
125   std::unique_ptr<Style> g = test::StyleBuilder()
126       .SetParent("android:style/Parent")
127       .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
128       .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
129       .Build();
130 
131   EXPECT_FALSE(a->Equals(b.get()));
132   EXPECT_FALSE(a->Equals(c.get()));
133   EXPECT_FALSE(a->Equals(d.get()));
134   EXPECT_FALSE(a->Equals(e.get()));
135   EXPECT_FALSE(a->Equals(f.get()));
136 
137   EXPECT_TRUE(a->Equals(g.get()));
138 }
139 
TEST(ResourceValuesTest,StyleClone)140 TEST(ResourceValuesTest, StyleClone) {
141   std::unique_ptr<Style> a = test::StyleBuilder()
142       .SetParent("android:style/Parent")
143       .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
144       .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
145       .Build();
146 
147   std::unique_ptr<Style> b(a->Clone(nullptr));
148   EXPECT_TRUE(a->Equals(b.get()));
149 }
150 
TEST(ResourceValuesTest,StyleMerges)151 TEST(ResourceValuesTest, StyleMerges) {
152   StringPool pool_a;
153   StringPool pool_b;
154 
155   std::unique_ptr<Style> a =
156       test::StyleBuilder()
157           .SetParent("android:style/Parent")
158           .AddItem("android:attr/a", util::make_unique<String>(pool_a.MakeRef("FooA")))
159           .AddItem("android:attr/b", util::make_unique<String>(pool_a.MakeRef("FooB")))
160           .Build();
161 
162   std::unique_ptr<Style> b =
163       test::StyleBuilder()
164           .SetParent("android:style/OverlayParent")
165           .AddItem("android:attr/c", util::make_unique<String>(pool_b.MakeRef("OverlayFooC")))
166           .AddItem("android:attr/a", util::make_unique<String>(pool_b.MakeRef("OverlayFooA")))
167           .Build();
168 
169   a->MergeWith(b.get(), &pool_a);
170 
171   StringPool pool;
172   std::unique_ptr<Style> expected =
173       test::StyleBuilder()
174           .SetParent("android:style/OverlayParent")
175           .AddItem("android:attr/a", util::make_unique<String>(pool.MakeRef("OverlayFooA")))
176           .AddItem("android:attr/b", util::make_unique<String>(pool.MakeRef("FooB")))
177           .AddItem("android:attr/c", util::make_unique<String>(pool.MakeRef("OverlayFooC")))
178           .Build();
179 
180   EXPECT_TRUE(a->Equals(expected.get()));
181 }
182 
183 // TYPE_NULL is encoded as TYPE_REFERENCE with a value of 0. This is represented in AAPT2
184 // by a default constructed Reference value.
TEST(ResourcesValuesTest,EmptyReferenceFlattens)185 TEST(ResourcesValuesTest, EmptyReferenceFlattens) {
186   android::Res_value value = {};
187   ASSERT_TRUE(Reference().Flatten(&value));
188 
189   EXPECT_EQ(android::Res_value::TYPE_REFERENCE, value.dataType);
190   EXPECT_EQ(0x0u, value.data);
191 }
192 
193 } // namespace aapt
194