Home | History | Annotate | Download | only in tests
      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