github.com/tunabay/go-bitarray@v1.3.1/util_test.go (about) 1 // Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved. 2 // Use of this source code is governed by the MIT license that can be found in 3 // the LICENSE file. 4 5 package bitarray_test 6 7 import ( 8 "bytes" 9 "fmt" 10 "math/rand" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/tunabay/go-bitarray" 16 ) 17 18 func TestCopyBitsB(t *testing.T) { 19 test := func( 20 dst, src []byte, 21 dstOff, srcOff, nBits int, 22 exp []byte, 23 ) { 24 t.Helper() 25 org := make([]byte, len(dst)) 26 copy(org, dst) 27 bitarray.CopyBitsB(dst, src, dstOff, srcOff, nBits) 28 if !bytes.Equal(dst, exp) { 29 t.Error("unexpected result:") 30 t.Logf("dstOff=%d, srcOff=%d, nBits=%d", dstOff, srcOff, nBits) 31 t.Logf(" dst: %08b", org) 32 t.Logf(" src: %08b", src) 33 t.Logf(" got: %08b", dst) 34 t.Logf("want: %08b", exp) 35 t.FailNow() 36 } 37 } 38 39 test( 40 []byte{0b_0000_0000}, 41 []byte{0b_1110_0000}, 42 0, 0, 3, 43 []byte{0b_1110_0000}, 44 ) 45 test( 46 []byte{0b_1111_1011}, 47 []byte{0b_0010_0000}, 48 0, 0, 4, 49 []byte{0b_0010_1011}, 50 ) 51 test( 52 []byte{0b_1111_1111}, 53 []byte{0b_0001_0011}, 54 0, 0, 5, 55 []byte{0b_0001_0111}, 56 ) 57 test( 58 []byte{0b_1111_1111, 0b_0000_1111}, 59 []byte{0b_0010_0000, 0b_1111_0000}, 60 3, 0, 4, 61 []byte{0b_1110_0101, 0b_0000_1111}, 62 ) 63 64 test( 65 []byte{0b_1111_1111, 0b_1111_1111, 0b_1111_1111, 0b_1111_1111, 0b_1111_1111}, 66 []byte{0b_0000_0000, 0b_0000_0000, 0b_0000_0000, 0b_0000_0000, 0b_0000_0000}, 67 10, 10, 12, 68 []byte{0b_1111_1111, 0b_1100_0000, 0b_0000_0011, 0b_1111_1111, 0b_1111_1111}, 69 ) 70 test( 71 []byte{0b_0000_0000, 0b_0000_0000, 0b_0000_0000, 0b_0000_0000, 0b_0000_0000}, 72 []byte{0b_1111_1111, 0b_1111_1111, 0b_1111_1111, 0b_1111_1111, 0b_1111_1111}, 73 8, 8, 12, 74 []byte{0b_0000_0000, 0b_1111_1111, 0b_1111_0000, 0b_0000_0000, 0b_0000_0000}, 75 ) 76 test( 77 []byte{0b_1111_1010, 0b_0000_0000, 0b_0000_0000, 0b_0000_0000, 0b_0000_1111}, 78 []byte{0b_0000_0111, 0b_1111_1111, 0b_1111_1111, 0b_1111_1111, 0b_1111_1111}, 79 11, 5, 22, 80 []byte{0b_1111_1010, 0b_0001_1111, 0b_1111_1111, 0b_1111_1111, 0b_1000_1111}, 81 ) 82 } 83 84 func mkBitsStr(b []byte) string { 85 s := "" 86 for _, be := range b { 87 s += fmt.Sprintf("%08b", be) 88 } 89 return s 90 } 91 92 func mkRandBits() []byte { 93 b := make([]byte, 1+rand.Intn(8)) // len = 1..8 94 rand.Read(b) 95 return b 96 } 97 98 func dupBits(b []byte) []byte { 99 d := make([]byte, len(b)) 100 copy(d, b) 101 return d 102 } 103 104 func sfmt(s string) string { 105 f := make([]string, (len(s)+7)>>3) 106 for i := 0; i < len(f); i++ { 107 f[i] = s[i<<3 : (i+1)<<3] 108 } 109 return fmt.Sprintf("[%s]", strings.Join(f, " ")) 110 } 111 112 func TestCopyBitsB_rand(t *testing.T) { 113 const testIterations = 50000 114 rand.Seed(time.Now().UnixNano()) 115 for i := 0; i < testIterations; i++ { 116 dstB, srcB := mkRandBits(), mkRandBits() 117 dstS, srcS := mkBitsStr(dstB), mkBitsStr(srcB) 118 orgB := dupBits(dstB) 119 orgS := mkBitsStr(orgB) 120 121 wid := len(dstS) 122 if len(srcS) < wid { 123 wid = len(srcS) 124 } 125 nBits := rand.Intn(wid) + 1 126 dst0 := rand.Intn(len(dstS) - nBits + 1) 127 src0 := rand.Intn(len(srcS) - nBits + 1) 128 129 subpS := srcS[src0 : src0+nBits] 130 wantS := orgS[:dst0] + subpS + orgS[dst0+nBits:] 131 gotZF := bitarray.CopyBitsB(dstB, srcB, dst0, src0, nBits) 132 dstS = mkBitsStr(dstB) 133 134 if gotZF && strings.Contains(subpS, "1") { 135 t.Errorf("unexpected ZF: true for %q", subpS) 136 } 137 if dstS != wantS { 138 t.Errorf("unexpected result: dstOff=%d, srcOff=%d, nBits=%d", dst0, src0, nBits) 139 } 140 if t.Failed() { 141 t.Logf(" dst: %08b", orgB) 142 t.Logf(" src: %08b", srcB) 143 t.Logf(" got: %08b", dstB) 144 t.Logf("want: %s", sfmt(wantS)) 145 t.FailNow() 146 } 147 // if i < 30 { 148 // t.Logf("pass: dstOff=%d, srcOff=%d, nBits=%d", dst0, src0, nBits) 149 // t.Logf(" dst: %08b", orgB) 150 // t.Logf(" src: %08b", srcB) 151 // t.Logf(" got: %08b", dstB) 152 // } 153 } 154 } 155 156 func TestClearBits(t *testing.T) { 157 test := func( 158 dst []byte, 159 off, nBits int, 160 exp []byte, 161 ) { 162 t.Helper() 163 org := make([]byte, len(dst)) 164 copy(org, dst) 165 bitarray.ClearBits(dst, off, nBits) 166 if !bytes.Equal(dst, exp) { 167 t.Error("unexpected result:") 168 t.Logf("off=%d, nBits=%d", off, nBits) 169 t.Logf(" dst: %08b", org) 170 t.Logf(" got: %08b", dst) 171 t.Logf("want: %08b", exp) 172 t.FailNow() 173 } 174 } 175 176 test( 177 []byte{0b_1111_1111}, 178 0, 1, 179 []byte{0b_0111_1111}, 180 ) 181 test( 182 []byte{0b_1111_1111}, 183 0, 3, 184 []byte{0b_0001_1111}, 185 ) 186 test( 187 []byte{0b_1111_1111}, 188 5, 2, 189 []byte{0b_1111_1001}, 190 ) 191 test( 192 []byte{0b_1111_1111}, 193 7, 1, 194 []byte{0b_1111_1110}, 195 ) 196 test( 197 []byte{0b_1111_1111, 0b_1111_1111}, 198 4, 3, 199 []byte{0b_1111_0001, 0b_1111_1111}, 200 ) 201 test( 202 []byte{0b_1111_1111, 0b_1111_1111}, 203 5, 3, 204 []byte{0b_1111_1000, 0b_1111_1111}, 205 ) 206 test( 207 []byte{0b_1111_1111, 0b_1111_1111}, 208 5, 4, 209 []byte{0b_1111_1000, 0b_0111_1111}, 210 ) 211 test( 212 []byte{0b_1111_1111, 0b_1111_1111}, 213 7, 1, 214 []byte{0b_1111_1110, 0b_1111_1111}, 215 ) 216 217 test( 218 []byte{0b_1111_1111, 0b_1111_1111, 0b_1111_1111, 0b_1111_1111, 0b_1111_1111}, 219 8, 8, 220 []byte{0b_1111_1111, 0b_0000_0000, 0b_1111_1111, 0b_1111_1111, 0b_1111_1111}, 221 ) 222 test( 223 []byte{0b_1111_1111, 0b_1111_1111, 0b_1111_1111, 0b_1111_1111, 0b_1111_1111}, 224 6, 21, 225 []byte{0b_1111_1100, 0b_0000_0000, 0b_0000_0000, 0b_0001_1111, 0b_1111_1111}, 226 ) 227 } 228 229 func TestClearBits_rand(t *testing.T) { 230 const testIterations = 50000 231 rand.Seed(time.Now().UnixNano()) 232 for i := 0; i < testIterations; i++ { 233 dstB := mkRandBits() 234 dstS := mkBitsStr(dstB) 235 orgB := dupBits(dstB) 236 orgS := mkBitsStr(orgB) 237 238 nBits := rand.Intn(len(dstS)) + 1 239 dst0 := rand.Intn(len(dstS) - nBits + 1) 240 241 wantS := orgS[:dst0] + strings.Repeat("0", nBits) + orgS[dst0+nBits:] 242 bitarray.ClearBits(dstB, dst0, nBits) 243 dstS = mkBitsStr(dstB) 244 245 if dstS != wantS { 246 t.Errorf("unexpected result: off=%d, nBits=%d", dst0, nBits) 247 t.Logf(" dst: %08b", orgB) 248 t.Logf(" got: %08b", dstB) 249 t.Logf("want: %s", sfmt(wantS)) 250 t.FailNow() 251 } 252 // if i < 30 { 253 // t.Logf("pass: off=%d, nBits=%d", dst0, nBits) 254 // t.Logf(" dst: %08b", orgB) 255 // t.Logf(" got: %08b", dstB) 256 // } 257 } 258 } 259 260 func TestSetBits_rand(t *testing.T) { 261 const testIterations = 50000 262 rand.Seed(time.Now().UnixNano()) 263 for i := 0; i < testIterations; i++ { 264 dstB := mkRandBits() 265 dstS := mkBitsStr(dstB) 266 orgB := dupBits(dstB) 267 orgS := mkBitsStr(orgB) 268 269 nBits := rand.Intn(len(dstS)) + 1 270 dst0 := rand.Intn(len(dstS) - nBits + 1) 271 272 wantS := orgS[:dst0] + strings.Repeat("1", nBits) + orgS[dst0+nBits:] 273 bitarray.SetBits(dstB, dst0, nBits) 274 dstS = mkBitsStr(dstB) 275 276 if dstS != wantS { 277 t.Errorf("unexpected result: off=%d, nBits=%d", dst0, nBits) 278 t.Logf(" dst: %08b", orgB) 279 t.Logf(" got: %08b", dstB) 280 t.Logf("want: %s", sfmt(wantS)) 281 t.FailNow() 282 } 283 // if i < 30 { 284 // t.Logf("pass: off=%d, nBits=%d", dst0, nBits) 285 // t.Logf(" dst: %08b", orgB) 286 // t.Logf(" got: %08b", dstB) 287 // } 288 } 289 } 290 291 func TestToggleBits_rand(t *testing.T) { 292 const testIterations = 50000 293 rand.Seed(time.Now().UnixNano()) 294 for i := 0; i < testIterations; i++ { 295 dstB := mkRandBits() 296 dstS := mkBitsStr(dstB) 297 orgB := dupBits(dstB) 298 orgS := mkBitsStr(orgB) 299 300 nBits := rand.Intn(len(dstS)) + 1 301 dst0 := rand.Intn(len(dstS) - nBits + 1) 302 303 mapfn := func(r rune) rune { 304 switch r { 305 case '0': 306 return '1' 307 case '1': 308 return '0' 309 } 310 return r 311 } 312 subpS := strings.Map(mapfn, dstS[dst0:dst0+nBits]) 313 wantS := orgS[:dst0] + subpS + orgS[dst0+nBits:] 314 bitarray.ToggleBits(dstB, dst0, nBits) 315 dstS = mkBitsStr(dstB) 316 317 if dstS != wantS { 318 t.Errorf("unexpected result: off=%d, nBits=%d", dst0, nBits) 319 t.Logf(" dst: %08b", orgB) 320 t.Logf(" got: %08b", dstB) 321 t.Logf("want: %s", sfmt(wantS)) 322 t.FailNow() 323 } 324 // if i < 30 { 325 // t.Logf("pass: off=%d, nBits=%d", dst0, nBits) 326 // t.Logf(" dst: %08b", orgB) 327 // t.Logf(" got: %08b", dstB) 328 // } 329 } 330 } 331 332 func TestAndBits_rand(t *testing.T) { 333 const testIterations = 50000 334 rand.Seed(time.Now().UnixNano()) 335 for i := 0; i < testIterations; i++ { 336 dstB, srcB := mkRandBits(), mkRandBits() 337 dstS, srcS := mkBitsStr(dstB), mkBitsStr(srcB) 338 orgB := dupBits(dstB) 339 orgS := mkBitsStr(orgB) 340 341 wid := len(dstS) 342 if len(srcS) < wid { 343 wid = len(srcS) 344 } 345 nBits := rand.Intn(wid) + 1 346 dst0 := rand.Intn(len(dstS) - nBits + 1) 347 src0 := rand.Intn(len(srcS) - nBits + 1) 348 349 subpS := "" 350 for i := 0; i < nBits; i++ { 351 switch dstS[dst0+i:dst0+i+1] + srcS[src0+i:src0+i+1] { 352 case "11": 353 subpS += "1" 354 default: 355 subpS += "0" 356 } 357 } 358 wantS := orgS[:dst0] + subpS + orgS[dst0+nBits:] 359 bitarray.AndBits(dstB, srcB, dst0, src0, nBits) 360 dstS = mkBitsStr(dstB) 361 362 if dstS != wantS { 363 t.Errorf("unexpected result: dstOff=%d, srcOff=%d, nBits=%d", dst0, src0, nBits) 364 t.Logf(" dst: %08b", orgB) 365 t.Logf(" src: %08b", srcB) 366 t.Logf(" got: %08b", dstB) 367 t.Logf("want: %s", sfmt(wantS)) 368 t.FailNow() 369 } 370 // if i < 30 { 371 // t.Logf("pass: dstOff=%d, srcOff=%d, nBits=%d", dst0, src0, nBits) 372 // t.Logf(" dst: %08b", orgB) 373 // t.Logf(" src: %08b", srcB) 374 // t.Logf(" got: %08b", dstB) 375 // } 376 } 377 } 378 379 func TestOrBits_rand(t *testing.T) { 380 const testIterations = 50000 381 rand.Seed(time.Now().UnixNano()) 382 for i := 0; i < testIterations; i++ { 383 dstB, srcB := mkRandBits(), mkRandBits() 384 dstS, srcS := mkBitsStr(dstB), mkBitsStr(srcB) 385 orgB := dupBits(dstB) 386 orgS := mkBitsStr(orgB) 387 388 wid := len(dstS) 389 if len(srcS) < wid { 390 wid = len(srcS) 391 } 392 nBits := rand.Intn(wid) + 1 393 dst0 := rand.Intn(len(dstS) - nBits + 1) 394 src0 := rand.Intn(len(srcS) - nBits + 1) 395 396 subpS := "" 397 for i := 0; i < nBits; i++ { 398 switch dstS[dst0+i:dst0+i+1] + srcS[src0+i:src0+i+1] { 399 case "00": 400 subpS += "0" 401 default: 402 subpS += "1" 403 } 404 } 405 wantS := orgS[:dst0] + subpS + orgS[dst0+nBits:] 406 bitarray.OrBits(dstB, srcB, dst0, src0, nBits) 407 dstS = mkBitsStr(dstB) 408 409 if dstS != wantS { 410 t.Errorf("unexpected result: dstOff=%d, srcOff=%d, nBits=%d", dst0, src0, nBits) 411 t.Logf(" dst: %08b", orgB) 412 t.Logf(" src: %08b", srcB) 413 t.Logf(" got: %08b", dstB) 414 t.Logf("want: %s", sfmt(wantS)) 415 t.FailNow() 416 } 417 // if i < 30 { 418 // t.Logf("pass: dstOff=%d, srcOff=%d, nBits=%d", dst0, src0, nBits) 419 // t.Logf(" dst: %08b", orgB) 420 // t.Logf(" src: %08b", srcB) 421 // t.Logf(" got: %08b", dstB) 422 // } 423 } 424 } 425 426 func TestXorBits_rand(t *testing.T) { 427 const testIterations = 50000 428 rand.Seed(time.Now().UnixNano()) 429 for i := 0; i < testIterations; i++ { 430 dstB, srcB := mkRandBits(), mkRandBits() 431 dstS, srcS := mkBitsStr(dstB), mkBitsStr(srcB) 432 orgB := dupBits(dstB) 433 orgS := mkBitsStr(orgB) 434 435 wid := len(dstS) 436 if len(srcS) < wid { 437 wid = len(srcS) 438 } 439 nBits := rand.Intn(wid) + 1 440 dst0 := rand.Intn(len(dstS) - nBits + 1) 441 src0 := rand.Intn(len(srcS) - nBits + 1) 442 443 subpS := "" 444 for i := 0; i < nBits; i++ { 445 switch dstS[dst0+i:dst0+i+1] + srcS[src0+i:src0+i+1] { 446 case "01", "10": 447 subpS += "1" 448 default: 449 subpS += "0" 450 } 451 } 452 wantS := orgS[:dst0] + subpS + orgS[dst0+nBits:] 453 bitarray.XorBits(dstB, srcB, dst0, src0, nBits) 454 dstS = mkBitsStr(dstB) 455 456 if dstS != wantS { 457 t.Errorf("unexpected result: dstOff=%d, srcOff=%d, nBits=%d", dst0, src0, nBits) 458 t.Logf(" dst: %08b", orgB) 459 t.Logf(" src: %08b", srcB) 460 t.Logf(" got: %08b", dstB) 461 t.Logf("want: %s", sfmt(wantS)) 462 t.FailNow() 463 } 464 // if i < 30 { 465 // t.Logf("pass: dstOff=%d, srcOff=%d, nBits=%d", dst0, src0, nBits) 466 // t.Logf(" dst: %08b", orgB) 467 // t.Logf(" src: %08b", srcB) 468 // t.Logf(" got: %08b", dstB) 469 // } 470 } 471 }