1 /* 2 * Copyright (C) 2014 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 <algorithm> 18 #include <androidfw/ResourceTypes.h> 19 #include <androidfw/TypeWrappers.h> 20 #include <utils/String8.h> 21 22 #include <gtest/gtest.h> 23 24 namespace android { 25 26 // create a ResTable_type in memory with a vector of Res_value* createTypeTable(std::vector<Res_value * > & values,bool compact_entry=false,bool short_offsets=false)27 static ResTable_type* createTypeTable(std::vector<Res_value*>& values, 28 bool compact_entry = false, 29 bool short_offsets = false) 30 { 31 ResTable_type t{}; 32 t.header.type = RES_TABLE_TYPE_TYPE; 33 t.header.headerSize = sizeof(t); 34 t.header.size = sizeof(t); 35 t.id = 1; 36 t.flags = short_offsets ? ResTable_type::FLAG_OFFSET16 : 0; 37 38 t.header.size += values.size() * (short_offsets ? sizeof(uint16_t) : sizeof(uint32_t)); 39 t.entriesStart = t.header.size; 40 t.entryCount = values.size(); 41 42 size_t entry_size = compact_entry ? sizeof(ResTable_entry) 43 : sizeof(ResTable_entry) + sizeof(Res_value); 44 for (auto const v : values) { 45 t.header.size += v ? entry_size : 0; 46 } 47 48 uint8_t* data = (uint8_t *)malloc(t.header.size); 49 uint8_t* p_header = data; 50 uint8_t* p_offsets = data + t.header.headerSize; 51 uint8_t* p_entries = data + t.entriesStart; 52 53 memcpy(p_header, &t, sizeof(t)); 54 55 size_t i = 0, entry_offset = 0; 56 uint32_t k = 0; 57 for (auto const& v : values) { 58 if (short_offsets) { 59 uint16_t *p = reinterpret_cast<uint16_t *>(p_offsets) + i; 60 *p = v ? (entry_offset >> 2) & 0xffffu : 0xffffu; 61 } else { 62 uint32_t *p = reinterpret_cast<uint32_t *>(p_offsets) + i; 63 *p = v ? entry_offset : ResTable_type::NO_ENTRY; 64 } 65 66 if (v) { 67 ResTable_entry entry{}; 68 if (compact_entry) { 69 entry.compact.key = i; 70 entry.compact.flags = ResTable_entry::FLAG_COMPACT | (v->dataType << 8); 71 entry.compact.data = v->data; 72 memcpy(p_entries, &entry, sizeof(entry)); p_entries += sizeof(entry); 73 entry_offset += sizeof(entry); 74 } else { 75 Res_value value{}; 76 entry.full.size = sizeof(entry); 77 entry.full.key.index = i; 78 value = *v; 79 memcpy(p_entries, &entry, sizeof(entry)); p_entries += sizeof(entry); 80 memcpy(p_entries, &value, sizeof(value)); p_entries += sizeof(value); 81 entry_offset += sizeof(entry) + sizeof(value); 82 } 83 } 84 i++; 85 } 86 return reinterpret_cast<ResTable_type*>(data); 87 } 88 TEST(TypeVariantIteratorTest,shouldIterateOverTypeWithoutErrors)89 TEST(TypeVariantIteratorTest, shouldIterateOverTypeWithoutErrors) { 90 std::vector<Res_value *> values; 91 92 Res_value *v1 = new Res_value{}; 93 values.push_back(v1); 94 95 values.push_back(nullptr); 96 97 Res_value *v2 = new Res_value{}; 98 values.push_back(v2); 99 100 Res_value *v3 = new Res_value{ sizeof(Res_value), 0, Res_value::TYPE_STRING, 0x12345678}; 101 values.push_back(v3); 102 103 // test for combinations of compact_entry and short_offsets 104 for (size_t i = 0; i < 4; i++) { 105 bool compact_entry = i & 0x1, short_offsets = i & 0x2; 106 ResTable_type* data = createTypeTable(values, compact_entry, short_offsets); 107 TypeVariant v(data); 108 109 TypeVariant::iterator iter = v.beginEntries(); 110 ASSERT_EQ(uint32_t(0), iter.index()); 111 ASSERT_TRUE(NULL != *iter); 112 ASSERT_EQ(uint32_t(0), iter->key()); 113 ASSERT_NE(v.endEntries(), iter); 114 115 iter++; 116 117 ASSERT_EQ(uint32_t(1), iter.index()); 118 ASSERT_TRUE(NULL == *iter); 119 ASSERT_NE(v.endEntries(), iter); 120 121 iter++; 122 123 ASSERT_EQ(uint32_t(2), iter.index()); 124 ASSERT_TRUE(NULL != *iter); 125 ASSERT_EQ(uint32_t(2), iter->key()); 126 ASSERT_NE(v.endEntries(), iter); 127 128 iter++; 129 130 ASSERT_EQ(uint32_t(3), iter.index()); 131 ASSERT_TRUE(NULL != *iter); 132 ASSERT_EQ(iter->is_compact(), compact_entry); 133 ASSERT_EQ(uint32_t(3), iter->key()); 134 ASSERT_EQ(uint32_t(0x12345678), iter->value().data); 135 ASSERT_EQ(Res_value::TYPE_STRING, iter->value().dataType); 136 137 iter++; 138 139 ASSERT_EQ(v.endEntries(), iter); 140 141 free(data); 142 } 143 } 144 145 } // namespace android 146