Loading libs/androidfw/tests/TypeWrappers_test.cpp +103 −67 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #include <algorithm> #include <androidfw/ResourceTypes.h> #include <androidfw/TypeWrappers.h> #include <utils/String8.h> Loading @@ -22,68 +23,93 @@ namespace android { void* createTypeData() { ResTable_type t; memset(&t, 0, sizeof(t)); // create a ResTable_type in memory with a vector of Res_value* static ResTable_type* createTypeTable(std::vector<Res_value*>& values, bool compact_entry = false, bool short_offsets = false) { ResTable_type t{}; t.header.type = RES_TABLE_TYPE_TYPE; t.header.headerSize = sizeof(t); t.header.size = sizeof(t); t.id = 1; t.entryCount = 3; t.flags = short_offsets ? ResTable_type::FLAG_OFFSET16 : 0; uint32_t offsets[3]; t.entriesStart = t.header.headerSize + sizeof(offsets); t.header.size = t.entriesStart; t.header.size += values.size() * (short_offsets ? sizeof(uint16_t) : sizeof(uint32_t)); t.entriesStart = t.header.size; t.entryCount = values.size(); offsets[0] = 0; ResTable_entry e1; memset(&e1, 0, sizeof(e1)); e1.full.size = sizeof(e1); e1.full.key.index = 0; t.header.size += sizeof(e1); size_t entry_size = compact_entry ? sizeof(ResTable_entry) : sizeof(ResTable_entry) + sizeof(Res_value); for (auto const v : values) { t.header.size += v ? entry_size : 0; } Res_value v1; memset(&v1, 0, sizeof(v1)); t.header.size += sizeof(v1); uint8_t* data = (uint8_t *)malloc(t.header.size); uint8_t* p_header = data; uint8_t* p_offsets = data + t.header.headerSize; uint8_t* p_entries = data + t.entriesStart; memcpy(p_header, &t, sizeof(t)); size_t i = 0, entry_offset = 0; uint32_t k = 0; for (auto const& v : values) { if (short_offsets) { uint16_t *p = reinterpret_cast<uint16_t *>(p_offsets) + i; *p = v ? (entry_offset >> 2) & 0xffffu : 0xffffu; } else { uint32_t *p = reinterpret_cast<uint32_t *>(p_offsets) + i; *p = v ? entry_offset : ResTable_type::NO_ENTRY; } offsets[1] = ResTable_type::NO_ENTRY; if (v) { ResTable_entry entry{}; if (compact_entry) { entry.compact.key = i; entry.compact.flags = ResTable_entry::FLAG_COMPACT | (v->dataType << 8); entry.compact.data = v->data; memcpy(p_entries, &entry, sizeof(entry)); p_entries += sizeof(entry); entry_offset += sizeof(entry); } else { Res_value value{}; entry.full.size = sizeof(entry); entry.full.key.index = i; value = *v; memcpy(p_entries, &entry, sizeof(entry)); p_entries += sizeof(entry); memcpy(p_entries, &value, sizeof(value)); p_entries += sizeof(value); entry_offset += sizeof(entry) + sizeof(value); } } i++; } return reinterpret_cast<ResTable_type*>(data); } offsets[2] = sizeof(e1) + sizeof(v1); ResTable_entry e2; memset(&e2, 0, sizeof(e2)); e2.full.size = sizeof(e2); e2.full.key.index = 1; t.header.size += sizeof(e2); TEST(TypeVariantIteratorTest, shouldIterateOverTypeWithoutErrors) { std::vector<Res_value *> values; Res_value v2; memset(&v2, 0, sizeof(v2)); t.header.size += sizeof(v2); Res_value *v1 = new Res_value{}; values.push_back(v1); uint8_t* data = (uint8_t*)malloc(t.header.size); uint8_t* p = data; memcpy(p, &t, sizeof(t)); p += sizeof(t); memcpy(p, offsets, sizeof(offsets)); p += sizeof(offsets); memcpy(p, &e1, sizeof(e1)); p += sizeof(e1); memcpy(p, &v1, sizeof(v1)); p += sizeof(v1); memcpy(p, &e2, sizeof(e2)); p += sizeof(e2); memcpy(p, &v2, sizeof(v2)); p += sizeof(v2); return data; } values.push_back(nullptr); TEST(TypeVariantIteratorTest, shouldIterateOverTypeWithoutErrors) { ResTable_type* data = (ResTable_type*) createTypeData(); Res_value *v2 = new Res_value{}; values.push_back(v2); Res_value *v3 = new Res_value{ sizeof(Res_value), 0, Res_value::TYPE_STRING, 0x12345678}; values.push_back(v3); // test for combinations of compact_entry and short_offsets for (size_t i = 0; i < 4; i++) { bool compact_entry = i & 0x1, short_offsets = i & 0x2; ResTable_type* data = createTypeTable(values, compact_entry, short_offsets); TypeVariant v(data); TypeVariant::iterator iter = v.beginEntries(); ASSERT_EQ(uint32_t(0), iter.index()); ASSERT_TRUE(NULL != *iter); ASSERT_EQ(uint32_t(0), iter->full.key.index); ASSERT_EQ(uint32_t(0), iter->key()); ASSERT_NE(v.endEntries(), iter); iter++; Loading @@ -96,14 +122,24 @@ TEST(TypeVariantIteratorTest, shouldIterateOverTypeWithoutErrors) { ASSERT_EQ(uint32_t(2), iter.index()); ASSERT_TRUE(NULL != *iter); ASSERT_EQ(uint32_t(1), iter->full.key.index); ASSERT_EQ(uint32_t(2), iter->key()); ASSERT_NE(v.endEntries(), iter); iter++; ASSERT_EQ(uint32_t(3), iter.index()); ASSERT_TRUE(NULL != *iter); ASSERT_EQ(iter->is_compact(), compact_entry); ASSERT_EQ(uint32_t(3), iter->key()); ASSERT_EQ(uint32_t(0x12345678), iter->value().data); ASSERT_EQ(Res_value::TYPE_STRING, iter->value().dataType); iter++; ASSERT_EQ(v.endEntries(), iter); free(data); } } } // namespace android Loading
libs/androidfw/tests/TypeWrappers_test.cpp +103 −67 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #include <algorithm> #include <androidfw/ResourceTypes.h> #include <androidfw/TypeWrappers.h> #include <utils/String8.h> Loading @@ -22,68 +23,93 @@ namespace android { void* createTypeData() { ResTable_type t; memset(&t, 0, sizeof(t)); // create a ResTable_type in memory with a vector of Res_value* static ResTable_type* createTypeTable(std::vector<Res_value*>& values, bool compact_entry = false, bool short_offsets = false) { ResTable_type t{}; t.header.type = RES_TABLE_TYPE_TYPE; t.header.headerSize = sizeof(t); t.header.size = sizeof(t); t.id = 1; t.entryCount = 3; t.flags = short_offsets ? ResTable_type::FLAG_OFFSET16 : 0; uint32_t offsets[3]; t.entriesStart = t.header.headerSize + sizeof(offsets); t.header.size = t.entriesStart; t.header.size += values.size() * (short_offsets ? sizeof(uint16_t) : sizeof(uint32_t)); t.entriesStart = t.header.size; t.entryCount = values.size(); offsets[0] = 0; ResTable_entry e1; memset(&e1, 0, sizeof(e1)); e1.full.size = sizeof(e1); e1.full.key.index = 0; t.header.size += sizeof(e1); size_t entry_size = compact_entry ? sizeof(ResTable_entry) : sizeof(ResTable_entry) + sizeof(Res_value); for (auto const v : values) { t.header.size += v ? entry_size : 0; } Res_value v1; memset(&v1, 0, sizeof(v1)); t.header.size += sizeof(v1); uint8_t* data = (uint8_t *)malloc(t.header.size); uint8_t* p_header = data; uint8_t* p_offsets = data + t.header.headerSize; uint8_t* p_entries = data + t.entriesStart; memcpy(p_header, &t, sizeof(t)); size_t i = 0, entry_offset = 0; uint32_t k = 0; for (auto const& v : values) { if (short_offsets) { uint16_t *p = reinterpret_cast<uint16_t *>(p_offsets) + i; *p = v ? (entry_offset >> 2) & 0xffffu : 0xffffu; } else { uint32_t *p = reinterpret_cast<uint32_t *>(p_offsets) + i; *p = v ? entry_offset : ResTable_type::NO_ENTRY; } offsets[1] = ResTable_type::NO_ENTRY; if (v) { ResTable_entry entry{}; if (compact_entry) { entry.compact.key = i; entry.compact.flags = ResTable_entry::FLAG_COMPACT | (v->dataType << 8); entry.compact.data = v->data; memcpy(p_entries, &entry, sizeof(entry)); p_entries += sizeof(entry); entry_offset += sizeof(entry); } else { Res_value value{}; entry.full.size = sizeof(entry); entry.full.key.index = i; value = *v; memcpy(p_entries, &entry, sizeof(entry)); p_entries += sizeof(entry); memcpy(p_entries, &value, sizeof(value)); p_entries += sizeof(value); entry_offset += sizeof(entry) + sizeof(value); } } i++; } return reinterpret_cast<ResTable_type*>(data); } offsets[2] = sizeof(e1) + sizeof(v1); ResTable_entry e2; memset(&e2, 0, sizeof(e2)); e2.full.size = sizeof(e2); e2.full.key.index = 1; t.header.size += sizeof(e2); TEST(TypeVariantIteratorTest, shouldIterateOverTypeWithoutErrors) { std::vector<Res_value *> values; Res_value v2; memset(&v2, 0, sizeof(v2)); t.header.size += sizeof(v2); Res_value *v1 = new Res_value{}; values.push_back(v1); uint8_t* data = (uint8_t*)malloc(t.header.size); uint8_t* p = data; memcpy(p, &t, sizeof(t)); p += sizeof(t); memcpy(p, offsets, sizeof(offsets)); p += sizeof(offsets); memcpy(p, &e1, sizeof(e1)); p += sizeof(e1); memcpy(p, &v1, sizeof(v1)); p += sizeof(v1); memcpy(p, &e2, sizeof(e2)); p += sizeof(e2); memcpy(p, &v2, sizeof(v2)); p += sizeof(v2); return data; } values.push_back(nullptr); TEST(TypeVariantIteratorTest, shouldIterateOverTypeWithoutErrors) { ResTable_type* data = (ResTable_type*) createTypeData(); Res_value *v2 = new Res_value{}; values.push_back(v2); Res_value *v3 = new Res_value{ sizeof(Res_value), 0, Res_value::TYPE_STRING, 0x12345678}; values.push_back(v3); // test for combinations of compact_entry and short_offsets for (size_t i = 0; i < 4; i++) { bool compact_entry = i & 0x1, short_offsets = i & 0x2; ResTable_type* data = createTypeTable(values, compact_entry, short_offsets); TypeVariant v(data); TypeVariant::iterator iter = v.beginEntries(); ASSERT_EQ(uint32_t(0), iter.index()); ASSERT_TRUE(NULL != *iter); ASSERT_EQ(uint32_t(0), iter->full.key.index); ASSERT_EQ(uint32_t(0), iter->key()); ASSERT_NE(v.endEntries(), iter); iter++; Loading @@ -96,14 +122,24 @@ TEST(TypeVariantIteratorTest, shouldIterateOverTypeWithoutErrors) { ASSERT_EQ(uint32_t(2), iter.index()); ASSERT_TRUE(NULL != *iter); ASSERT_EQ(uint32_t(1), iter->full.key.index); ASSERT_EQ(uint32_t(2), iter->key()); ASSERT_NE(v.endEntries(), iter); iter++; ASSERT_EQ(uint32_t(3), iter.index()); ASSERT_TRUE(NULL != *iter); ASSERT_EQ(iter->is_compact(), compact_entry); ASSERT_EQ(uint32_t(3), iter->key()); ASSERT_EQ(uint32_t(0x12345678), iter->value().data); ASSERT_EQ(Res_value::TYPE_STRING, iter->value().dataType); iter++; ASSERT_EQ(v.endEntries(), iter); free(data); } } } // namespace android