bitunion.test.cc revision 13465:dee578a46d87
1/* 2 * Copyright 2014 Google, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer; 8 * redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution; 11 * neither the name of the copyright holders nor the names of its 12 * contributors may be used to endorse or promote products derived from 13 * this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * Authors: Gabe Black 28 */ 29 30#include <gtest/gtest.h> 31 32#include <cassert> 33#include <iostream> 34#include <type_traits> 35 36#include "base/bitunion.hh" 37#include "base/cprintf.hh" 38 39using namespace std; 40 41namespace { 42 43BitUnion64(SixtyFour) 44 Bitfield<39, 32> byte5; 45 Bitfield<2> bit2; 46 BitfieldRO<39, 32> byte5RO; 47 BitfieldWO<39, 32> byte5WO; 48 SubBitUnion(byte6, 47, 40) 49 Bitfield<43, 42> bits43To42; 50 Bitfield<41> bit41; 51 SignedBitfield<41> bit41Signed; 52 EndSubBitUnion(byte6) 53 SignedBitfield<47, 40> byte6Signed; 54 SignedBitfieldRO<47, 40> byte6SignedRO; 55 SignedBitfieldWO<47, 40> byte6SignedWO; 56EndBitUnion(SixtyFour) 57 58BitUnion64(EmptySixtyFour) 59EndBitUnion(EmptySixtyFour) 60 61BitUnion32(EmptyThirtyTwo) 62EndBitUnion(EmptyThirtyTwo) 63 64BitUnion16(EmptySixteen) 65EndBitUnion(EmptySixteen) 66 67BitUnion8(EmptyEight) 68EndBitUnion(EmptyEight) 69 70class SplitField 71{ 72 protected: 73 BitUnion64(In) 74 Bitfield<15, 12> high; 75 Bitfield<7, 4> low; 76 EndBitUnion(In) 77 78 BitUnion64(Out) 79 Bitfield<7, 4> high; 80 Bitfield<3, 0> low; 81 EndBitUnion(Out) 82 public: 83 uint64_t 84 getter(const uint64_t &storage) const 85 { 86 Out out = 0; 87 In in = storage; 88 out.high = in.high; 89 out.low = in.low; 90 return out; 91 } 92 93 void 94 setter(uint64_t &storage, uint64_t val) 95 { 96 Out out = val; 97 In in = 0; 98 in.high = out.high; 99 in.low = out.low; 100 storage = in; 101 } 102}; 103 104BitUnion64(Split) 105 BitfieldType<SplitField> split; 106EndBitUnion(Split) 107 108struct ContainingStruct 109{ 110 BitUnion64(Contained) 111 Bitfield<63, 60> topNibble; 112 EndBitUnion(Contained) 113 114 Contained contained; 115}; 116 117uint64_t 118containingFunc(uint64_t init_val, uint64_t fieldVal) 119{ 120 BitUnion32(Contained) 121 Bitfield<16, 15> field; 122 EndBitUnion(Contained) 123 124 Contained contained = init_val; 125 contained.field = fieldVal; 126 return contained; 127} 128 129} // anonymous namespace 130 131// Declare these as global so g++ doesn't ignore them. Initialize them in 132// various ways. 133EmptySixtyFour emptySixtyFour = 0; 134EmptyThirtyTwo emptyThirtyTwo; 135EmptySixteen emptySixteen; 136EmptyEight emptyEight(0); 137 138class BitUnionData : public testing::Test { 139 protected: 140 SixtyFour sixtyFour; 141 Split split; 142 143 void SetUp() override { sixtyFour = 0; split = 0; } 144 145 template <typename T> 146 uint64_t templatedFunction(T) { return 0; } 147 148 template <typename T> 149 uint64_t 150 templatedFunction(BitUnionType<T> u) 151 { 152 BitUnionBaseType<T> b = u; 153 return b; 154 } 155}; 156 157TEST_F(BitUnionData, NormalBitfield) 158{ 159 EXPECT_EQ(sixtyFour.byte5, 0); 160 sixtyFour.byte5 = 0xff; 161 EXPECT_EQ(sixtyFour, 0xff00000000); 162 sixtyFour.byte5 = 0xfff; 163 EXPECT_EQ(sixtyFour, 0xff00000000); 164 EXPECT_EQ(sixtyFour.byte5, 0xff); 165} 166 167TEST_F(BitUnionData, SingleBitfield) 168{ 169 EXPECT_EQ(sixtyFour.bit2, 0); 170 sixtyFour.bit2 = 0x1; 171 EXPECT_EQ(sixtyFour, 0x4); 172 EXPECT_EQ(sixtyFour.bit2, 0x1); 173} 174 175TEST_F(BitUnionData, ReadOnlyBitfield) 176{ 177 EXPECT_EQ(sixtyFour.byte5RO, 0); 178 sixtyFour.byte5 = 0xff; 179 EXPECT_EQ(sixtyFour.byte5RO, 0xff); 180} 181 182TEST_F(BitUnionData, WriteOnlyBitfield) 183{ 184 sixtyFour.byte5WO = 0xff; 185 EXPECT_EQ(sixtyFour, 0xff00000000); 186} 187 188TEST_F(BitUnionData, SubBitUnions) 189{ 190 EXPECT_EQ(sixtyFour.byte6.bit41, 0); 191 sixtyFour.byte6 = 0x2; 192 EXPECT_EQ(sixtyFour.byte6.bit41, 1); 193 sixtyFour.byte6.bits43To42 = 0x3; 194 EXPECT_EQ(sixtyFour.byte6, 0xe); 195 sixtyFour.byte6 = 0xff; 196 sixtyFour.byte6.bit41 = 0; 197 EXPECT_EQ(sixtyFour, 0xfd0000000000); 198} 199 200TEST_F(BitUnionData, SignedBitfields) 201{ 202 sixtyFour.byte6 = 0xff; 203 EXPECT_EQ(sixtyFour.byte6Signed, -1); 204 EXPECT_EQ(sixtyFour.byte6SignedRO, -1); 205 sixtyFour.byte6SignedWO = 0; 206 EXPECT_EQ(sixtyFour.byte6Signed, 0); 207 EXPECT_EQ(sixtyFour.byte6SignedRO, 0); 208 EXPECT_EQ(sixtyFour.byte6, 0); 209} 210 211TEST_F(BitUnionData, InsideStruct) 212{ 213 ContainingStruct containing; 214 containing.contained = 0; 215 containing.contained.topNibble = 0xd; 216 EXPECT_EQ(containing.contained, 0xd000000000000000); 217} 218 219TEST_F(BitUnionData, InsideFunction) 220{ 221 EXPECT_EQ(containingFunc(0xfffff, 0), 0xe7fff); 222} 223 224TEST_F(BitUnionData, BitfieldToBitfieldAssignment) 225{ 226 SixtyFour otherSixtyFour = 0; 227 sixtyFour.bit2 = 1; 228 otherSixtyFour.byte6.bit41 = sixtyFour.bit2; 229 EXPECT_EQ(otherSixtyFour, 0x20000000000); 230 otherSixtyFour.bit2 = sixtyFour.bit2; 231 EXPECT_EQ(otherSixtyFour, 0x20000000004); 232} 233 234TEST_F(BitUnionData, Operators) 235{ 236 SixtyFour otherSixtyFour = 0x4; 237 sixtyFour = otherSixtyFour; 238 EXPECT_EQ(sixtyFour, 0x4); 239 sixtyFour = 0; 240 EXPECT_TRUE(sixtyFour < otherSixtyFour); 241 EXPECT_TRUE(otherSixtyFour > sixtyFour); 242 EXPECT_TRUE(sixtyFour != otherSixtyFour); 243 sixtyFour = otherSixtyFour; 244 EXPECT_TRUE(sixtyFour == otherSixtyFour); 245} 246 247TEST_F(BitUnionData, Custom) 248{ 249 EXPECT_EQ(split, 0); 250 split.split = 0xfff; 251 EXPECT_EQ(split, 0xf0f0); 252 EXPECT_EQ((uint64_t)split.split, 0xff); 253} 254 255TEST_F(BitUnionData, Templating) 256{ 257 sixtyFour = 0xff; 258 EXPECT_EQ(templatedFunction(sixtyFour), 0xff); 259 EXPECT_EQ(templatedFunction((uint64_t)sixtyFour), 0); 260 261 BitUnion(uint64_t, Dummy64) 262 EndBitUnion(Dummy64); 263 264 BitUnion(uint32_t, Dummy32) 265 EndBitUnion(Dummy32); 266 267 bool is64; 268 is64 = std::is_same<BitUnionBaseType<Dummy64>, uint64_t>::value; 269 EXPECT_TRUE(is64); 270 is64 = std::is_same<BitUnionBaseType<Dummy32>, uint64_t>::value; 271 EXPECT_FALSE(is64); 272} 273 274TEST_F(BitUnionData, Output) 275{ 276 sixtyFour = 1234567812345678; 277 std::stringstream ss; 278 ss << sixtyFour; 279 EXPECT_EQ(ss.str(), "1234567812345678"); 280 ss.str(""); 281 282 EmptyEight eight = 65; 283 ss << eight; 284 EXPECT_EQ(ss.str(), "65"); 285 ss.str(""); 286} 287