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