AAPT2: Fix Plural::Equals() method
Test: make aapt2_tests Bug: 35902437 Change-Id: I8797f89af58876f891f0b0c5cce85fd7781c4e24
This commit is contained in:
@@ -582,6 +582,16 @@ TEST_F(ResourceParserTest, ParsePlural) {
|
||||
" <item quantity=\"one\">apple</item>\n"
|
||||
"</plurals>";
|
||||
ASSERT_TRUE(TestParse(input));
|
||||
|
||||
Plural* plural = test::GetValue<Plural>(&table_, "plurals/foo");
|
||||
ASSERT_NE(nullptr, plural);
|
||||
EXPECT_EQ(nullptr, plural->values[Plural::Zero]);
|
||||
EXPECT_EQ(nullptr, plural->values[Plural::Two]);
|
||||
EXPECT_EQ(nullptr, plural->values[Plural::Few]);
|
||||
EXPECT_EQ(nullptr, plural->values[Plural::Many]);
|
||||
|
||||
EXPECT_NE(nullptr, plural->values[Plural::One]);
|
||||
EXPECT_NE(nullptr, plural->values[Plural::Other]);
|
||||
}
|
||||
|
||||
TEST_F(ResourceParserTest, ParseCommentsWithResource) {
|
||||
|
||||
@@ -341,7 +341,7 @@ Attribute::Attribute(bool w, uint32_t t)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* addPointer(T& val) {
|
||||
constexpr T* add_pointer(T& val) {
|
||||
return &val;
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ bool Attribute::Equals(const Value* value) const {
|
||||
|
||||
std::vector<const Symbol*> sorted_a;
|
||||
std::transform(symbols.begin(), symbols.end(), std::back_inserter(sorted_a),
|
||||
addPointer<const Symbol>);
|
||||
add_pointer<const Symbol>);
|
||||
std::sort(sorted_a.begin(), sorted_a.end(),
|
||||
[](const Symbol* a, const Symbol* b) -> bool {
|
||||
return a->symbol.name < b->symbol.name;
|
||||
@@ -370,7 +370,7 @@ bool Attribute::Equals(const Value* value) const {
|
||||
|
||||
std::vector<const Symbol*> sorted_b;
|
||||
std::transform(other->symbols.begin(), other->symbols.end(),
|
||||
std::back_inserter(sorted_b), addPointer<const Symbol>);
|
||||
std::back_inserter(sorted_b), add_pointer<const Symbol>);
|
||||
std::sort(sorted_b.begin(), sorted_b.end(),
|
||||
[](const Symbol* a, const Symbol* b) -> bool {
|
||||
return a->symbol.name < b->symbol.name;
|
||||
@@ -599,7 +599,7 @@ bool Style::Equals(const Value* value) const {
|
||||
|
||||
std::vector<const Entry*> sorted_a;
|
||||
std::transform(entries.begin(), entries.end(), std::back_inserter(sorted_a),
|
||||
addPointer<const Entry>);
|
||||
add_pointer<const Entry>);
|
||||
std::sort(sorted_a.begin(), sorted_a.end(),
|
||||
[](const Entry* a, const Entry* b) -> bool {
|
||||
return a->key.name < b->key.name;
|
||||
@@ -607,7 +607,7 @@ bool Style::Equals(const Value* value) const {
|
||||
|
||||
std::vector<const Entry*> sorted_b;
|
||||
std::transform(other->entries.begin(), other->entries.end(),
|
||||
std::back_inserter(sorted_b), addPointer<const Entry>);
|
||||
std::back_inserter(sorted_b), add_pointer<const Entry>);
|
||||
std::sort(sorted_b.begin(), sorted_b.end(),
|
||||
[](const Entry* a, const Entry* b) -> bool {
|
||||
return a->key.name < b->key.name;
|
||||
@@ -695,18 +695,21 @@ bool Plural::Equals(const Value* value) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (values.size() != other->values.size()) {
|
||||
return false;
|
||||
auto one_iter = values.begin();
|
||||
auto one_end_iter = values.end();
|
||||
auto two_iter = other->values.begin();
|
||||
for (; one_iter != one_end_iter; ++one_iter, ++two_iter) {
|
||||
const std::unique_ptr<Item>& a = *one_iter;
|
||||
const std::unique_ptr<Item>& b = *two_iter;
|
||||
if (a != nullptr && b != nullptr) {
|
||||
if (!a->Equals(b.get())) {
|
||||
return false;
|
||||
}
|
||||
} else if (a != b) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return std::equal(values.begin(), values.end(), other->values.begin(),
|
||||
[](const std::unique_ptr<Item>& a,
|
||||
const std::unique_ptr<Item>& b) -> bool {
|
||||
if (bool(a) != bool(b)) {
|
||||
return false;
|
||||
}
|
||||
return bool(a) == bool(b) || a->Equals(b.get());
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
Plural* Plural::Clone(StringPool* new_pool) const {
|
||||
@@ -743,6 +746,10 @@ void Plural::Print(std::ostream* out) const {
|
||||
if (values[Many]) {
|
||||
*out << " many=" << *values[Many];
|
||||
}
|
||||
|
||||
if (values[Other]) {
|
||||
*out << " other=" << *values[Other];
|
||||
}
|
||||
}
|
||||
|
||||
static ::std::ostream& operator<<(::std::ostream& out,
|
||||
|
||||
151
tools/aapt2/ResourceValues_test.cpp
Normal file
151
tools/aapt2/ResourceValues_test.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ResourceValues.h"
|
||||
|
||||
#include "test/Test.h"
|
||||
|
||||
namespace aapt {
|
||||
|
||||
TEST(ResourceValuesTest, PluralEquals) {
|
||||
StringPool pool;
|
||||
|
||||
Plural a;
|
||||
a.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one"));
|
||||
a.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other"));
|
||||
|
||||
Plural b;
|
||||
b.values[Plural::One] = util::make_unique<String>(pool.MakeRef("une"));
|
||||
b.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("autre"));
|
||||
|
||||
Plural c;
|
||||
c.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one"));
|
||||
c.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other"));
|
||||
|
||||
EXPECT_FALSE(a.Equals(&b));
|
||||
EXPECT_TRUE(a.Equals(&c));
|
||||
}
|
||||
|
||||
TEST(ResourceValuesTest, PluralClone) {
|
||||
StringPool pool;
|
||||
|
||||
Plural a;
|
||||
a.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one"));
|
||||
a.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other"));
|
||||
|
||||
std::unique_ptr<Plural> b(a.Clone(&pool));
|
||||
EXPECT_TRUE(a.Equals(b.get()));
|
||||
}
|
||||
|
||||
TEST(ResourceValuesTest, ArrayEquals) {
|
||||
StringPool pool;
|
||||
|
||||
Array a;
|
||||
a.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
|
||||
a.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
|
||||
|
||||
Array b;
|
||||
b.items.push_back(util::make_unique<String>(pool.MakeRef("une")));
|
||||
b.items.push_back(util::make_unique<String>(pool.MakeRef("deux")));
|
||||
|
||||
Array c;
|
||||
c.items.push_back(util::make_unique<String>(pool.MakeRef("uno")));
|
||||
|
||||
Array d;
|
||||
d.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
|
||||
d.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
|
||||
|
||||
EXPECT_FALSE(a.Equals(&b));
|
||||
EXPECT_FALSE(a.Equals(&c));
|
||||
EXPECT_FALSE(b.Equals(&c));
|
||||
EXPECT_TRUE(a.Equals(&d));
|
||||
}
|
||||
|
||||
TEST(ResourceValuesTest, ArrayClone) {
|
||||
StringPool pool;
|
||||
|
||||
Array a;
|
||||
a.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
|
||||
a.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
|
||||
|
||||
std::unique_ptr<Array> b(a.Clone(&pool));
|
||||
EXPECT_TRUE(a.Equals(b.get()));
|
||||
}
|
||||
|
||||
TEST(ResourceValuesTest, StyleEquals) {
|
||||
StringPool pool;
|
||||
|
||||
std::unique_ptr<Style> a = test::StyleBuilder()
|
||||
.SetParent("android:style/Parent")
|
||||
.AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
|
||||
.AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
|
||||
.Build();
|
||||
|
||||
std::unique_ptr<Style> b = test::StyleBuilder()
|
||||
.SetParent("android:style/Parent")
|
||||
.AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
|
||||
.AddItem("android:attr/bar", ResourceUtils::TryParseInt("3"))
|
||||
.Build();
|
||||
|
||||
std::unique_ptr<Style> c = test::StyleBuilder()
|
||||
.SetParent("android:style/NoParent")
|
||||
.AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
|
||||
.AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
|
||||
.Build();
|
||||
|
||||
std::unique_ptr<Style> d = test::StyleBuilder()
|
||||
.AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
|
||||
.AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
|
||||
.Build();
|
||||
|
||||
std::unique_ptr<Style> e = test::StyleBuilder()
|
||||
.SetParent("android:style/Parent")
|
||||
.AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
|
||||
.AddItem("android:attr/bat", ResourceUtils::TryParseInt("2"))
|
||||
.Build();
|
||||
|
||||
std::unique_ptr<Style> f = test::StyleBuilder()
|
||||
.SetParent("android:style/Parent")
|
||||
.AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
|
||||
.Build();
|
||||
|
||||
std::unique_ptr<Style> g = test::StyleBuilder()
|
||||
.SetParent("android:style/Parent")
|
||||
.AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
|
||||
.AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
|
||||
.Build();
|
||||
|
||||
EXPECT_FALSE(a->Equals(b.get()));
|
||||
EXPECT_FALSE(a->Equals(c.get()));
|
||||
EXPECT_FALSE(a->Equals(d.get()));
|
||||
EXPECT_FALSE(a->Equals(e.get()));
|
||||
EXPECT_FALSE(a->Equals(f.get()));
|
||||
|
||||
EXPECT_TRUE(a->Equals(g.get()));
|
||||
}
|
||||
|
||||
TEST(ResourceValuesTest, StyleClone) {
|
||||
std::unique_ptr<Style> a = test::StyleBuilder()
|
||||
.SetParent("android:style/Parent")
|
||||
.AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
|
||||
.AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
|
||||
.Build();
|
||||
|
||||
std::unique_ptr<Style> b(a->Clone(nullptr));
|
||||
EXPECT_TRUE(a->Equals(b.get()));
|
||||
}
|
||||
|
||||
} // namespace aapt
|
||||
@@ -77,6 +77,8 @@ class DominatedKeyValueRemover : public DominatorTree::BottomUpVisitor {
|
||||
DiagMessage(node_value->value->GetSource())
|
||||
<< "removing dominated duplicate resource with name \""
|
||||
<< entry_->name << "\"");
|
||||
context_->GetDiagnostics()->Note(
|
||||
DiagMessage(parent_value->value->GetSource()) << "dominated here");
|
||||
}
|
||||
node_value->value = {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user