golang.org/x/text@v0.14.0/internal/gen/bitfield/bitfield_test.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package bitfield 6 7 import ( 8 "bytes" 9 "fmt" 10 "os" 11 "testing" 12 ) 13 14 type myUint8 uint8 15 16 type test1 struct { // 28 bits 17 foo uint16 `bitfield:",fob"` 18 Bar int8 `bitfield:"5,baz"` 19 Foo uint64 20 bar myUint8 `bitfield:"3"` 21 Bool bool `bitfield:""` 22 Baz int8 `bitfield:"3"` 23 } 24 25 type test2 struct { 26 larger1 uint16 `bitfield:"32"` 27 larger2 uint16 `bitfield:"32"` 28 } 29 30 type tooManyBits struct { 31 u1 uint16 `bitfield:"12"` 32 u2 uint16 `bitfield:"12"` 33 u3 uint16 `bitfield:"12"` 34 u4 uint16 `bitfield:"12"` 35 u5 uint16 `bitfield:"12"` 36 u6 uint16 `bitfield:"12"` 37 } 38 39 type just64 struct { 40 foo uint64 `bitfield:""` 41 } 42 43 type toUint8 struct { 44 foo bool `bitfield:""` 45 } 46 47 type toUint16 struct { 48 foo int `bitfield:"9"` 49 } 50 51 type faultySize struct { 52 foo uint64 `bitfield:"a"` 53 } 54 55 type faultyType struct { 56 foo *int `bitfield:"5"` 57 } 58 59 var ( 60 maxed = test1{ 61 foo: 0xffff, 62 Bar: 0x1f, 63 Foo: 0xffff, 64 bar: 0x7, 65 Bool: true, 66 Baz: 0x7, 67 } 68 alternate1 = test1{ 69 foo: 0xffff, 70 bar: 0x7, 71 Baz: 0x7, 72 } 73 alternate2 = test1{ 74 Bar: 0x1f, 75 Bool: true, 76 } 77 overflow = test1{ 78 Bar: 0x3f, 79 } 80 negative = test1{ 81 Bar: -1, 82 } 83 ) 84 85 func TestPack(t *testing.T) { 86 testCases := []struct { 87 desc string 88 x interface{} 89 nBits uint 90 out uint64 91 ok bool 92 }{ 93 {"maxed out fields", maxed, 0, 0xfffffff0, true}, 94 {"maxed using less bits", maxed, 28, 0x0fffffff, true}, 95 96 {"alternate1", alternate1, 0, 0xffff0770, true}, 97 {"alternate2", alternate2, 0, 0x0000f880, true}, 98 99 {"just64", &just64{0x0f0f0f0f}, 00, 0xf0f0f0f, true}, 100 {"just64", &just64{0x0f0f0f0f}, 64, 0xf0f0f0f, true}, 101 {"just64", &just64{0xffffFFFF}, 64, 0xffffffff, true}, 102 {"to uint8", &toUint8{true}, 0, 0x80, true}, 103 {"to uint16", &toUint16{1}, 0, 0x0080, true}, 104 // errors 105 {"overflow", overflow, 0, 0, false}, 106 {"too many bits", &tooManyBits{}, 0, 0, false}, 107 {"fault size", &faultySize{}, 0, 0, false}, 108 {"fault type", &faultyType{}, 0, 0, false}, 109 {"negative", negative, 0, 0, false}, 110 {"not enough bits", maxed, 27, 0, false}, 111 } 112 for _, tc := range testCases { 113 t.Run(fmt.Sprintf("%T/%s", tc.x, tc.desc), func(t *testing.T) { 114 v, err := Pack(tc.x, &Config{NumBits: tc.nBits}) 115 if ok := err == nil; v != tc.out || ok != tc.ok { 116 t.Errorf("got %#x, %v; want %#x, %v (%v)", v, ok, tc.out, tc.ok, err) 117 } 118 }) 119 } 120 } 121 122 func TestRoundtrip(t *testing.T) { 123 testCases := []struct { 124 x test1 125 }{ 126 {maxed}, 127 {alternate1}, 128 {alternate2}, 129 } 130 for _, tc := range testCases { 131 t.Run("", func(t *testing.T) { 132 v, err := Pack(tc.x, nil) 133 if err != nil { 134 t.Fatal(err) 135 } 136 want := tc.x 137 want.Foo = 0 // not stored 138 x := myInt(v) 139 got := test1{ 140 foo: x.fob(), 141 Bar: x.baz(), 142 bar: x.bar(), 143 Bool: x.Bool(), 144 Baz: x.Baz(), 145 } 146 if got != want { 147 t.Errorf("\ngot %#v\nwant %#v (%#x)", got, want, v) 148 } 149 }) 150 } 151 } 152 153 func TestGen(t *testing.T) { 154 testCases := []struct { 155 desc string 156 x interface{} 157 config *Config 158 ok bool 159 out string 160 }{{ 161 desc: "test1", 162 x: &test1{}, 163 ok: true, 164 out: test1Gen, 165 }, { 166 desc: "test1 with options", 167 x: &test1{}, 168 config: &Config{Package: "bitfield", TypeName: "myInt"}, 169 ok: true, 170 out: mustRead("gen1_test.go"), 171 }, { 172 desc: "test1 with alternative bits", 173 x: &test1{}, 174 config: &Config{NumBits: 28, Package: "bitfield", TypeName: "myInt2"}, 175 ok: true, 176 out: mustRead("gen2_test.go"), 177 }, { 178 desc: "failure", 179 x: &test1{}, 180 config: &Config{NumBits: 27}, // Too few bits. 181 ok: false, 182 out: "", 183 }} 184 185 for _, tc := range testCases { 186 t.Run(tc.desc, func(t *testing.T) { 187 w := &bytes.Buffer{} 188 err := Gen(w, tc.x, tc.config) 189 if ok := err == nil; ok != tc.ok { 190 t.Fatalf("got %v; want %v (%v)", ok, tc.ok, err) 191 } 192 got := w.String() 193 if got != tc.out { 194 t.Errorf("got:\n%s\nwant:\n%s", got, tc.out) 195 } 196 }) 197 } 198 } 199 200 const test1Gen = `type test1 uint32 201 202 func (t test1) fob() uint16 { 203 return uint16((t >> 16) & 0xffff) 204 } 205 206 func (t test1) baz() int8 { 207 return int8((t >> 11) & 0x1f) 208 } 209 210 func (t test1) bar() myUint8 { 211 return myUint8((t >> 8) & 0x7) 212 } 213 214 func (t test1) Bool() bool { 215 const bit = 1 << 7 216 return t&bit == bit 217 } 218 219 func (t test1) Baz() int8 { 220 return int8((t >> 4) & 0x7) 221 } 222 ` 223 224 func mustRead(filename string) string { 225 b, err := os.ReadFile(filename) 226 if err != nil { 227 panic(err) 228 } 229 return string(b) 230 }