123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- // Copyright 2018 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package bitfield
- import (
- "bytes"
- "fmt"
- "io/ioutil"
- "testing"
- )
- type myUint8 uint8
- type test1 struct { // 28 bits
- foo uint16 `bitfield:",fob"`
- Bar int8 `bitfield:"5,baz"`
- Foo uint64
- bar myUint8 `bitfield:"3"`
- Bool bool `bitfield:""`
- Baz int8 `bitfield:"3"`
- }
- type test2 struct {
- larger1 uint16 `bitfield:"32"`
- larger2 uint16 `bitfield:"32"`
- }
- type tooManyBits struct {
- u1 uint16 `bitfield:"12"`
- u2 uint16 `bitfield:"12"`
- u3 uint16 `bitfield:"12"`
- u4 uint16 `bitfield:"12"`
- u5 uint16 `bitfield:"12"`
- u6 uint16 `bitfield:"12"`
- }
- type just64 struct {
- foo uint64 `bitfield:""`
- }
- type toUint8 struct {
- foo bool `bitfield:""`
- }
- type toUint16 struct {
- foo int `bitfield:"9"`
- }
- type faultySize struct {
- foo uint64 `bitfield:"a"`
- }
- type faultyType struct {
- foo *int `bitfield:"5"`
- }
- var (
- maxed = test1{
- foo: 0xffff,
- Bar: 0x1f,
- Foo: 0xffff,
- bar: 0x7,
- Bool: true,
- Baz: 0x7,
- }
- alternate1 = test1{
- foo: 0xffff,
- bar: 0x7,
- Baz: 0x7,
- }
- alternate2 = test1{
- Bar: 0x1f,
- Bool: true,
- }
- overflow = test1{
- Bar: 0x3f,
- }
- negative = test1{
- Bar: -1,
- }
- )
- func TestPack(t *testing.T) {
- testCases := []struct {
- desc string
- x interface{}
- nBits uint
- out uint64
- ok bool
- }{
- {"maxed out fields", maxed, 0, 0xfffffff0, true},
- {"maxed using less bits", maxed, 28, 0x0fffffff, true},
- {"alternate1", alternate1, 0, 0xffff0770, true},
- {"alternate2", alternate2, 0, 0x0000f880, true},
- {"just64", &just64{0x0f0f0f0f}, 00, 0xf0f0f0f, true},
- {"just64", &just64{0x0f0f0f0f}, 64, 0xf0f0f0f, true},
- {"just64", &just64{0xffffFFFF}, 64, 0xffffffff, true},
- {"to uint8", &toUint8{true}, 0, 0x80, true},
- {"to uint16", &toUint16{1}, 0, 0x0080, true},
- // errors
- {"overflow", overflow, 0, 0, false},
- {"too many bits", &tooManyBits{}, 0, 0, false},
- {"fault size", &faultySize{}, 0, 0, false},
- {"fault type", &faultyType{}, 0, 0, false},
- {"negative", negative, 0, 0, false},
- {"not enough bits", maxed, 27, 0, false},
- }
- for _, tc := range testCases {
- t.Run(fmt.Sprintf("%T/%s", tc.x, tc.desc), func(t *testing.T) {
- v, err := Pack(tc.x, &Config{NumBits: tc.nBits})
- if ok := err == nil; v != tc.out || ok != tc.ok {
- t.Errorf("got %#x, %v; want %#x, %v (%v)", v, ok, tc.out, tc.ok, err)
- }
- })
- }
- }
- func TestRoundtrip(t *testing.T) {
- testCases := []struct {
- x test1
- }{
- {maxed},
- {alternate1},
- {alternate2},
- }
- for _, tc := range testCases {
- t.Run("", func(t *testing.T) {
- v, err := Pack(tc.x, nil)
- if err != nil {
- t.Fatal(err)
- }
- want := tc.x
- want.Foo = 0 // not stored
- x := myInt(v)
- got := test1{
- foo: x.fob(),
- Bar: x.baz(),
- bar: x.bar(),
- Bool: x.Bool(),
- Baz: x.Baz(),
- }
- if got != want {
- t.Errorf("\ngot %#v\nwant %#v (%#x)", got, want, v)
- }
- })
- }
- }
- func TestGen(t *testing.T) {
- testCases := []struct {
- desc string
- x interface{}
- config *Config
- ok bool
- out string
- }{{
- desc: "test1",
- x: &test1{},
- ok: true,
- out: test1Gen,
- }, {
- desc: "test1 with options",
- x: &test1{},
- config: &Config{Package: "bitfield", TypeName: "myInt"},
- ok: true,
- out: mustRead("gen1_test.go"),
- }, {
- desc: "test1 with alternative bits",
- x: &test1{},
- config: &Config{NumBits: 28, Package: "bitfield", TypeName: "myInt2"},
- ok: true,
- out: mustRead("gen2_test.go"),
- }, {
- desc: "failure",
- x: &test1{},
- config: &Config{NumBits: 27}, // Too few bits.
- ok: false,
- out: "",
- }}
- for _, tc := range testCases {
- t.Run(tc.desc, func(t *testing.T) {
- w := &bytes.Buffer{}
- err := Gen(w, tc.x, tc.config)
- if ok := err == nil; ok != tc.ok {
- t.Fatalf("got %v; want %v (%v)", ok, tc.ok, err)
- }
- got := w.String()
- if got != tc.out {
- t.Errorf("got:\n%s\nwant:\n%s", got, tc.out)
- }
- })
- }
- }
- const test1Gen = `type test1 uint32
- func (t test1) fob() uint16 {
- return uint16((t >> 16) & 0xffff)
- }
- func (t test1) baz() int8 {
- return int8((t >> 11) & 0x1f)
- }
- func (t test1) bar() myUint8 {
- return myUint8((t >> 8) & 0x7)
- }
- func (t test1) Bool() bool {
- const bit = 1 << 7
- return t&bit == bit
- }
- func (t test1) Baz() int8 {
- return int8((t >> 4) & 0x7)
- }
- `
- func mustRead(filename string) string {
- b, err := ioutil.ReadFile(filename)
- if err != nil {
- panic(err)
- }
- return string(b)
- }
|