1 /* 2 * Copyright 2016 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 //#define LOG_NDEBUG 0 18 #define LOG_TAG "Flagged_test" 19 20 #include <gtest/gtest.h> 21 22 #include <media/stagefright/foundation/Flagged.h> 23 24 namespace android { 25 26 /** 27 * Helper template that can be used to print values in static_assert error messages. 28 * 29 * Use integers here. 30 */ 31 template<bool, int ...N> 32 struct _print_as_warning { }; 33 34 template<int ...N> 35 struct _print_as_warning<true, N...> : std::true_type { }; 36 37 #define static_assert_equals(a, b, msg) \ 38 static_assert(_print_as_warning<(a) == (b), a, b>::value, msg) 39 40 class FlaggedTest : public ::testing::Test { 41 protected: 42 // empty structs 43 struct A0 { }; 44 struct A1 { }; 45 struct A_A0 : public A0 { }; 46 47 // simple struct 48 struct BB { 49 int32_t i; 50 uint32_t u; 51 }; 52 53 // struct inheriting from A0 54 struct BB_A0 : public A0 { 55 int32_t i; 56 uint32_t u; 57 }; 58 59 // struct inheriting from struct inheriting A0 60 struct BB_AA0 : public A_A0 { 61 int32_t i; 62 uint32_t u; 63 }; 64 65 // struct that wraps 66 struct WBBA0 { 67 BB_A0 b; 68 }; 69 70 struct WBBA0_A1 : public A1 { 71 BB_A0 b; 72 }; 73 74 struct WBBA0_A0 : public A0 { 75 BB_A0 b; 76 }; 77 78 struct WBB_A0 : public A0 { 79 BB b; 80 }; 81 82 struct WBBA0_AA0 : public A_A0 { 83 BB_A0 b; 84 }; 85 86 struct WBBAA0_A0 : public A0 { 87 BB_AA0 b; 88 }; 89 90 struct WWBBA0_A0 : public A0 { 91 WBBA0 b; 92 }; 93 }; 94 95 /** 96 * This test is here to confirm the handling of wrapping classes that inherit from an interface 97 * while also inheriting from that same interface. While we no longer use this construct, we want 98 * to track if this defect is ever fixed. 99 */ 100 TEST_F(FlaggedTest, StaticSanityTests) { 101 static_assert(sizeof(A0) == 1, ""); 102 static_assert(sizeof(A1) == 1, ""); 103 static_assert(sizeof(A_A0) == 1, ""); 104 105 static constexpr size_t size = sizeof(BB); // original [pair] 106 107 // inheriting from A0 does not increase size 108 static_assert(sizeof(BB_A0) == size, ""); // [pair]:A0 109 static_assert(sizeof(BB_AA0) == size, ""); // [pair]:[:A0] 110 111 // wrapping a class that inherits from A0 does not increase size 112 static_assert(sizeof(WBBA0) == size, ""); // [ [pair]:[:A0] ] 113 114 // wrapping a class that inherits from A0 while also inheriting from A1 does not increase size 115 static_assert(sizeof(WBBA0_A1) == size, ""); // [ [pair]:A0 ]:A1 116 117 // wrapping a class that inherits from A0 while also inheriting from A0 DOES increase size 118 EXPECT_GT(sizeof(WBBA0_A0), size); // [ [pair]:A0 ]:A0 119 120 // wrapping a class that does not inherit from A0 while inheriting from A0 does not increase 121 // size 122 static_assert(sizeof(WBB_A0) == size, ""); // [[pair]]:A0 123 124 // wrapping a class that inherits from A0 while also inheriting from a class that inherits 125 // from A0 does increase size 126 EXPECT_GT(sizeof(WBBA0_AA0), size); // [ [pair]:A0 ]:[:A0] 127 128 // wrapping a class that indirectly inherits from A0 while also inheriting from A0 does 129 // increase size 130 EXPECT_GT(sizeof(WBBAA0_A0), size); // [ [pair]:[:A0] ]:A0 131 132 // wrapping a class that inherits from A0 while also inheriting A0 does increase size 133 EXPECT_GT(sizeof(WWBBA0_A0), size); // [ [pair]:A0 ]:A0 134 } 135 136 enum FLAG : int32_t { 137 kMask0 = 0x0FF, 138 kFlag0_A = 0x0AA, 139 kFlag0_B = 0x0BB, 140 kFlag0_C = 0x0CC, 141 kMask1 = 0xFF0, 142 kFlag1_A = 0xAA0, 143 kFlag1_B = 0xBB0, 144 kFlag1_C = 0xCC0, 145 kMaskCommon = 0x0F0, 146 }; 147 148 TEST_F(FlaggedTest, BasicExample) { 149 enum SafeFlags : uint32_t { 150 kUnsafe, 151 kSafe, 152 kSafeMask = _Flagged_helper::minMask(kSafe), 153 }; 154 typedef Flagged<int32_t, SafeFlags, kSafeMask> safeInt32; 155 156 safeInt32 a(kUnsafe); 157 a.setFlags(kSafe); 158 a.get() = 15; 159 EXPECT_EQ(a.flags(), kSafe); 160 EXPECT_EQ(a.get(), 15); 161 162 enum OriginFlags : uint32_t { 163 kUnknown, 164 kConst, 165 kCalculated, 166 kComponent, 167 kApplication, 168 kFile, 169 kBinder, 170 kOriginMask = _Flagged_helper::minMask(kBinder), 171 }; 172 typedef Flagged<safeInt32, OriginFlags, kOriginMask> 173 trackedSafeInt32; 174 175 static_assert(sizeof(trackedSafeInt32) == sizeof(safeInt32), ""); 176 177 trackedSafeInt32 b(kConst, kSafe, 1); 178 EXPECT_EQ(b.flags(), kConst); 179 EXPECT_EQ(b.get().flags(), kSafe); 180 EXPECT_EQ(b.get().get(), 1); 181 b.setFlags(kCalculated); 182 volatile bool overflow = true; 183 b.get().setFlags(overflow ? kUnsafe : kSafe); 184 185 enum ValidatedFlags : uint32_t { 186 kUnsafeV = kUnsafe, 187 kSafeV = kSafe, 188 kValidated = kSafe | 2, 189 kSharedMaskV = kSafeMask, 190 kValidatedMask = _Flagged_helper::minMask(kValidated), 191 }; 192 typedef Flagged<safeInt32, ValidatedFlags, kValidatedMask, kSharedMaskV> validatedInt32; 193 194 validatedInt32 v(kUnsafeV, kSafe, 10); 195 EXPECT_EQ(v.flags(), kUnsafeV); 196 EXPECT_EQ(v.get().flags(), kUnsafe); // !kUnsafeV overrides kSafe 197 EXPECT_EQ(v.get().get(), 10); 198 v.setFlags(kValidated); 199 EXPECT_EQ(v.flags(), kValidated); 200 EXPECT_EQ(v.get().flags(), kSafe); 201 v.get().setFlags(kUnsafe); 202 EXPECT_EQ(v.flags(), 2); // NOTE: sharing masks with enums allows strange situations to occur 203 } 204 205 TEST_F(FlaggedTest, _Flagged_helper_Test) { 206 using helper = _Flagged_helper; 207 208 using i32 = int32_t; 209 using u32 = uint32_t; 210 using u8 = uint8_t; 211 212 // base2 213 static_assert(Flagged<i32, u32, 0u, 0u, 0>::sFlagMask == 0u, ""); 214 static_assert(Flagged<i32, u32, 0u, 0u, 0>::sFlagShift == 0, ""); 215 static_assert(Flagged<i32, u32, 0u, 0u, 0>::sEffectiveMask == 0u, ""); 216 217 static_assert(Flagged<i32, u32, 0u, 0u, 10>::sFlagMask == 0u, ""); 218 static_assert(Flagged<i32, u32, 0u, 0u, 10>::sFlagShift == 10, ""); 219 static_assert(Flagged<i32, u32, 0u, 0u, 10>::sEffectiveMask == 0u, ""); 220 221 static_assert(Flagged<i32, u32, 0u, 0u, -1>::sFlagMask == 0u, ""); 222 static_assert(Flagged<i32, u32, 0u, 0u, -1>::sFlagShift == 0, ""); 223 static_assert(Flagged<i32, u32, 0u, 0u, -1>::sEffectiveMask == 0u, ""); 224 225 static_assert(Flagged<i32, u32, 99u, 0u, 0>::sFlagMask == 99u, ""); 226 static_assert(Flagged<i32, u32, 99u, 0u, 0>::sFlagShift == 0, ""); 227 static_assert(Flagged<i32, u32, 99u, 0u, 0>::sEffectiveMask == 99u, ""); 228 229 static_assert(Flagged<i32, u32, 0x99u, 0u, 12>::sFlagMask == 0x99u, ""); 230 static_assert(Flagged<i32, u32, 0x99u, 0u, 12>::sFlagShift == 12, ""); 231 static_assert(Flagged<i32, u32, 0x99u, 0u, 12>::sEffectiveMask == 0x99000u, ""); 232 233 static_assert(Flagged<i32, u32, 99u, 0u, -1>::sFlagMask == 99u, ""); 234 static_assert(Flagged<i32, u32, 99u, 0u, -1>::sFlagShift == 0, ""); 235 static_assert(Flagged<i32, u32, 99u, 0u, -1>::sEffectiveMask == 99u, ""); 236 237 // mask_of<T, Flag> 238 // also Flagged<> no default 239 typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 0 /* shift */> i32_800f_0; 240 typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 4 /* shift */> i32_800f_4; 241 // this also tests that these types can be instantiated 242 static_assert(sizeof(i32_800f_0) >= sizeof(i32) + sizeof(u32), 243 "should be at least size of component types"); 244 static_assert(sizeof(i32_800f_4) == sizeof(i32_800f_0), "regardless of shift"); 245 static_assert(!i32_800f_0::sFlagCombined, ""); 246 static_assert(!i32_800f_4::sFlagCombined, ""); 247 248 static_assert(helper::mask_of<i32_800f_0, u32>::value == 0x800F, "incorrect mask"); 249 static_assert(helper::mask_of<i32_800f_0, i32>::value == 0, 250 "mask should be 0 when types mismatch"); 251 static_assert(helper::mask_of<i32_800f_0, u32>::effective_value == 0x800F, "incorrect mask"); 252 static_assert(helper::mask_of<i32_800f_0, i32>::effective_value == 0, 253 "mask should be 0 when types mismatch"); 254 static_assert(helper::mask_of<i32_800f_0, u32>::shift == 0, "incorrect shift"); 255 static_assert(helper::mask_of<i32_800f_0, i32>::shift == 0, 256 "shift should be 0 when types mismatch"); 257 258 static_assert(helper::mask_of<i32_800f_4, u32>::value == 0x800F, "incorrect mask"); 259 static_assert(helper::mask_of<i32_800f_4, i32>::value == 0, 260 "mask should be 0 when types mismatch"); 261 static_assert(helper::mask_of<i32_800f_4, u32>::effective_value == 0x800F0, "incorrect mask"); 262 static_assert(helper::mask_of<i32_800f_4, i32>::effective_value == 0, 263 "mask should be 0 when types mismatch"); 264 static_assert(helper::mask_of<i32_800f_4, u32>::shift == 4, "incorrect shift"); 265 static_assert(helper::mask_of<i32_800f_4, i32>::shift == 0, 266 "shift should be 0 when types mismatch"); 267 static_assert(helper::mask_of<i32, u32>::value == 0, "mask should be 0 if not masked"); 268 static_assert(helper::mask_of<i32, i32>::value == 0, "mask should be 0 if not masked"); 269 270 // lshift(value, n) 271 static_assert(helper::lshift(0U, 0) == 0U, ""); 272 static_assert(helper::lshift(0U, 30) == 0U, ""); 273 static_assert(helper::lshift(1U, 0) == 1U, ""); 274 static_assert(helper::lshift(1U, 10) == 1024U, ""); 275 static_assert(helper::lshift(10U, 10) == 10240U, ""); 276 static_assert(helper::lshift(10, 10) == 10240, ""); 277 static_assert(helper::lshift(-10, 0) == -10, ""); 278 // static_assert(helper::lshift(-10, 10) == -10240, ""); // error: left shift of negative value 279 280 // minMask(maxValue) 281 static_assert(helper::minMask(0U) == 0U, "lowest 0 bits"); 282 static_assert(helper::minMask(1U) == 1U, "lowest 1 bit"); 283 static_assert(helper::minMask(2U) == 3U, "lowest 2 bits"); 284 static_assert(helper::minMask(3U) == 3U, "lowest 2 bits"); 285 static_assert(helper::minMask(4U) == 7U, "lowest 3 bits"); 286 static_assert(helper::minMask(~0U) == ~0U, "all bits"); 287 // static_assert(helper::minMask(10) == 0xF, "all bits"); // error: must be unsigned 288 289 // topBits(n) 290 static_assert(helper::topBits<u32>(0) == 0U, "top 0 bit"); 291 static_assert(helper::topBits<u32>(1) == 0x80000000U, "top 1 bit"); 292 static_assert(helper::topBits<u32>(2) == 0xC0000000U, "top 2 bits"); 293 static_assert(helper::topBits<u32>(12) == 0xFFF00000U, "top 12 bits"); 294 static_assert(helper::topBits<u32>(32) == 0xFFFFFFFFU, "all bits"); 295 // static_assert(helper::topBits<u32>(33) == 0xFFFFFFFFU, ""); // should OVERFLOW 296 297 static_assert(helper::topBits<u8>(0) == 0U, "top 0 bit"); 298 static_assert(helper::topBits<u8>(1) == 0x80U, "top 1 bit"); 299 static_assert(helper::topBits<u8>(2) == 0xC0U, "top 2 bit"); 300 static_assert(helper::topBits<u8>(8) == 0xFFU, "all bits"); 301 // static_assert(helper::topBits<u8>(9) == 0xFFU, ""); // should OVERFLOW 302 303 // getShift(mask, base, shared, base-shift, base-effective) 304 static_assert(helper::getShift(0u, 0u, 0u, 0, 0u) == 0, "no flag require no shift"); 305 static_assert(helper::getShift(0u, 0u, 1u, 0, 0u) == -1, 306 "shared must be within mask and base mask"); 307 static_assert(helper::getShift(0u, 1u, 1u, 0, 1u) == -1, "shared must be within mask"); 308 static_assert(helper::getShift(0u, 1u, 0u, 0, 1u) == 0, 309 "no flags require no shift even with base mask"); 310 static_assert(helper::getShift(0u, 1u, 0u, 1, 2u) == 0, 311 "no flags require no shift even with shifted base mask"); 312 static_assert(helper::getShift(1u, 0u, 0u, 0, 0u) == 0, "no base mask requires no shift"); 313 static_assert(helper::getShift(1u, 1u, 0u, 0, 1u) == 1, 314 "overlapping mask and basemask requires shift"); 315 static_assert(helper::getShift(1u, 1u, 0u, 0, 1u) == 1, 316 "overlapping mask and basemask requires shift"); 317 static_assert(helper::getShift(1u, 1u, 1u, 0, 1u) == 0, 318 "shared mask requires using base shift"); 319 static_assert(helper::getShift(1u, 1u, 1u, 1, 2u) == 1, 320 "shared mask requires using base shift"); 321 static_assert(helper::getShift(3u, 5u, 1u, 0, 5u) == 0, 322 "mask and basemask that overlap only in shared region requires no shift"); 323 static_assert(helper::getShift(3u, 7u, 1u, 0, 7u) == -1, 324 "mask and basemask must not overlap in more than shared region"); 325 static_assert(helper::getShift(1u, 0u, 1u, 0, 0u) == -1, "shared must be within base mask"); 326 327 static_assert(helper::getShift(0u, 1u, 0u, 1, 1u) == -2, "effective mask must cover base mask"); 328 static_assert(helper::getShift(0u, 5u, 0u, 1, 2u) == -2, "effective mask must cover base mask"); 329 static_assert(helper::getShift(0u, 5u, 0u, 1, 10u) == 0, ""); 330 static_assert(helper::getShift(0u, 5u, 0u, 1, 31u) == 0, 331 "effective mask can be larger than base mask"); 332 333 static_assert(helper::getShift(0x800Fu, 0x800Fu, 0x800Fu, 0, 0x800Fu) == 0, 334 "(0x800F << 0) & 0x800F == 0x800F"); 335 static_assert(helper::getShift(0x800Fu, 0x800Fu, 0x800Fu, 16, 0x800F0000u) == 16, 336 "(0x800F << 0) & 0x800F == 0x800F"); 337 static_assert(helper::getShift(0x1800Fu, 0x800Fu, 0x800Fu, 0, 0x800Fu) == 0, 338 "(0x1800F << 0) & 0x800F == 0x800F"); 339 static_assert(helper::getShift(0x1800Fu, 0x800Fu, 0x800Fu, 16, 0x800F0000u) == -1, 340 "(0x1800F << 16) overflows"); 341 342 // verify that when not sharing masks, effective mask makes the difference 343 static_assert(helper::getShift(0x800Fu, 0u, 0u, 0, 0x800Fu) == 4, 344 "(0x800F << 4) & 0x800F == 0"); 345 static_assert(helper::getShift(0x800Fu, 0x2u, 0u, 0, 0x8002u) == 2, 346 "(0x800F << 2) & 0x8002 == 0"); 347 static_assert(helper::getShift(0x800Fu, 0x1u, 0u, 15, 0x8001u) == 1, 348 "(0x800F << 1) & 0x8001 == 0"); 349 static_assert(helper::getShift(0x800Fu, 0x800Fu, 0u, 16, 0x800F0000u) == 0, 350 "0x800F & 0x800F0000 == 0"); 351 static_assert(helper::getShift(0x800Fu, 0x800F8000u, 0u, 0, 0x800F8000u) == 5, 352 "(0x800F << 5) & 0x800F8000 == 0"); 353 static_assert(helper::getShift(0x800Fu, 0xF0000u, 0u, 0, 0x800F8000u) == 5, 354 "(0x800F << 5) & 0x800F8000 == 0"); 355 static_assert(helper::getShift(0x800Fu, 0x1Fu, 0u, 15, 0x800F8000u) == 5, 356 "(0x800F << 5) & 0x800F8000 == 0"); 357 static_assert(helper::getShift(0xFFu, 0x80808080u, 0u, 0, 0x80808080u) == -1, 358 "0xFF always overlaps with 0x80808080"); 359 static_assert(helper::getShift(0xFFu, 0x10001000u, 0u, 3, 0x80808080u) == -1, 360 "0xFF always overlaps with 0x80808080"); 361 static_assert(helper::getShift(0xFFu, 0x80808040u, 0u, 0, 0x80808040u) == 7, 362 "(0xFF << 7) & 0x 80808040 == 0"); 363 364 // verify min_shift (mask must be positive or no shift can be required) 365 static_assert(helper::getShift(0xFF, 0x40808040, 0, 0, 0x40808040) == 7, ""); 366 static_assert(helper::getShift((i32)0x800000FF, 0x40808040, 0, 0, 0x40808040) == -1, ""); 367 static_assert(helper::getShift(0x100000FF, 0x40808040, 0, 0, 0x40808040) == -1, ""); 368 static_assert(helper::getShift(0xFF, (i32)0x80808040, 0, 0, (i32)0x80808040) == 7, ""); 369 static_assert(helper::getShift((i32)0x80007F80, 0x40808040, 0, 0, 0x40808040) == 0, ""); 370 371 // shared mask can also be negative (but not shift can be required) 372 static_assert(helper::getShift((i32)0x80007F80, (i32)0xC0808040, (i32)0x80000000, 373 0, (i32)0xC0808040) == 0, ""); 374 static_assert(helper::getShift((i32)0x80007F80, (i32)0xC0808040, (i32)0xC0000000, 375 0, (i32)0xC0808040) == -1, ""); 376 static_assert(helper::getShift((i32)0x80007F80, (i32)0x60404020, (i32)0x60000000, 377 1, (i32)0xC0808040) == -1, ""); 378 379 // min_shift 380 typedef Flagged<i32, u32, 0u> i32_0_0; 381 typedef Flagged<i32, u32, 1u> i32_1_0; 382 typedef Flagged<i32, u32, 1u, 0u, 1> i32_1_1; 383 384 // this is a wrapper over getShift, so same test cases apply when T is flagged 385 static_assert(helper::min_shift<i32_0_0, u32, 0u, 0u>::value == 0, ""); 386 static_assert(helper::min_shift<i32_0_0, u32, 0u, 1u>::value == -1, ""); 387 static_assert(helper::min_shift<i32_1_0, u32, 0u, 1u>::value == -1, ""); 388 static_assert(helper::min_shift<i32_1_0, u32, 0u, 0u>::value == 0, ""); 389 static_assert(helper::min_shift<i32_0_0, u32, 1u, 0u>::value == 0, ""); 390 static_assert(helper::min_shift<i32_1_0, u32, 1u, 0u>::value == 1, ""); 391 static_assert(helper::min_shift<i32_1_0, u32, 1u, 1u>::value == 0, ""); 392 static_assert(helper::min_shift<i32_1_1, u32, 1u, 1u>::value == 1, ""); 393 static_assert(helper::min_shift<i32_1_1, u32, 3u, 0u>::value == 2, ""); 394 static_assert(helper::min_shift<Flagged<i32, u32, 5u>, u32, 3u, 1u>::value == 0, ""); 395 static_assert(helper::min_shift<Flagged<i32, u32, 7u>, u32, 3u, 1u>::value == -1, ""); 396 static_assert(helper::min_shift<i32_0_0, u32, 1u, 1u>::value == -1, ""); 397 398 static_assert(helper::min_shift<i32_800f_0, u32, 0x800Fu, 0u>::value == 4, ""); 399 static_assert(helper::min_shift<i32_800f_4, u32, 0x1800Fu, 0x800Fu>::value == 4, ""); 400 static_assert(helper::min_shift<i32_800f_4, u32, 0x800Fu, 0u>::value == 0, ""); 401 static_assert(helper::min_shift<Flagged<i32, u32, 0x8002u>, u32, 0x800Fu, 0u>::value == 2, ""); 402 static_assert(helper::min_shift<Flagged<i32, u32, 0x8001u>, u32, 0x800Fu, 0u>::value == 1, ""); 403 static_assert( 404 helper::min_shift<Flagged<i32, u32, 0x800Fu, 0u, 16>, u32, 0x800Fu, 0u>::value == 0, ""); 405 static_assert( 406 helper::min_shift<Flagged<i32, u32, 0x800F8000u>, u32, 0x800Fu, 0u>::value == 5, ""); 407 static_assert( 408 helper::min_shift<Flagged<i32, u32, 0x80808080u>, u32, 0xFFu, 0u>::value == -1, ""); 409 static_assert( 410 helper::min_shift<Flagged<i32, u32, 0x80808040u>, u32, 0xFFu, 0u>::value == 7, ""); 411 412 // for min_shift, non-tagged type behaves as if having base mask of 0 413 static_assert(helper::min_shift<i32, u32, 0u, 0u>::value == 0, ""); 414 static_assert(helper::min_shift<u32, u32, 0u, 0u>::value == 0, ""); 415 static_assert(helper::min_shift<i32, u32, 0u, 0u>::value == 0, ""); 416 static_assert(helper::min_shift<i32, u32, 0u, 1u>::value == -1, ""); 417 static_assert(helper::min_shift<i32, u32, 1u, 0u>::value == 0, ""); 418 static_assert(helper::min_shift<i32, u32, 1u, 1u>::value == -1, ""); 419 420 // verify min_shift (mask must be positive or no shift can be required) 421 static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>, i32, 0xFF, 0>::value == 7, ""); 422 static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>, 423 i32, (i32)0x800000FF, 0>::value == -1, ""); 424 static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>, 425 i32, 0x100000FF, 0>::value == -1, ""); 426 static_assert(helper::min_shift<Flagged<i32, i32, (i32)0x80808040>, 427 i32, 0xFF, 0>::value == 7, ""); 428 static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>, 429 i32, (i32)0x80007F80, 0>::value == 0, ""); 430 431 static_assert(helper::min_shift<Flagged<i32, i32, (i32)0x80808040>, 432 i32, (i32)0x80007F80, (i32)0x80000000>::value == 0, ""); 433 static_assert(helper::min_shift<Flagged<i32, i32, (i32)0xC0808040>, 434 i32, (i32)0x80007F80, (i32)0xC0000000>::value == -1, ""); 435 // note: cannot create a flagged type with signed flag and shift 436 // static_assert(helper::min_shift<Flagged<i32, i32, (i32)0x60404020, 0, 1>, 437 // i32, (i32)0x40003FC0, (i32)0x40000000>::value == -1, ""); 438 439 typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 16 /* shift */> i32_800f_16; 440 static_assert_equals(sizeof(i32_800f_16), sizeof(i32_800f_0), ""); 441 // shifted mask overflows! 442 // typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 17 /* shift */> i32_800f_17; 443 // static_assert(sizeof(i32_800f_17) == sizeof(i32_800f_0), ""); 444 typedef Flagged<i32, i32, 0x800F /* mask */, 0 /* shared mask */, 15 /* shift */> i32_800f_15i; 445 static_assert_equals(sizeof(i32_800f_15i), sizeof(i32_800f_0), ""); 446 // shifted mask overflows! 447 // typedef Flagged<i32, i32, 0x800F /* mask */, 0 /* shared mask */, 16 /* shift */> i32_800f_16i; 448 // static_assert(sizeof(i32_800f_16i) == sizeof(i32_800f_0), ""); 449 450 // canCombine(mask, base, shared, shift, base-shift, base-effective) 451 static_assert(helper::canCombine(0u, 0u, 0u, 0, 0, 0u), "using no mask is valid"); 452 static_assert(helper::canCombine(0u, 0u, 0u, 0, 0, 0u), ""); 453 static_assert(helper::canCombine(0u, 0u, 0u, 4, 0, 0u), ""); 454 static_assert(!helper::canCombine(0u, 0u, 1u, 0, 0, 0u), 455 "shared mask must be the overlap of masks"); 456 static_assert(helper::canCombine(1u, 0u, 0u, 0, 0, 0u), ""); 457 static_assert(helper::canCombine(1u, 0u, 0u, 4, 0, 0u), ""); 458 static_assert(helper::canCombine(3u, 5u, 1u, 0, 0, 5u), ""); 459 static_assert(!helper::canCombine(3u, 3u, 3u, 1, 0, 3u), "shift must match when sharing mask"); 460 static_assert(helper::canCombine(3u, 3u, 3u, 1, 1, 6u), ""); 461 static_assert(!helper::canCombine(3u, 3u, 3u, 1, 2, 12u), "shift must match when sharing mask"); 462 static_assert(!helper::canCombine(3u, 7u, 1u, 0, 0, 7u), ""); 463 static_assert(!helper::canCombine(1u, 0u, 1u, 0, 0, 0u), ""); 464 465 static_assert(!helper::canCombine(0u, 1u, 1u, 0, 0, 1u), 466 "shared mask must be the overlap of masks"); 467 static_assert(helper::canCombine(0u, 1u, 0u, 0, 0, 1u), ""); 468 static_assert(helper::canCombine(0u, 1u, 0u, 4, 0, 1u), ""); 469 static_assert(helper::canCombine(1u, 1u, 0u, 1, 0, 1u), ""); 470 static_assert(!helper::canCombine(1u, 1u, 0u, 0, 0, 1u), ""); 471 static_assert(helper::canCombine(1u, 1u, 0u, 1, 0, 1u), ""); 472 static_assert(helper::canCombine(1u, 1u, 1u, 0, 0, 1u), ""); 473 static_assert(!helper::canCombine(1u, 1u, 1u, 1, 0, 1u), "shift must match when sharing mask"); 474 475 static_assert(helper::canCombine(0x800Fu, 0x800Fu, 0u, 4, 0, 0x800Fu), ""); 476 static_assert(!helper::canCombine(0x800Fu, 0x800Fu, 0u, 1, 0, 0x800Fu), ""); 477 static_assert(helper::canCombine(0x800Fu, 0x8002u, 0u, 2, 0, 0x8002u), ""); 478 static_assert(helper::canCombine(0x800Fu, 0x8001u, 0u, 1, 0, 0x8001u), ""); 479 static_assert(helper::canCombine(0x800Fu, 0x800Fu, 0u, 0, 16, 0x800F0000u), ""); 480 static_assert(helper::canCombine(0x800Fu, 0x800Fu, 0x800Fu, 16, 16, 0x800F0000u), ""); 481 static_assert(!helper::canCombine(0x1800Fu, 0x800Fu, 0u, 0, 16, 0x800F0000u), ""); 482 static_assert(!helper::canCombine(0x1800Fu, 0x800Fu, 0x800Fu, 16, 16, 0x800F0000u), ""); 483 static_assert(helper::canCombine(0x800Fu, 0x800F8000u, 0u, 8, 0, 0x800F8000u), ""); 484 static_assert(!helper::canCombine(0xFFu, 0x80808080u, 0u, -1, 0, 0x80808080u), ""); 485 static_assert(helper::canCombine(0xFFu, 0x80808040u, 0u, 7, 0, 0x80808040u), ""); 486 static_assert(helper::canCombine(0xFFu, 0x8000u, 0u, 7, 0, 0x80808040u), ""); 487 static_assert(helper::canCombine(0xFFu, 0x101u, 0u, 7, 15, 0x80808040u), ""); 488 489 // can combine signed-flagged types only if mask is positive or no shift is required 490 static_assert(!helper::canCombine(0xFF, 0x40808040, 0, 0, 0, 0x40808040), ""); 491 static_assert(helper::canCombine(0xFF, 0x40808040, 0, 7, 0, 0x40808040), ""); 492 static_assert(!helper::canCombine((i32)0x800000FF, 0x40808040, 0, 0, 0, 0x40808040), ""); 493 static_assert(!helper::canCombine((i32)0x800000FF, 0x40808040, 0, 7, 0, 0x40808040), ""); 494 static_assert(!helper::canCombine(0x100000FF, 0x40808040, 0, 0, 0, 0x40808040), ""); 495 static_assert(!helper::canCombine(0x100000FF, 0x40808040, 0, 7, 0, 0x40808040), ""); 496 static_assert(!helper::canCombine(0xFF, (i32)0x80808040, 0, 0, 0, (i32)0x80808040), ""); 497 static_assert(helper::canCombine(0xFF, (i32)0x80808040, 0, 7, 0, (i32)0x80808040), ""); 498 static_assert(helper::canCombine((i32)0x80007F80, 0x40808040, 0, 0, 0, 0x40808040), ""); 499 500 static_assert(helper::canCombine((i32)0x80007F80, (i32)0x80808040, (i32)0x80000000, 0, 0, (i32)0x80808040), ""); 501 static_assert(!helper::canCombine((i32)0xC0007F80, (i32)0x80808040, (i32)0xC0000000, 0, 0, (i32)0x80808040), ""); 502 static_assert(!helper::canCombine((i32)0x80007F80, (i32)0x80808040, (i32)0x80000000, 1, 0, (i32)0x80808040), ""); 503 static_assert(!helper::canCombine((i32)0xC0007F80, (i32)0x80808040, (i32)0xC0000000, 1, 0, (i32)0x80808040), ""); 504 505 // can_combine<T, Flag, MASK, [SHARED_MASK], [SHIFT] 506 static_assert(helper::can_combine<i32_0_0, u32, 0u>::value, ""); 507 static_assert(helper::can_combine<i32_0_0, u32, 0u, 0u>::value, ""); 508 static_assert(helper::can_combine<i32_0_0, u32, 0u, 0u, 4>::value, ""); 509 static_assert(!helper::can_combine<i32_0_0, u32, 0u, 1u>::value, ""); 510 static_assert(helper::can_combine<i32_0_0, u32, 1u, 0u>::value, ""); 511 static_assert(helper::can_combine<i32_0_0, u32, 1u, 0u, 4>::value, ""); 512 static_assert(!helper::can_combine<i32_0_0, u32, 1u, 1u>::value, ""); 513 514 static_assert(!helper::can_combine<i32_1_0, u32, 0u, 1u>::value, ""); 515 static_assert(helper::can_combine<i32_1_0, u32, 0u, 0u>::value, ""); 516 static_assert(helper::can_combine<i32_1_0, u32, 0u, 0u, 4>::value, ""); 517 static_assert(helper::can_combine<i32_1_0, u32, 1u, 0u>::value, ""); 518 static_assert(!helper::can_combine<i32_1_0, u32, 1u, 0u, 0>::value, ""); 519 static_assert(helper::can_combine<i32_1_0, u32, 1u, 0u, 1>::value, ""); 520 static_assert(helper::can_combine<i32_1_0, u32, 1u, 1u>::value, ""); 521 static_assert(helper::can_combine<i32_1_0, u32, 1u, 1u, 0>::value, ""); 522 static_assert(!helper::can_combine<i32_1_0, u32, 1u, 1u, 1>::value, 523 "shouldn't be able to use SHIFT with SHARED_MASK"); 524 525 static_assert(helper::can_combine<i32_800f_0, u32, 0x800Fu, 0u, 4>::value, ""); 526 static_assert(!helper::can_combine<i32_800f_0, u32, 0x800Fu, 0u, 1>::value, ""); 527 static_assert(helper::can_combine<i32_800f_0, u32, 0x800Fu, 0u>::value, ""); 528 static_assert(helper::can_combine<Flagged<i32, u32, 0x8002u>, u32, 0x800Fu, 0u>::value, ""); 529 static_assert(helper::can_combine<Flagged<i32, u32, 0x8001u>, u32, 0x800Fu, 0u>::value, ""); 530 static_assert(helper::can_combine<Flagged<i32, u32, 0x800F0000u>, u32, 0x800Fu, 0u>::value, ""); 531 static_assert(helper::can_combine<Flagged<i32, u32, 0x800F8000u>, u32, 0x800Fu, 0u>::value, ""); 532 static_assert(!helper::can_combine<Flagged<i32, u32, 0x80808080u>, u32, 0xFFu, 0u>::value, ""); 533 static_assert(helper::can_combine<Flagged<i32, u32, 0x80808040u>, u32, 0xFFu, 0u>::value, ""); 534 535 // can combine signed-flagged types only if mask is positive or no shift is required 536 static_assert(helper::can_combine<Flagged<i32, i32, 0x40808040>, i32, 0xFF, 0>::value, ""); 537 static_assert(!helper::can_combine<Flagged<i32, i32, 0x40808040>, 538 i32, (i32)0x800000FF, 0>::value, ""); 539 static_assert(!helper::can_combine<Flagged<i32, i32, 0x40808040>, 540 i32, 0x100000FF, 0>::value, ""); 541 static_assert(helper::can_combine<Flagged<i32, i32, (i32)0x80808040>, i32, 0xFF, 0>::value, ""); 542 static_assert(helper::can_combine<Flagged<i32, i32, 0x40808040>, 543 i32, (i32)0x80007F80, 0>::value, ""); 544 545 static_assert(helper::can_combine<Flagged<i32, i32, (i32)0x80808040>, 546 i32, (i32)0x80007F80, (i32)0x80000000>::value, ""); 547 static_assert(!helper::can_combine<Flagged<i32, i32, (i32)0xC0808040>, 548 i32, (i32)0x80007F80, (i32)0xC0000000>::value, ""); 549 550 static_assert(helper::min_shift<Flagged<i32, FLAG, (FLAG)0x80808040>, 551 FLAG, (FLAG)0x80007F80, (FLAG)0x80000000>::value == 0, ""); 552 static_assert(helper::can_combine<Flagged<i32, FLAG, (FLAG)0x80808040>, 553 FLAG, (FLAG)0x80007F80, (FLAG)0x80000000>::value, ""); 554 555 // cannot combine non-tagged types 556 static_assert(!helper::can_combine<i32, u32, 0u, 0u>::value, ""); 557 static_assert(!helper::can_combine<u32, u32, 0u, 0u>::value, ""); 558 static_assert(!helper::can_combine<i32, u32, 0u, 0u>::value, ""); 559 static_assert(!helper::can_combine<i32, u32, 0u, 1u>::value, ""); 560 static_assert(!helper::can_combine<i32, u32, 1u, 0u>::value, ""); 561 static_assert(!helper::can_combine<i32, u32, 1u, 1u>::value, ""); 562 563 typedef Flagged<i32_800f_0, u32, 0x800F /* mask */, 0 /* shared mask */> i32_800f_800f; 564 static_assert(i32_800f_800f::sFlagMask == 0x800F, ""); 565 static_assert(i32_800f_800f::sFlagShift == 4, ""); 566 static_assert(i32_800f_800f::sEffectiveMask == 0x880FF, ""); 567 static_assert(!i32_800f_0::sFlagCombined, ""); 568 static_assert(!i32_800f_4::sFlagCombined, ""); 569 570 static_assert(i32_800f_800f::sFlagCombined, ""); 571 static_assert_equals(sizeof(i32_800f_800f), sizeof(i32_800f_0), ""); 572 573 typedef Flagged<i32_800f_0, u32, 0x1FFFF /* mask */> i32_800f_1ffff; 574 static_assert(i32_800f_1ffff::sFlagMask == 0x1FFFF, ""); 575 static_assert(i32_800f_1ffff::sFlagShift == 0, ""); 576 static_assert(i32_800f_1ffff::sEffectiveMask == 0x1FFFF, ""); 577 static_assert(!i32_800f_1ffff::sFlagCombined, ""); 578 579 // operational tests 580 i32_800f_800f val(0x8000, 0x1234, 56); 581 EXPECT_EQ(val.get().get(), 56); 582 EXPECT_EQ(val.flags(), 0x8000u); 583 EXPECT_EQ(val.get().flags(), 0x1234u & 0x800F); 584 val.setFlags(0x12345); 585 EXPECT_EQ(val.flags(), 0x12345u & 0x800F); 586 EXPECT_EQ(val.get().flags(), 0x1234u & 0x800F); 587 val.get().setFlags(0x54321); 588 EXPECT_EQ(val.flags(), 0x12345u & 0x800F); 589 EXPECT_EQ(val.get().flags(), 0x54321u & 0x800F); 590 EXPECT_EQ(val.get().get(), 56); 591 592 typedef Flagged<i32_800f_4, u32, 0x800F /* mask */, 0 /* shared mask */> i32_800f_800f_B; 593 static_assert(i32_800f_800f_B::sFlagMask == 0x800F, ""); 594 static_assert(i32_800f_800f_B::sFlagShift == 0, ""); 595 static_assert(i32_800f_800f_B::sEffectiveMask == 0x880FF, ""); 596 597 i32_800f_800f_B valB(0x8000, 0x1234, -987); 598 EXPECT_EQ(valB.get().get(), -987); 599 EXPECT_EQ(valB.flags(), 0x8000u); 600 EXPECT_EQ(valB.get().flags(), 0x1234u & 0x800F); 601 valB.setFlags(0x12345); 602 EXPECT_EQ(valB.flags(), 0x12345u & 0x800F); 603 EXPECT_EQ(valB.get().flags(), 0x1234u & 0x800F); 604 valB.get().setFlags(0x5C321); 605 EXPECT_EQ(valB.flags(), 0x12345u & 0x800F); 606 EXPECT_EQ(valB.get().flags(), 0x5C321u & 0x800F); 607 EXPECT_EQ(valB.get().get(), -987); 608 609 typedef Flagged<Flagged<i32, u32, 0xFF>, u32, 0xFF0, 0xF0> i32_ff_ff0; 610 i32_ff_ff0 valC(0xABCD, 0x1234, 101); 611 EXPECT_EQ(valC.get().get(), 101); 612 EXPECT_EQ(valC.flags(), 0xBC0u); 613 EXPECT_EQ(valC.get().flags(), 0xC4u); 614 valC.setFlags(0x12345); 615 EXPECT_EQ(valC.flags(), 0x340u); 616 EXPECT_EQ(valC.get().flags(), 0x44u); 617 valC.get().setFlags(0x54321); 618 EXPECT_EQ(valC.flags(), 0x320u); 619 EXPECT_EQ(valC.get().flags(), 0x21u); 620 EXPECT_EQ(valC.get().get(), 101); 621 622 // when combining flags (with no shift), it should work with signed flags 623 typedef Flagged<Flagged<i32, FLAG, kMask0>, FLAG, kMask1, kMaskCommon> i32_F_ff_ff0; 624 static_assert(i32_F_ff_ff0::sFlagCombined, "flags should be combined"); 625 626 i32_F_ff_ff0 valD(kFlag1_A, kFlag0_A, 1023); 627 EXPECT_EQ(valD.get().get(), 1023); 628 EXPECT_EQ(valD.flags(), kFlag1_A); 629 EXPECT_EQ(valD.get().flags(), kFlag0_A); 630 valD.setFlags(kFlag1_B); 631 EXPECT_EQ(valD.flags(), kFlag1_B); 632 EXPECT_EQ(valD.get().flags(), FLAG(0x0BA)); 633 valD.get().setFlags(kFlag0_C); 634 EXPECT_EQ(valD.flags(), FLAG(0xBC0)); 635 EXPECT_EQ(valD.get().flags(), kFlag0_C); 636 EXPECT_EQ(valD.get().get(), 1023); 637 } 638 639 } // namespace android 640