113465Sgabeblack@google.com/* 213465Sgabeblack@google.com * Copyright 2014 Google, Inc. 313465Sgabeblack@google.com * 413465Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 513465Sgabeblack@google.com * modification, are permitted provided that the following conditions are 613465Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 713465Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 813465Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 913465Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1013465Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1113465Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1213465Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1313465Sgabeblack@google.com * this software without specific prior written permission. 1413465Sgabeblack@google.com * 1513465Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1613465Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1713465Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1813465Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1913465Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2013465Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2113465Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2213465Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2313465Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2413465Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2513465Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2613465Sgabeblack@google.com * 2713465Sgabeblack@google.com * Authors: Gabe Black 2813465Sgabeblack@google.com */ 2913465Sgabeblack@google.com 3013465Sgabeblack@google.com#include <gtest/gtest.h> 3113465Sgabeblack@google.com 3213465Sgabeblack@google.com#include <cassert> 3313465Sgabeblack@google.com#include <iostream> 3413465Sgabeblack@google.com#include <type_traits> 3513465Sgabeblack@google.com 3613465Sgabeblack@google.com#include "base/bitunion.hh" 3713465Sgabeblack@google.com#include "base/cprintf.hh" 3813465Sgabeblack@google.com 3913465Sgabeblack@google.comusing namespace std; 4013465Sgabeblack@google.com 4113465Sgabeblack@google.comnamespace { 4213465Sgabeblack@google.com 4313465Sgabeblack@google.comBitUnion64(SixtyFour) 4413465Sgabeblack@google.com Bitfield<39, 32> byte5; 4513465Sgabeblack@google.com Bitfield<2> bit2; 4613465Sgabeblack@google.com BitfieldRO<39, 32> byte5RO; 4713465Sgabeblack@google.com BitfieldWO<39, 32> byte5WO; 4813465Sgabeblack@google.com SubBitUnion(byte6, 47, 40) 4913465Sgabeblack@google.com Bitfield<43, 42> bits43To42; 5013465Sgabeblack@google.com Bitfield<41> bit41; 5113465Sgabeblack@google.com SignedBitfield<41> bit41Signed; 5213465Sgabeblack@google.com EndSubBitUnion(byte6) 5313465Sgabeblack@google.com SignedBitfield<47, 40> byte6Signed; 5413465Sgabeblack@google.com SignedBitfieldRO<47, 40> byte6SignedRO; 5513465Sgabeblack@google.com SignedBitfieldWO<47, 40> byte6SignedWO; 5613465Sgabeblack@google.comEndBitUnion(SixtyFour) 5713465Sgabeblack@google.com 5813465Sgabeblack@google.comBitUnion64(EmptySixtyFour) 5913465Sgabeblack@google.comEndBitUnion(EmptySixtyFour) 6013465Sgabeblack@google.com 6113465Sgabeblack@google.comBitUnion32(EmptyThirtyTwo) 6213465Sgabeblack@google.comEndBitUnion(EmptyThirtyTwo) 6313465Sgabeblack@google.com 6413465Sgabeblack@google.comBitUnion16(EmptySixteen) 6513465Sgabeblack@google.comEndBitUnion(EmptySixteen) 6613465Sgabeblack@google.com 6713465Sgabeblack@google.comBitUnion8(EmptyEight) 6813465Sgabeblack@google.comEndBitUnion(EmptyEight) 6913465Sgabeblack@google.com 7013465Sgabeblack@google.comclass SplitField 7113465Sgabeblack@google.com{ 7213465Sgabeblack@google.com protected: 7313465Sgabeblack@google.com BitUnion64(In) 7413465Sgabeblack@google.com Bitfield<15, 12> high; 7513465Sgabeblack@google.com Bitfield<7, 4> low; 7613465Sgabeblack@google.com EndBitUnion(In) 7713465Sgabeblack@google.com 7813465Sgabeblack@google.com BitUnion64(Out) 7913465Sgabeblack@google.com Bitfield<7, 4> high; 8013465Sgabeblack@google.com Bitfield<3, 0> low; 8113465Sgabeblack@google.com EndBitUnion(Out) 8213465Sgabeblack@google.com public: 8313465Sgabeblack@google.com uint64_t 8413465Sgabeblack@google.com getter(const uint64_t &storage) const 8513465Sgabeblack@google.com { 8613465Sgabeblack@google.com Out out = 0; 8713465Sgabeblack@google.com In in = storage; 8813465Sgabeblack@google.com out.high = in.high; 8913465Sgabeblack@google.com out.low = in.low; 9013465Sgabeblack@google.com return out; 9113465Sgabeblack@google.com } 9213465Sgabeblack@google.com 9313465Sgabeblack@google.com void 9413465Sgabeblack@google.com setter(uint64_t &storage, uint64_t val) 9513465Sgabeblack@google.com { 9613465Sgabeblack@google.com Out out = val; 9713465Sgabeblack@google.com In in = 0; 9813465Sgabeblack@google.com in.high = out.high; 9913465Sgabeblack@google.com in.low = out.low; 10013465Sgabeblack@google.com storage = in; 10113465Sgabeblack@google.com } 10213465Sgabeblack@google.com}; 10313465Sgabeblack@google.com 10413465Sgabeblack@google.comBitUnion64(Split) 10513465Sgabeblack@google.com BitfieldType<SplitField> split; 10613465Sgabeblack@google.comEndBitUnion(Split) 10713465Sgabeblack@google.com 10813465Sgabeblack@google.comstruct ContainingStruct 10913465Sgabeblack@google.com{ 11013465Sgabeblack@google.com BitUnion64(Contained) 11113465Sgabeblack@google.com Bitfield<63, 60> topNibble; 11213465Sgabeblack@google.com EndBitUnion(Contained) 11313465Sgabeblack@google.com 11413465Sgabeblack@google.com Contained contained; 11513465Sgabeblack@google.com}; 11613465Sgabeblack@google.com 11713465Sgabeblack@google.comuint64_t 11813465Sgabeblack@google.comcontainingFunc(uint64_t init_val, uint64_t fieldVal) 11913465Sgabeblack@google.com{ 12013465Sgabeblack@google.com BitUnion32(Contained) 12113465Sgabeblack@google.com Bitfield<16, 15> field; 12213465Sgabeblack@google.com EndBitUnion(Contained) 12313465Sgabeblack@google.com 12413465Sgabeblack@google.com Contained contained = init_val; 12513465Sgabeblack@google.com contained.field = fieldVal; 12613465Sgabeblack@google.com return contained; 12713465Sgabeblack@google.com} 12813465Sgabeblack@google.com 12913465Sgabeblack@google.com} // anonymous namespace 13013465Sgabeblack@google.com 13113465Sgabeblack@google.com// Declare these as global so g++ doesn't ignore them. Initialize them in 13213465Sgabeblack@google.com// various ways. 13313465Sgabeblack@google.comEmptySixtyFour emptySixtyFour = 0; 13413465Sgabeblack@google.comEmptyThirtyTwo emptyThirtyTwo; 13513465Sgabeblack@google.comEmptySixteen emptySixteen; 13613465Sgabeblack@google.comEmptyEight emptyEight(0); 13713465Sgabeblack@google.com 13813465Sgabeblack@google.comclass BitUnionData : public testing::Test { 13913465Sgabeblack@google.com protected: 14013465Sgabeblack@google.com SixtyFour sixtyFour; 14113465Sgabeblack@google.com Split split; 14213465Sgabeblack@google.com 14313465Sgabeblack@google.com void SetUp() override { sixtyFour = 0; split = 0; } 14413465Sgabeblack@google.com 14513465Sgabeblack@google.com template <typename T> 14613465Sgabeblack@google.com uint64_t templatedFunction(T) { return 0; } 14713465Sgabeblack@google.com 14813465Sgabeblack@google.com template <typename T> 14913465Sgabeblack@google.com uint64_t 15013465Sgabeblack@google.com templatedFunction(BitUnionType<T> u) 15113465Sgabeblack@google.com { 15213465Sgabeblack@google.com BitUnionBaseType<T> b = u; 15313465Sgabeblack@google.com return b; 15413465Sgabeblack@google.com } 15513465Sgabeblack@google.com}; 15613465Sgabeblack@google.com 15713465Sgabeblack@google.comTEST_F(BitUnionData, NormalBitfield) 15813465Sgabeblack@google.com{ 15913465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte5, 0); 16013465Sgabeblack@google.com sixtyFour.byte5 = 0xff; 16113465Sgabeblack@google.com EXPECT_EQ(sixtyFour, 0xff00000000); 16213465Sgabeblack@google.com sixtyFour.byte5 = 0xfff; 16313465Sgabeblack@google.com EXPECT_EQ(sixtyFour, 0xff00000000); 16413465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte5, 0xff); 16513465Sgabeblack@google.com} 16613465Sgabeblack@google.com 16713465Sgabeblack@google.comTEST_F(BitUnionData, SingleBitfield) 16813465Sgabeblack@google.com{ 16913465Sgabeblack@google.com EXPECT_EQ(sixtyFour.bit2, 0); 17013465Sgabeblack@google.com sixtyFour.bit2 = 0x1; 17113465Sgabeblack@google.com EXPECT_EQ(sixtyFour, 0x4); 17213465Sgabeblack@google.com EXPECT_EQ(sixtyFour.bit2, 0x1); 17313465Sgabeblack@google.com} 17413465Sgabeblack@google.com 17513465Sgabeblack@google.comTEST_F(BitUnionData, ReadOnlyBitfield) 17613465Sgabeblack@google.com{ 17713465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte5RO, 0); 17813465Sgabeblack@google.com sixtyFour.byte5 = 0xff; 17913465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte5RO, 0xff); 18013465Sgabeblack@google.com} 18113465Sgabeblack@google.com 18213465Sgabeblack@google.comTEST_F(BitUnionData, WriteOnlyBitfield) 18313465Sgabeblack@google.com{ 18413465Sgabeblack@google.com sixtyFour.byte5WO = 0xff; 18513465Sgabeblack@google.com EXPECT_EQ(sixtyFour, 0xff00000000); 18613465Sgabeblack@google.com} 18713465Sgabeblack@google.com 18813465Sgabeblack@google.comTEST_F(BitUnionData, SubBitUnions) 18913465Sgabeblack@google.com{ 19013465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte6.bit41, 0); 19113465Sgabeblack@google.com sixtyFour.byte6 = 0x2; 19213465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte6.bit41, 1); 19313465Sgabeblack@google.com sixtyFour.byte6.bits43To42 = 0x3; 19413465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte6, 0xe); 19513465Sgabeblack@google.com sixtyFour.byte6 = 0xff; 19613465Sgabeblack@google.com sixtyFour.byte6.bit41 = 0; 19713465Sgabeblack@google.com EXPECT_EQ(sixtyFour, 0xfd0000000000); 19813465Sgabeblack@google.com} 19913465Sgabeblack@google.com 20013465Sgabeblack@google.comTEST_F(BitUnionData, SignedBitfields) 20113465Sgabeblack@google.com{ 20213465Sgabeblack@google.com sixtyFour.byte6 = 0xff; 20313465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte6Signed, -1); 20413465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte6SignedRO, -1); 20513465Sgabeblack@google.com sixtyFour.byte6SignedWO = 0; 20613465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte6Signed, 0); 20713465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte6SignedRO, 0); 20813465Sgabeblack@google.com EXPECT_EQ(sixtyFour.byte6, 0); 20913465Sgabeblack@google.com} 21013465Sgabeblack@google.com 21113465Sgabeblack@google.comTEST_F(BitUnionData, InsideStruct) 21213465Sgabeblack@google.com{ 21313465Sgabeblack@google.com ContainingStruct containing; 21413465Sgabeblack@google.com containing.contained = 0; 21513465Sgabeblack@google.com containing.contained.topNibble = 0xd; 21613465Sgabeblack@google.com EXPECT_EQ(containing.contained, 0xd000000000000000); 21713465Sgabeblack@google.com} 21813465Sgabeblack@google.com 21913465Sgabeblack@google.comTEST_F(BitUnionData, InsideFunction) 22013465Sgabeblack@google.com{ 22113465Sgabeblack@google.com EXPECT_EQ(containingFunc(0xfffff, 0), 0xe7fff); 22213465Sgabeblack@google.com} 22313465Sgabeblack@google.com 22413465Sgabeblack@google.comTEST_F(BitUnionData, BitfieldToBitfieldAssignment) 22513465Sgabeblack@google.com{ 22613465Sgabeblack@google.com SixtyFour otherSixtyFour = 0; 22713465Sgabeblack@google.com sixtyFour.bit2 = 1; 22813465Sgabeblack@google.com otherSixtyFour.byte6.bit41 = sixtyFour.bit2; 22913465Sgabeblack@google.com EXPECT_EQ(otherSixtyFour, 0x20000000000); 23013465Sgabeblack@google.com otherSixtyFour.bit2 = sixtyFour.bit2; 23113465Sgabeblack@google.com EXPECT_EQ(otherSixtyFour, 0x20000000004); 23213465Sgabeblack@google.com} 23313465Sgabeblack@google.com 23413465Sgabeblack@google.comTEST_F(BitUnionData, Operators) 23513465Sgabeblack@google.com{ 23613465Sgabeblack@google.com SixtyFour otherSixtyFour = 0x4; 23713465Sgabeblack@google.com sixtyFour = otherSixtyFour; 23813465Sgabeblack@google.com EXPECT_EQ(sixtyFour, 0x4); 23913465Sgabeblack@google.com sixtyFour = 0; 24013465Sgabeblack@google.com EXPECT_TRUE(sixtyFour < otherSixtyFour); 24113465Sgabeblack@google.com EXPECT_TRUE(otherSixtyFour > sixtyFour); 24213465Sgabeblack@google.com EXPECT_TRUE(sixtyFour != otherSixtyFour); 24313465Sgabeblack@google.com sixtyFour = otherSixtyFour; 24413465Sgabeblack@google.com EXPECT_TRUE(sixtyFour == otherSixtyFour); 24513465Sgabeblack@google.com} 24613465Sgabeblack@google.com 24713465Sgabeblack@google.comTEST_F(BitUnionData, Custom) 24813465Sgabeblack@google.com{ 24913465Sgabeblack@google.com EXPECT_EQ(split, 0); 25013465Sgabeblack@google.com split.split = 0xfff; 25113465Sgabeblack@google.com EXPECT_EQ(split, 0xf0f0); 25213465Sgabeblack@google.com EXPECT_EQ((uint64_t)split.split, 0xff); 25313465Sgabeblack@google.com} 25413465Sgabeblack@google.com 25513465Sgabeblack@google.comTEST_F(BitUnionData, Templating) 25613465Sgabeblack@google.com{ 25713465Sgabeblack@google.com sixtyFour = 0xff; 25813465Sgabeblack@google.com EXPECT_EQ(templatedFunction(sixtyFour), 0xff); 25913465Sgabeblack@google.com EXPECT_EQ(templatedFunction((uint64_t)sixtyFour), 0); 26013465Sgabeblack@google.com 26113465Sgabeblack@google.com BitUnion(uint64_t, Dummy64) 26213465Sgabeblack@google.com EndBitUnion(Dummy64); 26313465Sgabeblack@google.com 26413465Sgabeblack@google.com BitUnion(uint32_t, Dummy32) 26513465Sgabeblack@google.com EndBitUnion(Dummy32); 26613465Sgabeblack@google.com 26713465Sgabeblack@google.com bool is64; 26813465Sgabeblack@google.com is64 = std::is_same<BitUnionBaseType<Dummy64>, uint64_t>::value; 26913465Sgabeblack@google.com EXPECT_TRUE(is64); 27013465Sgabeblack@google.com is64 = std::is_same<BitUnionBaseType<Dummy32>, uint64_t>::value; 27113465Sgabeblack@google.com EXPECT_FALSE(is64); 27213465Sgabeblack@google.com} 27313465Sgabeblack@google.com 27413465Sgabeblack@google.comTEST_F(BitUnionData, Output) 27513465Sgabeblack@google.com{ 27613465Sgabeblack@google.com sixtyFour = 1234567812345678; 27713465Sgabeblack@google.com std::stringstream ss; 27813465Sgabeblack@google.com ss << sixtyFour; 27913465Sgabeblack@google.com EXPECT_EQ(ss.str(), "1234567812345678"); 28013465Sgabeblack@google.com ss.str(""); 28113465Sgabeblack@google.com 28213465Sgabeblack@google.com EmptyEight eight = 65; 28313465Sgabeblack@google.com ss << eight; 28413465Sgabeblack@google.com EXPECT_EQ(ss.str(), "65"); 28513465Sgabeblack@google.com ss.str(""); 28613465Sgabeblack@google.com} 287