github.com/tunabay/go-bitarray@v1.3.1/buffer_slice_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 "testing" 11 12 "github.com/tunabay/go-bitarray" 13 ) 14 15 func TestBuffer_Slice(t *testing.T) { 16 bs := "" 17 set := func(s string) { 18 t.Helper() 19 bs = s 20 } 21 test := func(s, e int, exp string) { 22 t.Helper() 23 ba := bitarray.MustParse(bs) 24 buf := bitarray.NewBufferFromBitArray(ba) 25 bufSliced := buf.Slice(s, e) 26 bufSliced.V() 27 sliced := bufSliced.BitArray() 28 expected := bitarray.MustParse(exp) 29 if !sliced.Equal(expected) { 30 t.Errorf("% b: [%d:%d]: unexpected slice:", ba, s, e) 31 t.Logf(" got: %#b", sliced) 32 t.Logf("want: %#b", expected) 33 t.FailNow() 34 } 35 } 36 testPanic := func(s, e int) { 37 t.Helper() 38 ba := bitarray.MustParse(bs) 39 buf := bitarray.NewBufferFromBitArray(ba) 40 var rbuf *bitarray.Buffer 41 defer func() { 42 if recover() == nil { 43 t.Errorf("panic expected:") 44 t.Logf(" got: %#b", rbuf) 45 } 46 }() 47 rbuf = buf.Slice(s, e) 48 } 49 50 set("") 51 test(0, 0, "") 52 testPanic(0, 1) 53 54 set("1111-11") 55 test(0, 0, "") 56 test(4, 4, "") 57 test(0, 3, "111") 58 test(0, 6, "1111-11") 59 testPanic(-1, 1) 60 testPanic(1, 0) 61 testPanic(5, 0) 62 testPanic(5, 3) 63 testPanic(99, 3) 64 testPanic(0, -1) 65 66 set("1111-0000 1010-0101 1100-11") 67 test(0, 0, "") 68 test(0, 1, "1") 69 test(1, 3, "11") 70 test(0, 3, "111") 71 test(0, 8, "1111-0000") 72 test(2, 8, "11-0000") 73 test(3, 11, "1-0000 101") 74 test(9, 15, "010-010") 75 test(0, 22, "1111-0000 1010-0101 1100-11") 76 test(18, 22, "0011") 77 test(21, 22, "1") 78 79 set("0000-0000 0000-0000 0000-0000 0000-0000") 80 test(0, 0, "") 81 test(0, 1, "0") 82 test(0, 7, "0000-000") 83 test(0, 8, "0000-0000") 84 test(0, 9, "0000-0000 0") 85 test(0, 15, "0000-0000 0000-000") 86 test(0, 16, "0000-0000 0000-0000") 87 test(0, 17, "0000-0000 0000-0000 0") 88 test(6, 15, "00 0000-000") 89 test(6, 16, "00 0000-0000") 90 test(6, 17, "00 0000-0000 0") 91 test(0, 31, "0000-0000 0000-0000 0000-0000 0000-000") 92 test(0, 32, "0000-0000 0000-0000 0000-0000 0000-0000") 93 test(15, 31, "0 0000-0000 0000-000") 94 test(15, 32, "0 0000-0000 0000-0000") 95 test(16, 31, "0000-0000 0000-000") 96 test(16, 32, "0000-0000 0000-0000") 97 test(19, 31, "0-0000 0000-000") 98 test(19, 32, "0-0000 0000-0000") 99 test(24, 31, "0000-000") 100 test(24, 32, "0000-0000") 101 test(27, 31, "0-000") 102 test(27, 32, "0-0000") 103 104 set("0000-0000 0") 105 test(0, 9, "0000-0000 0") 106 testPanic(0, 10) 107 testPanic(9, 10) 108 109 set("1010-0101 1010-0101 1010-0101 1010-0101") 110 test(0, 0, "") 111 test(0, 1, "1") 112 test(0, 2, "10") 113 test(0, 3, "101") 114 test(0, 4, "1010") 115 test(0, 5, "1010-0") 116 test(0, 6, "1010-01") 117 test(0, 7, "1010-010") 118 test(0, 8, "1010-0101") 119 test(0, 9, "1010-0101 1") 120 test(0, 10, "1010-0101 10") 121 test(2, 2, "") 122 test(2, 3, "1") 123 test(2, 4, "10") 124 test(2, 5, "10-0") 125 test(2, 6, "10-01") 126 test(2, 7, "10-010") 127 test(2, 8, "10-0101") 128 test(2, 9, "10-0101 1") 129 test(2, 10, "10-0101 10") 130 test(2, 11, "10-0101 101") 131 test(2, 12, "10-0101 1010") 132 test(3, 6, "0-01") 133 test(7, 8, "1") 134 test(8, 9, "1") 135 test(0, 7, "1010-010") 136 test(0, 8, "1010-0101") 137 test(0, 9, "1010-0101 1") 138 test(0, 15, "1010-0101 1010-010") 139 test(0, 16, "1010-0101 1010-0101") 140 test(0, 17, "1010-0101 1010-0101 1") 141 test(6, 15, "01 1010-010") 142 test(6, 16, "01 1010-0101") 143 test(6, 17, "01 1010-0101 1") 144 test(10, 14, "10-01") 145 test(0, 31, "1010-0101 1010-0101 1010-0101 1010-010") 146 test(0, 32, "1010-0101 1010-0101 1010-0101 1010-0101") 147 test(15, 31, "1 1010-0101 1010-010") 148 test(15, 32, "1 1010-0101 1010-0101") 149 test(16, 31, "1010-0101 1010-010") 150 test(16, 32, "1010-0101 1010-0101") 151 test(19, 31, "0-0101 1010-010") 152 test(19, 32, "0-0101 1010-0101") 153 test(24, 31, "1010-010") 154 test(24, 32, "1010-0101") 155 test(26, 29, "10-0") 156 test(27, 31, "0-010") 157 test(27, 32, "0-0101") 158 159 set("1110-0011 1000-1110 0011-1000 1110-0011 1000") 160 test(0, 0, "") 161 test(0, 1, "1") 162 test(2, 6, "10-00") 163 test(6, 8, "11") 164 test(8, 10, "10") 165 test(0, 7, "1110-001") 166 test(0, 8, "1110-0011") 167 test(0, 9, "1110-0011 1") 168 test(0, 15, "1110-0011 1000-111") 169 test(0, 16, "1110-0011 1000-1110") 170 test(0, 17, "1110-0011 1000-1110 0") 171 test(5, 15, "011 1000-111") 172 test(5, 16, "011 1000-1110") 173 test(5, 17, "011 1000-1110 0") 174 test(10, 14, "00-11") 175 test(0, 31, "1110-0011 1000-1110 0011-1000 1110-001") 176 test(0, 32, "1110-0011 1000-1110 0011-1000 1110-0011") 177 test(0, 33, "1110-0011 1000-1110 0011-1000 1110-0011 1") 178 test(0, 34, "1110-0011 1000-1110 0011-1000 1110-0011 10") 179 test(0, 35, "1110-0011 1000-1110 0011-1000 1110-0011 100") 180 test(0, 36, "1110-0011 1000-1110 0011-1000 1110-0011 1000") 181 test(14, 31, "10 0011-1000 1110-001") 182 test(14, 32, "10 0011-1000 1110-0011") 183 test(14, 33, "10 0011-1000 1110-0011 1") 184 test(14, 34, "10 0011-1000 1110-0011 10") 185 test(14, 35, "10 0011-1000 1110-0011 100") 186 test(14, 36, "10 0011-1000 1110-0011 1000") 187 test(16, 31, "0011-1000 1110-001") 188 test(16, 32, "0011-1000 1110-0011") 189 test(16, 33, "0011-1000 1110-0011 1") 190 test(16, 36, "0011-1000 1110-0011 1000") 191 test(19, 31, "1-1000 1110-001") 192 test(19, 32, "1-1000 1110-0011") 193 test(19, 33, "1-1000 1110-0011 1") 194 test(19, 36, "1-1000 1110-0011 1000") 195 test(24, 31, "1110-001") 196 test(24, 32, "1110-0011") 197 test(25, 31, "110-001") 198 test(26, 29, "10-0") 199 test(27, 31, "0-001") 200 test(27, 32, "0-0011") 201 } 202 203 func TestBuffer_Slice_roOpsOnSlice(t *testing.T) { 204 test := func(npad, padbit int, s string) { 205 ba := bitarray.MustParse(s) 206 buf := bitarray.NewBuffer(npad*2 + ba.Len()) 207 if padbit != 0 { 208 buf.FillBitsAt(0, buf.Len(), 1) 209 } 210 padba := bitarray.NewZeroFilled(npad) 211 if padbit != 0 { 212 padba = bitarray.NewOneFilled(npad) 213 } 214 215 slice := buf.Slice(npad, npad+ba.Len()) 216 slice.V() 217 slice.PutBitArrayAt(0, ba) 218 219 // IsZero() on slice 220 if got, want := slice.IsZero(), ba.IsZero(); got != want { 221 t.Errorf("unexpected slice.IsZero(): npad=%d, pad=%d, s=%q", npad, padbit, s) 222 t.Logf(" got: %t", got) 223 t.Logf(" want: %t", want) 224 } 225 226 // Len() on slice 227 if got, want := slice.Len(), ba.Len(); got != want { 228 t.Errorf("unexpected slice.Len(): npad=%d, pad=%d, s=%q", npad, padbit, s) 229 t.Logf(" got: %d", got) 230 t.Logf(" want: %d", want) 231 } 232 233 // String() on slice 234 if got := slice.String(); got != s { 235 t.Errorf("unexpected slice.String(): npad=%d, pad=%d, s=%q", npad, padbit, s) 236 t.Logf(" got: %q", got) 237 t.Logf(" want: %q", s) 238 } 239 240 // BitArray() on slice 241 if got := slice.BitArray(); !got.Equal(ba) { 242 t.Errorf("unexpected slice.BitArray(): npad=%d, pad=%d, s=%q", npad, padbit, s) 243 t.Logf(" got: %# b", got) 244 t.Logf(" want: %# b", ba) 245 } 246 247 // Clone() on slice 248 if got := slice.Clone().BitArray(); !got.Equal(ba) { 249 t.Errorf("unexpected slice.Clone(): npad=%d, pad=%d, s=%q", npad, padbit, s) 250 t.Logf(" got: %# b", got) 251 t.Logf(" want: %# b", ba) 252 } 253 254 // Format() on slice 255 if got, want := fmt.Sprintf("%# b", slice), fmt.Sprintf("%# b", ba); got != want { 256 t.Errorf("unexpected slice.Format(): npad=%d, pad=%d, s=%q", npad, padbit, s) 257 t.Logf(" got: %q", got) 258 t.Logf(" want: %q", want) 259 } 260 261 // BitAt() on slice 262 for i := 0; i < ba.Len(); i++ { 263 if got, want := slice.BitAt(i), ba.BitAt(i); got != want { 264 t.Errorf("unexpected slice.BitAt(%d): npad=%d, pad=%d, s=%q", i, npad, padbit, s) 265 t.Logf(" got: %d", got) 266 t.Logf(" want: %d", want) 267 } 268 } 269 270 // BitArrayAt(full) on slice 271 if got := slice.BitArrayAt(0, slice.Len()); !got.Equal(ba) { 272 t.Errorf("unexpected slice.BitArrayAt(): npad=%d, pad=%d, s=%q", npad, padbit, s) 273 t.Logf(" got: %# b", got) 274 t.Logf(" want: %# b", ba) 275 } 276 277 // LeadingZeros() on slice 278 if got, want := slice.LeadingZeros(), ba.LeadingZeros(); got != want { 279 t.Errorf("unexpected slice.LeadingZeros(): npad=%d, pad=%d, s=%q", npad, padbit, s) 280 t.Logf(" got: %d", got) 281 t.Logf(" want: %d", want) 282 } 283 284 // TrailingZeros() on slice 285 if got, want := slice.TrailingZeros(), ba.TrailingZeros(); got != want { 286 t.Errorf("unexpected slice.TrailingZeros(): npad=%d, pad=%d, s=%q", npad, padbit, s) 287 t.Logf(" got: %d", got) 288 t.Logf(" want: %d", want) 289 } 290 291 // OnesCount() on slice 292 if got, want := slice.OnesCount(), ba.OnesCount(); got != want { 293 t.Errorf("unexpected slice.OnesCount(): npad=%d, pad=%d, s=%q", npad, padbit, s) 294 t.Logf(" got: %d", got) 295 t.Logf(" want: %d", want) 296 } 297 298 // String() on buf (tests the parent buf is not changed) 299 if got, want := buf.String(), padba.String()+s+padba.String(); got != want { 300 t.Errorf("unexpected buf.String(): npad=%d, pad=%d, s=%q", npad, padbit, s) 301 t.Logf(" got: %q", got) 302 t.Logf(" want: %q", want) 303 } 304 305 if t.Failed() { 306 t.FailNow() 307 t.Logf(" buf: %# b", buf) 308 t.Logf(" buf: %s", buf.D()) 309 t.Logf("slice: %# b", slice) 310 t.Logf("slice: %s", slice.D()) 311 } 312 } 313 314 tcs := []string{ 315 "", 316 "0", 317 "00", 318 "000", 319 "0000", 320 "00000", 321 "000000", 322 "0000000", 323 "00000000", 324 "000000000", 325 "0000000000", 326 "000000000000000", 327 "0000000000000000", 328 "00000000000000000", 329 "000111111111000", 330 "0000111111100000", 331 "00000111110000000", 332 "11110111110000000", 333 "11110111110000111", 334 "000000000000000000000000000000000000000000000000000000000000000", 335 "0000000000000000000000000000000000000000000000000000000000000000", 336 "00000000000000000000000000000000000000000000000000000000000000000", 337 "000000000000000000000000000000000000000000000000000000000000001", 338 "0000000000000000000000000000000000000000000000000000000000000001", 339 "00000000000000000000000000000000000000000000000000000000000000001", 340 "100000000000000000000000000000000000000000000000000000000000000", 341 "1000000000000000000000000000000000000000000000000000000000000000", 342 "10000000000000000000000000000000000000000000000000000000000000000", 343 "1", 344 "11", 345 "111", 346 "1111", 347 "11111", 348 "111111", 349 "1111111", 350 "11111111", 351 "111111111", 352 "1111111111", 353 "111111111111111", 354 "1111111111111111", 355 "11111111111111111", 356 "111100001100111", 357 "111100001100000", 358 "1110000110011111", 359 "0010000110011111", 360 "11111000011001111", 361 "00111000011001100", 362 "110000110011111", 363 "1111110000110011", 364 "11110100110010011", 365 "111111111111110101001010000101011111111101010001011110111010001", 366 "1000000000000000000000011111111110000101001000010011111100000001", 367 "01000111111100000000000000000000011111111110000111100000011100000", 368 "1111000111100111100101001000111", 369 "11110001111001111001010010001111", 370 "111100011110011110010100100011111", 371 "0000000111100111100101001000111", 372 "00000001111001111001010010001111", 373 "000000011110011110010100100011111", 374 "1111000111100111100101001000100", 375 "11110001111001111001010010001000", 376 "111100011110011110010100100011000", 377 } 378 for _, tc := range tcs { 379 for npad := 0; npad < 31; npad++ { 380 for padbit := 0; padbit < 2; padbit++ { 381 test(npad, padbit, tc) 382 } 383 } 384 } 385 } 386 387 func TestBuffer_Slice_rwOpsOnSlice(t *testing.T) { 388 var buf, slice *bitarray.Buffer 389 390 test := func(tag, sliceS, bufS string) { 391 t.Helper() 392 sliceW := bitarray.MustParse(sliceS) 393 bufW := bitarray.MustParse(bufS) 394 if got := slice.BitArray(); !got.Equal(sliceW) { 395 t.Errorf("%s: unexpected slice:", tag) 396 t.Logf(" got: %# b", got) 397 t.Logf(" want: %# b", sliceW) 398 } 399 if got := buf.BitArray(); !got.Equal(bufW) { 400 t.Errorf("%s: unexpected buf:", tag) 401 t.Logf(" got: %# b", got) 402 t.Logf(" want: %# b", bufW) 403 } 404 if t.Failed() { 405 t.FailNow() 406 t.Logf(" buf: %# b", buf) 407 t.Logf(" buf: %s", buf.D()) 408 t.Logf("slice: %# b", slice) 409 t.Logf("slice: %s", slice.D()) 410 } 411 } 412 413 allZero31 := bitarray.NewBufferFromBitArray(bitarray.NewZeroFilled(31)) 414 allOne33 := bitarray.NewBufferFromBitArray(bitarray.NewOneFilled(33)) 415 allZeroS15 := allZero31.Slice(5, 20) 416 417 // initial 418 buf = bitarray.NewBuffer(14) 419 slice = buf.Slice(1, 12) 420 slice.V() 421 // 0[000-0000 0000]-00 422 test("initial1", "000-0000 0000", "0000-0000 0000-00") 423 slice = slice.Slice(3, 10) 424 slice.V() 425 // 0000-[0000 000]0-00 426 test("initial2", "0000 000", "0000-0000 0000-00") 427 428 // CopyBits 429 if n := bitarray.CopyBits(slice, allOne33); n != 7 { 430 t.Errorf("CopyBits: unexpected n: got %d, want 7.", n) 431 } 432 // 0000-[1111 111]0-00 433 test("CopyBits", "1111-111", "0000-1111 1110-00") 434 435 // CopyBitsFromBytes(00010) 436 slice.CopyBitsFromBytes(1, []byte{8}, 1, 5) 437 // 0000-[1000 101]0-00 438 test("CopyBitsFromBytes", "1000-101", "0000-1000 1010-00") 439 440 // CopyBitsToBytes 441 tb := make([]byte, 1) 442 slice.CopyBitsToBytes(4, tb, 2, 3) 443 if tb[0] != 0b_0010_1000 { 444 t.Errorf("CopyBitsToBytes: unexpected tb: got %08b, want 0010_1000.", tb[0]) 445 } 446 // 0000-[1000 101]0-00 (unchanged) 447 test("CopyBitsToBytes", "1000-101", "0000-1000 1010-00") 448 449 // CopyBitsN 450 if n := bitarray.CopyBitsN(slice, allZero31, 5); n != 5 { 451 t.Errorf("CopyBitsN: unexpected n: got %d, want 5.", n) 452 } 453 // 0000-[0000 001]0-00 454 test("CopyBitsFromBytes", "0000-001", "0000-0000 0010-00") 455 456 // CopyBits to parent 457 if n := bitarray.CopyBits(buf, allOne33); n != 14 { 458 t.Errorf("CopyBits: unexpected n: got %d, want 14.", n) 459 } 460 // 1111-[1111 111]1-11 461 test("CopyBits(parent)", "1111-111", "1111-1111 1111-11") 462 463 // CopyBitsPartial 464 if n := bitarray.CopyBitsPartial(slice, allZeroS15, 2, 3, 5); n != 5 { 465 t.Errorf("CopyBitsPartial: unexpected n: got %d, want 5.", n) 466 } 467 // 1111-[1100 000]1-11 468 test("CopyBitsPartial", "1100-000", "1111-1100 0001-11") 469 470 // PutBitAt 471 buf.PutBitAt(0, 0) 472 buf.PutBitAt(3, 0) 473 // 0110-[1100 000]1-11 474 test("PutBitAt", "1100-000", "0110-1100 0001-11") 475 buf.PutBitAt(11, 0) 476 buf.PutBitAt(13, 0) 477 // 0110-[1100 000]0-10 478 test("PutBitAt", "1100-000", "0110-1100 0000-10") 479 slice.PutBitAt(0, 0) 480 // 0110-[0100 000]0-10 481 test("PutBitAt", "0100-000", "0110-0100 0000-10") 482 slice.PutBitAt(5, 1) 483 slice.PutBitAt(6, 1) 484 // 0110-[0100 011]0-10 485 test("PutBitAt", "0100-011", "0110-0100 0110-10") 486 487 // BitArrayAt 488 if ba := slice.BitArrayAt(1, 5); !ba.Equal(bitarray.MustParse("10001")) { 489 t.Errorf("BitArrayAt: unexpected result: got %q, want 10001.", ba) 490 } 491 // 0110-[0100 011]0-10 (unchanged) 492 test("BitArrayAt", "0100-011", "0110-0100 0110-10") 493 494 // PutBitArrayAt 495 slice.PutBitArrayAt(1, bitarray.MustParse("11011")) 496 // 0110-[0110 111]0-10 497 test("PutBitArrayAt", "0110-111", "0110-0110 1110-10") 498 499 // byte opes 500 // 0110-0110 1110-1000 0000-0000 0000-0000 0000 501 buf.Resize(36, bitarray.AlignLeft) 502 buf.PutBitArrayAt(5, bitarray.NewOneFilled(15)) 503 // 0110-0111 1111-1111 1111-0000 0000-0000 0000 (unlinked) 504 test("Resize", "0110-111", "0110-0111 1111-1111 1111-0000 0000-0000 0000") 505 506 slice = buf.Slice(5, 34) 507 slice.V() 508 // 0110-0[111 1111-1111 1111-0000 0000-0000 00]00 509 test("Slice-2", "111 1111-1111 1111-0000 0000-0000 00", "0110-0111 1111-1111 1111-0000 0000-0000 0000") 510 511 slice = slice.Slice(5, 26) 512 slice.V() 513 // 0110-0111 11[11-1111 1111-0000 0000-000]0 0000 514 test("Slice-3", "11-1111 1111-0000 0000-000", "0110-0111 1111-1111 1111-0000 0000-0000 0000") 515 516 // ByteAt 517 // [11-1111 (1111-0000) 0000-000] 518 if b := slice.ByteAt(6); b != 0b_1111_0000 { 519 t.Errorf("ByteAt: unexpected result: got %08b, want 11110000.", b) 520 } 521 // [11-1111 1(111-0000 0)000-000] 522 if b := slice.ByteAt(7); b != 0b_1110_0000 { 523 t.Errorf("ByteAt: unexpected result: got %08b, want 11100000.", b) 524 } 525 526 // PutByteAt 527 // 0110-0111 11[11-1111 (1111-0000) 0000-000]0 0000 528 // 0110-0111 11[11-1111 (1000-0011) 0000-000]0 0000 529 slice.PutByteAt(6, 0b_1000_0011) 530 test("PutByteAt-1", "11-1111 1000-0011 0000-000", "0110-0111 1111-1111 1000-0011 0000-0000 0000") 531 532 // 0110-0111 11[11-1111 1000-0(011 0000-0)00]0 0000 533 // 0110-0111 11[11-1111 1000-0(100 0111-1)00]0 0000 534 slice.PutByteAt(11, 0b_1000_1111) 535 test("PutByteAt-2", "11-1111 1000-0100 0111-100", "0110-0111 1111-1111 1000-0100 0111-1000 0000") 536 537 // BytesAt 538 // 0110-0111 11[1(1-1111 1000-0100 011)1-100]0 0000 539 if b := slice.BytesAt(1, 2); !bytes.Equal(b, []byte{0b_1111_1100, 0b_0010_0011}) { 540 t.Errorf("BytesAt: unexpected result: got %08b, want [1111-1100 0010-0011].", b) 541 } 542 // 0110-0111 11[11-(1111 1000-0100 0111)-100]0 0000 543 if b := slice.BytesAt(2, 2); !bytes.Equal(b, []byte{0b_1111_1000, 0b_0100_0111}) { 544 t.Errorf("BytesAt: unexpected result: got %08b, want [1111-1000 0100-0111].", b) 545 } 546 // 0110-0111 11[11-1111 1000-0100 0111-100]0 0000 (unchanged) 547 test("BytesAt", "11-1111 1000-0100 0111-100", "0110-0111 1111-1111 1000-0100 0111-1000 0000") 548 549 // PutBytesAt 550 // 0110-0111 11[1(1-1111 1000-0100 011)1-100]0 0000 551 // 0110-0111 11[1(0-0110 0111-1001 100)1-100]0 0000 552 slice.PutBytesAt(1, []byte{0b_0011_0011, 0b_1100_1100}) 553 test("BytesAt", "10-0110 0111-1001 1001-100", "0110-0111 1110-0110 0111-1001 1001-1000 0000") 554 555 // 0110-0111 11[10-(0110 0111-1001 1001)-100]0 0000 556 // 0110-0111 11[10-(1111 0000-1111 0000)-100]0 0000 557 slice.PutBytesAt(2, []byte{0b_1111_0000, 0b_1111_0000}) 558 test("BytesAt", "10-1111 0000-1111 0000-100", "0110-0111 1110-1111 0000-1111 0000-1000 0000") 559 }