github.com/tunabay/go-bitarray@v1.3.1/bitarray_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  	"crypto/sha256"
    10  	"encoding/hex"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/tunabay/go-bitarray"
    15  )
    16  
    17  func TestNew(t *testing.T) {
    18  	tcs := []struct {
    19  		b []byte
    20  		s string
    21  	}{
    22  		{[]byte{}, ""},
    23  		{[]byte{0}, "0"},
    24  		{[]byte{1}, "1"},
    25  		{[]byte{0, 0}, "00"},
    26  		{[]byte{0, 0, 0}, "000"},
    27  		{[]byte{0, 0, 0, 0}, "0000"},
    28  		{[]byte{0, 0, 0, 0, 0}, "00000"},
    29  		{[]byte{0, 0, 0, 0, 0, 0}, "000000"},
    30  		{[]byte{0, 0, 0, 0, 0, 0, 0}, "0000000"},
    31  		{[]byte{0, 0, 0, 0, 0, 0, 0, 0}, "00000000"},
    32  		{[]byte{0, 0, 0, 0, 0, 0, 0, 0, 0}, "000000000"},
    33  		{[]byte{1, 1}, "11"},
    34  		{[]byte{1, 1, 0, 0, 0}, "11000"},
    35  		{[]byte{1, 1, 0, 0, 0, 0, 0, 0, 0}, "110000000"},
    36  	}
    37  	for _, tc := range tcs {
    38  		ba := bitarray.New(tc.b...)
    39  		ba.V()
    40  		s := ba.String()
    41  		if s != tc.s {
    42  			t.Errorf("unexpected result: got %q, want %q", s, tc.s)
    43  			t.Logf("input: %v", tc.b)
    44  			t.Logf(" data: %s", ba.D())
    45  			t.FailNow()
    46  		}
    47  	}
    48  }
    49  
    50  func TestNewFromBytes(t *testing.T) {
    51  	b := bytes.Repeat([]byte{0b_1111_0011, 0b_1010_0101}, 3)
    52  	tcs := []struct {
    53  		n, o int
    54  		s    string
    55  	}{
    56  		{0, 0, ""},
    57  		{0, 1, ""},
    58  		{0, 7, ""},
    59  		{0, 8, ""},
    60  		{0, 9, ""},
    61  		{0, 47, ""},
    62  		{0, 48, ""},
    63  		{1, 0, "1"},
    64  		{2, 0, "11"},
    65  		{3, 0, "111"},
    66  		{4, 0, "1111"},
    67  		{5, 0, "11110"},
    68  		{6, 0, "111100"},
    69  		{7, 0, "1111001"},
    70  		{8, 0, "11110011"},
    71  		{9, 0, "111100111"},
    72  		{10, 0, "1111001110"},
    73  		{16, 0, "1111001110100101"},
    74  		{17, 0, "11110011101001011"},
    75  		{24, 0, "111100111010010111110011"},
    76  		{25, 0, "1111001110100101111100111"},
    77  		{24, 1, "111001110100101111100111"},
    78  		{23, 2, "11001110100101111100111"},
    79  		{22, 3, "1001110100101111100111"},
    80  		{21, 4, "001110100101111100111"},
    81  		{20, 5, "01110100101111100111"},
    82  		{19, 6, "1110100101111100111"},
    83  		{18, 7, "110100101111100111"},
    84  		{17, 8, "10100101111100111"},
    85  		{16, 9, "0100101111100111"},
    86  		{10, 15, "1111100111"},
    87  		{9, 16, "111100111"},
    88  		{8, 17, "11100111"},
    89  		{7, 18, "1100111"},
    90  		{1, 47, "1"},
    91  		{2, 46, "01"},
    92  		{3, 45, "101"},
    93  		{4, 44, "0101"},
    94  		{5, 43, "00101"},
    95  		{6, 42, "100101"},
    96  		{7, 41, "0100101"},
    97  		{8, 40, "10100101"},
    98  		{9, 39, "110100101"},
    99  		{48, 0, "111100111010010111110011101001011111001110100101"},
   100  	}
   101  	for _, tc := range tcs {
   102  		ba := bitarray.NewFromBytes(b, tc.o, tc.n)
   103  		ba.V()
   104  		bs := ba.String()
   105  		if bs != tc.s {
   106  			t.Errorf("unexpected result: nBits=%d, off=%d", tc.n, tc.o)
   107  			t.Logf(" src: %b", b)
   108  			t.Logf(" got: %q", bs)
   109  			t.Logf("want: %q", tc.s)
   110  			t.Logf("  ba: %s", ba.D())
   111  			t.FailNow()
   112  		}
   113  	}
   114  }
   115  
   116  func TestNewFromBytes_panic(t *testing.T) {
   117  	var ba *bitarray.BitArray
   118  	testNoPanicZero := func(b []byte, nBits, off int) {
   119  		t.Helper()
   120  		ba = bitarray.NewFromBytes(b, off, nBits)
   121  		if !ba.IsZero() {
   122  			t.Errorf("zero expected: nBits=%d, off=%d", nBits, off)
   123  			t.Logf("input: b=%v", b)
   124  			t.Logf("  got: %#b", ba)
   125  			t.Logf("  got: %s", ba.D())
   126  		}
   127  	}
   128  	testPanic := func(b []byte, nBits, off int) {
   129  		t.Helper()
   130  		defer func() {
   131  			t.Helper()
   132  			if recover() == nil {
   133  				t.Errorf("panic expected: nBits=%d, off=%d", nBits, off)
   134  				t.Logf("input: b=%v", b)
   135  				t.Logf("  got: %#b", ba)
   136  				t.Logf("  got: %s", ba.D())
   137  			}
   138  		}()
   139  		ba = bitarray.NewFromBytes(b, off, nBits)
   140  	}
   141  	testPanic(nil, -1, 0)
   142  	testPanic(nil, 0, -1)
   143  	testPanic([]byte{}, -1, 0)
   144  	testPanic([]byte{}, 0, -1)
   145  	testNoPanicZero(nil, 0, 0)
   146  	testNoPanicZero([]byte{}, 0, 0)
   147  	testPanic(nil, 1, 0)
   148  	testPanic(nil, 0, 1)
   149  	testPanic([]byte{}, 1, 0)
   150  	testPanic([]byte{}, 0, 1)
   151  	testPanic([]byte{}, 7, 0)
   152  	testPanic([]byte{}, 8, 0)
   153  	testPanic([]byte{}, 9, 0)
   154  	testPanic([]byte{}, 0, 7)
   155  	testPanic([]byte{}, 0, 8)
   156  	testPanic([]byte{}, 0, 9)
   157  
   158  	testNoPanicZero([]byte{0}, 0, 0)
   159  	testNoPanicZero([]byte{0}, 0, 7)
   160  	testNoPanicZero([]byte{0}, 0, 8)
   161  	testPanic([]byte{0}, 0, 9)
   162  	testPanic([]byte{0}, 9, 0)
   163  	testPanic([]byte{0}, 1, 8)
   164  	testPanic([]byte{0}, 4, 5)
   165  	testPanic([]byte{0}, 7, 2)
   166  	testPanic([]byte{0}, 32, 64)
   167  	testNoPanicZero([]byte{0, 0, 0, 0}, 0, 32)
   168  	testPanic([]byte{0, 0, 0, 0}, 16, 17)
   169  	testPanic([]byte{0, 0, 0, 0}, 17, 16)
   170  	testPanic([]byte{0, 0, 0, 0}, -1, 0)
   171  	testPanic([]byte{0, 0, 0, 0}, 0, -1)
   172  }
   173  
   174  func TestNewFromByteBits(t *testing.T) {
   175  	tcs := []struct {
   176  		b []byte
   177  		s string
   178  	}{
   179  		{nil, ""},
   180  		{[]byte{}, ""},
   181  		{[]byte{0}, "0"},
   182  		{[]byte{0, 0}, "00"},
   183  		{[]byte{0, 0, 0}, "000"},
   184  		{[]byte{0, 0, 0, 0}, "0000"},
   185  		{[]byte{0, 0, 0, 0, 0}, "0000-0"},
   186  		{[]byte{0, 0, 0, 0, 0, 0}, "0000-00"},
   187  		{[]byte{0, 0, 0, 0, 0, 0, 0}, "0000-000"},
   188  		{[]byte{0, 0, 0, 0, 0, 0, 0, 0}, "0000-0000"},
   189  		{[]byte{0, 0, 0, 0, 0, 0, 0, 0, 0}, "0000-0000 0"},
   190  		{[]byte{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1}, "0000-0000 1010-0000 1"},
   191  		{[]byte{1}, "1"},
   192  		{[]byte{1, 1}, "11"},
   193  		{[]byte{1, 1, 1}, "111"},
   194  		{[]byte{1, 1, 1, 1}, "1111"},
   195  		{[]byte{1, 1, 1, 1, 1}, "1111-1"},
   196  		{[]byte{1, 1, 1, 1, 1, 1}, "1111-11"},
   197  		{[]byte{1, 1, 1, 1, 1, 1, 1}, "1111-111"},
   198  		{[]byte{1, 1, 1, 1, 1, 1, 1, 1}, "1111-1111"},
   199  		{[]byte{1, 1, 1, 1, 1, 1, 1, 1, 1}, "1111-1111 1"},
   200  		{[]byte{1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0}, "1111-1111 0111-0101 00"},
   201  		{[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, "1111-1111 1"},
   202  		{[]byte{0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe}, "0000-0000 0"},
   203  		{[]byte{0xff, 0xfe, 0xff, 0xfe, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff}, "1010-0101 01"},
   204  	}
   205  	for _, tc := range tcs {
   206  		ba0 := bitarray.NewFromByteBits(tc.b)
   207  		want := bitarray.MustParse(tc.s)
   208  		ba0.V()
   209  		if !ba0.Equal(want) {
   210  			t.Error("unexpected result:")
   211  			t.Logf(" got: %#b", ba0)
   212  			t.Logf(" got: %s", ba0.D())
   213  			t.Logf("want: %#b", want)
   214  		}
   215  	}
   216  }
   217  
   218  func TestNewZeroFilled(t *testing.T) {
   219  	testPanic := func(nBits int) {
   220  		t.Helper()
   221  		var ba *bitarray.BitArray
   222  		defer func() {
   223  			t.Helper()
   224  			if recover() == nil {
   225  				t.Errorf("panic expected.")
   226  				t.Logf("got: %#b", ba)
   227  				t.Logf("got: %s", ba.D())
   228  			}
   229  		}()
   230  		ba = bitarray.NewZeroFilled(nBits)
   231  	}
   232  	testPanic(-1)
   233  	testPanic(-7)
   234  
   235  	ba0 := bitarray.NewZeroFilled(0)
   236  	ba0.V()
   237  	if !ba0.IsZero() || ba0.Len() != 0 || ba0.NumPadding() != 0 {
   238  		t.Errorf("unexpected: got %#b, want zero", ba0)
   239  	}
   240  
   241  	tcs := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 63, 64, 65}
   242  	for _, tc := range tcs {
   243  		ba := bitarray.NewZeroFilled(tc)
   244  		ba.V()
   245  		baE := ba.ZExpand()
   246  		baE.V()
   247  		got := ba.String()
   248  		gotE := baE.String()
   249  		exp := strings.Repeat("0", tc)
   250  		if got != exp || gotE != exp {
   251  			t.Errorf("unexpected: got %q, want %q", got, exp)
   252  		}
   253  	}
   254  }
   255  
   256  func TestNewOneFilled(t *testing.T) {
   257  	testPanic := func(nBits int) {
   258  		t.Helper()
   259  		var ba *bitarray.BitArray
   260  		defer func() {
   261  			t.Helper()
   262  			if recover() == nil {
   263  				t.Errorf("panic expected.")
   264  				t.Logf("got: %#b", ba)
   265  				t.Logf("got: %s", ba.D())
   266  			}
   267  		}()
   268  		ba = bitarray.NewOneFilled(nBits)
   269  	}
   270  	testPanic(-1)
   271  	testPanic(-7)
   272  
   273  	ba0 := bitarray.NewOneFilled(0)
   274  	ba0.V()
   275  	if !ba0.IsZero() || ba0.Len() != 0 || ba0.NumPadding() != 0 {
   276  		t.Errorf("unexpected: got %#b, want zero", ba0)
   277  	}
   278  
   279  	tcs := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 63, 64, 65}
   280  	for _, tc := range tcs {
   281  		ba := bitarray.NewOneFilled(tc)
   282  		ba.V()
   283  		got := ba.String()
   284  		exp := strings.Repeat("1", tc)
   285  		if got != exp {
   286  			t.Errorf("unexpected: got %q, want %q", got, exp)
   287  		}
   288  	}
   289  }
   290  
   291  func TestNewByRunLength(t *testing.T) {
   292  	ba0 := bitarray.NewByRunLength()
   293  	if !ba0.IsZero() || ba0.Len() != 0 || ba0.NumPadding() != 0 {
   294  		t.Errorf("unexpected: got %#b, want zero", ba0)
   295  	}
   296  
   297  	tcs := []*bitarray.BitArray{
   298  		bitarray.NewByRunLength(),
   299  		bitarray.MustParse(""),
   300  
   301  		bitarray.NewByRunLength(0, 0, 0),
   302  		bitarray.MustParse(""),
   303  
   304  		bitarray.NewByRunLength(1),
   305  		bitarray.MustParse("0"),
   306  
   307  		bitarray.NewByRunLength(0, 1),
   308  		bitarray.MustParse("1"),
   309  
   310  		bitarray.NewByRunLength(100, 0, 100),
   311  		bitarray.MustParse(strings.Repeat("0", 200)),
   312  	}
   313  	for i := 0; i < len(tcs); i += 2 {
   314  		x := tcs[i]
   315  		xE := x.ZExpand()
   316  		xO := x.ZOptimize()
   317  		x.V()
   318  		xE.V()
   319  		xO.V()
   320  		y := tcs[i+1]
   321  		switch {
   322  		case !x.Equal(y):
   323  			t.Error("unexpected:")
   324  			t.Logf(" got: %#b", x)
   325  			t.Logf(" got: %s", x.D())
   326  		case !xE.Equal(y):
   327  			t.Error("unexpected (e):")
   328  			t.Logf(" got: %#b", xE)
   329  			t.Logf(" got: %s", xE.D())
   330  		case !xO.Equal(y):
   331  			t.Error("unexpected (o):")
   332  			t.Logf(" got: %#b", xO)
   333  			t.Logf(" got: %s", xO.D())
   334  		}
   335  		if t.Failed() {
   336  			t.Logf("want: %#b", y)
   337  			t.FailNow()
   338  		}
   339  	}
   340  }
   341  
   342  func TestBitArray_IsZero(t *testing.T) {
   343  	var ba *bitarray.BitArray
   344  	if !ba.IsZero() {
   345  		t.Error("unexpected nil.IsZero(): got false, want true")
   346  	}
   347  	ba = &bitarray.BitArray{}
   348  	if !ba.IsZero() {
   349  		t.Error("unexpected zero.IsZero(): got false, want true")
   350  	}
   351  	ba = bitarray.NewZeroFilled(0)
   352  	if !ba.IsZero() {
   353  		t.Error("unexpected zero.IsZero(): got false, want true")
   354  	}
   355  	ba = bitarray.NewZeroFilled(1)
   356  	if ba.IsZero() {
   357  		t.Error("unexpected 0.IsZero(): got true, want false")
   358  	}
   359  }
   360  
   361  func TestBitArray_Len_edge(t *testing.T) {
   362  	var ba *bitarray.BitArray
   363  	if n := ba.Len(); n != 0 {
   364  		t.Errorf("unexpected nil.Len(): got %d, want 0", n)
   365  	}
   366  	ba = &bitarray.BitArray{}
   367  	if n := ba.Len(); n != 0 {
   368  		t.Errorf("unexpected zero.Len(): got %d, want 0", n)
   369  	}
   370  	ba = bitarray.NewZeroFilled(0)
   371  	if n := ba.Len(); n != 0 {
   372  		t.Errorf("unexpected zero.Len(): got %d, want 0", n)
   373  	}
   374  	ba = bitarray.NewZeroFilled(1000)
   375  	if n := ba.Len(); n != 1000 {
   376  		t.Errorf("unexpected Len(): got %d, want 1000", n)
   377  	}
   378  	if n := ba.ZExpand().Len(); n != 1000 {
   379  		t.Errorf("unexpected Len(): got %d, want 1000", n)
   380  	}
   381  	ba = bitarray.NewOneFilled(1000)
   382  	if n := ba.Len(); n != 1000 {
   383  		t.Errorf("unexpected Len(): got %d, want 1000", n)
   384  	}
   385  }
   386  
   387  func TestBitArray_NumPadding_edge(t *testing.T) {
   388  	var ba *bitarray.BitArray
   389  	if n := ba.NumPadding(); n != 0 {
   390  		t.Errorf("unexpected nil.NumPadding(): got %d, want 0", n)
   391  	}
   392  	ba = &bitarray.BitArray{}
   393  	if n := ba.NumPadding(); n != 0 {
   394  		t.Errorf("unexpected zero.NumPadding(): got %d, want 0", n)
   395  	}
   396  	ba = bitarray.NewZeroFilled(0)
   397  	if n := ba.NumPadding(); n != 0 {
   398  		t.Errorf("unexpected zero.NumPadding(): got %d, want 0", n)
   399  	}
   400  	ba = bitarray.NewZeroFilled(1001)
   401  	if n := ba.NumPadding(); n != 7 {
   402  		t.Errorf("unexpected NumPadding(): got %d, want 7", n)
   403  	}
   404  	if n := ba.ZExpand().NumPadding(); n != 7 {
   405  		t.Errorf("unexpected NumPadding(): got %d, want 7", n)
   406  	}
   407  	ba = bitarray.NewOneFilled(1001)
   408  	if n := ba.NumPadding(); n != 7 {
   409  		t.Errorf("unexpected NumPadding(): got %d, want 7", n)
   410  	}
   411  }
   412  
   413  func TestBitArray_String_edge(t *testing.T) {
   414  	ba := &bitarray.BitArray{}
   415  	if s := ba.String(); s != "" {
   416  		t.Errorf(`unexpected zero.String(): got %q, want ""`, s)
   417  	}
   418  	ba = bitarray.NewZeroFilled(0)
   419  	if s := ba.String(); s != "" {
   420  		t.Errorf(`unexpected zero.String(): got %q, want ""`, s)
   421  	}
   422  	ba = bitarray.NewZeroFilled(1000)
   423  	z1000 := strings.Repeat("0", 1000)
   424  	if s := ba.String(); s != z1000 {
   425  		t.Errorf(`unexpected String(): got %q, want %q`, s, z1000)
   426  	}
   427  	if s := ba.ZExpand().String(); s != z1000 {
   428  		t.Errorf(`unexpected String(): got %q, want %q`, s, z1000)
   429  	}
   430  	ba = bitarray.NewOneFilled(1000)
   431  	o1000 := strings.Repeat("1", 1000)
   432  	if s := ba.String(); s != o1000 {
   433  		t.Errorf(`unexpected String(): got %q, want %q`, s, o1000)
   434  	}
   435  }
   436  
   437  func TestBitArray_Bytes(t *testing.T) {
   438  	tcs := []struct {
   439  		s, b string
   440  		pad  int
   441  	}{
   442  		{"", "", 0},
   443  		{"0", "00", 7},
   444  		{"00", "00", 6},
   445  		{"000", "00", 5},
   446  		{"0000", "00", 4},
   447  		{"0000-0", "00", 3},
   448  		{"0000-00", "00", 2},
   449  		{"0000-000", "00", 1},
   450  		{"0000-0000", "00", 0},
   451  		{"0000-0000 0", "0000", 7},
   452  		{"0000-0000 00", "0000", 6},
   453  		{"1", "80", 7},
   454  		{"10", "80", 6},
   455  		// TODO: more
   456  	}
   457  	for _, tc := range tcs {
   458  		ba := bitarray.MustParse(tc.s).ZOptimize()
   459  		baE := ba.ZExpand()
   460  		want, _ := hex.DecodeString(tc.b)
   461  		if b, pad := ba.Bytes(); !bytes.Equal(b, want) || pad != tc.pad {
   462  			t.Error("unexpected result:")
   463  			t.Logf(" got: %x, pad=%d", b, pad)
   464  			t.Logf("want: %s, pad=%d", tc.b, tc.pad)
   465  			t.Logf("  ba: %#b", ba)
   466  			t.Logf("  ba: %s", ba.D())
   467  			t.FailNow()
   468  		}
   469  		if b, pad := baE.Bytes(); !bytes.Equal(b, want) || pad != tc.pad {
   470  			t.Error("unexpected result (e):")
   471  			t.Logf(" got: %x, pad=%d", b, pad)
   472  			t.Logf("want: %s, pad=%d", tc.b, tc.pad)
   473  			t.Logf("  ba: %#b", baE)
   474  			t.Logf("  ba: %s", baE.D())
   475  			t.FailNow()
   476  		}
   477  	}
   478  }
   479  
   480  func TestBitArray_BitArray(t *testing.T) {
   481  	ba := bitarray.MustParse("0001-0000 1111-1111")
   482  	if cp := ba.BitArray(); cp != ba {
   483  		t.Errorf("unexpected result: %p != %p", cp, ba)
   484  	}
   485  }
   486  
   487  func TestBitArray_BitAt(t *testing.T) {
   488  	mustPanic := func(ba *bitarray.BitArray, off int) {
   489  		t.Helper()
   490  		var b byte
   491  		defer func() {
   492  			t.Helper()
   493  			if recover() == nil {
   494  				t.Errorf("expected panic: got %d", b)
   495  			}
   496  		}()
   497  		b = ba.BitAt(off)
   498  	}
   499  
   500  	var ba *bitarray.BitArray
   501  	mustPanic(ba, 0)
   502  	mustPanic(ba, -1)
   503  	mustPanic(ba, 1)
   504  
   505  	ba = &bitarray.BitArray{}
   506  	mustPanic(ba, 0)
   507  	mustPanic(ba, -1)
   508  	mustPanic(ba, 1)
   509  
   510  	ba = bitarray.NewZeroFilled(1001)
   511  	mustPanic(ba, -1)
   512  	mustPanic(ba, 2000)
   513  	if b := ba.BitAt(123); b != 0 {
   514  		t.Errorf("unexpected: got %d, want 0", b)
   515  	}
   516  	if b := ba.ZExpand().BitAt(456); b != 0 {
   517  		t.Errorf("unexpected: got %d, want 0", b)
   518  	}
   519  
   520  	ba = bitarray.NewOneFilled(1001)
   521  	mustPanic(ba, -1)
   522  	mustPanic(ba, 2000)
   523  	if b := ba.BitAt(234); b != 1 {
   524  		t.Errorf("unexpected: got %d, want 1", b)
   525  	}
   526  	if b := ba.ZExpand().BitAt(567); b != 1 {
   527  		t.Errorf("unexpected: got %d, want 1", b)
   528  	}
   529  }
   530  
   531  func TestBitArray_Hash(t *testing.T) {
   532  	m := make(map[string]struct{})
   533  
   534  	add := func(ba *bitarray.BitArray) {
   535  		ba = ba.ZOptimize()
   536  		baE := ba.ZExpand()
   537  		h := ba.Hash(sha256.New())
   538  		hE := baE.Hash(sha256.New())
   539  		m[hex.EncodeToString(h)] = struct{}{}
   540  		m[hex.EncodeToString(hE)] = struct{}{}
   541  	}
   542  
   543  	for i := 0; i < 200; i++ { // 200
   544  		add(bitarray.NewZeroFilled(i))
   545  	}
   546  	for i := 0; i < 200; i++ { // 199, #0 is duplicated
   547  		add(bitarray.NewOneFilled(i))
   548  	}
   549  
   550  	var ba *bitarray.BitArray
   551  	add(ba) // duplicated
   552  
   553  	// 9
   554  	add(bitarray.MustParse("1")) // duplicated
   555  	add(bitarray.MustParse("10"))
   556  	add(bitarray.MustParse("100"))
   557  	add(bitarray.MustParse("1000"))
   558  	add(bitarray.MustParse("1000-0"))
   559  	add(bitarray.MustParse("1000-00"))
   560  	add(bitarray.MustParse("1000-000"))
   561  	add(bitarray.MustParse("1000-0000"))
   562  	add(bitarray.MustParse("1000-0000 0"))
   563  	add(bitarray.MustParse("1000-0000 00"))
   564  
   565  	// 9
   566  	add(bitarray.MustParse("0")) // duplicated
   567  	add(bitarray.MustParse("01"))
   568  	add(bitarray.MustParse("001"))
   569  	add(bitarray.MustParse("0001"))
   570  	add(bitarray.MustParse("0000-1"))
   571  	add(bitarray.MustParse("0000-01"))
   572  	add(bitarray.MustParse("0000-001"))
   573  	add(bitarray.MustParse("0000-0001"))
   574  	add(bitarray.MustParse("0000-0000 1"))
   575  	add(bitarray.MustParse("0000-0000 01"))
   576  
   577  	want := 200 + 199 + 9 + 9
   578  	if len(m) != want {
   579  		t.Errorf("unexpected number of keys: got %d, want %d", len(m), want)
   580  	}
   581  }
   582  
   583  func TestBitArray_MapKey(t *testing.T) {
   584  	m := make(map[string]struct{})
   585  
   586  	add := func(ba *bitarray.BitArray) {
   587  		m[ba.ZOptimize().MapKey()] = struct{}{}
   588  		m[ba.ZExpand().MapKey()] = struct{}{}
   589  	}
   590  
   591  	for i := 0; i < 200; i++ { // 200
   592  		add(bitarray.NewZeroFilled(i))
   593  	}
   594  	for i := 0; i < 200; i++ { // 199, #0 is duplicated
   595  		add(bitarray.NewOneFilled(i))
   596  	}
   597  
   598  	var ba *bitarray.BitArray
   599  	add(ba) // duplicated
   600  
   601  	// 9
   602  	add(bitarray.MustParse("1")) // duplicated
   603  	add(bitarray.MustParse("10"))
   604  	add(bitarray.MustParse("100"))
   605  	add(bitarray.MustParse("1000"))
   606  	add(bitarray.MustParse("1000-0"))
   607  	add(bitarray.MustParse("1000-00"))
   608  	add(bitarray.MustParse("1000-000"))
   609  	add(bitarray.MustParse("1000-0000"))
   610  	add(bitarray.MustParse("1000-0000 0"))
   611  	add(bitarray.MustParse("1000-0000 00"))
   612  
   613  	// 9
   614  	add(bitarray.MustParse("0")) // duplicated
   615  	add(bitarray.MustParse("01"))
   616  	add(bitarray.MustParse("001"))
   617  	add(bitarray.MustParse("0001"))
   618  	add(bitarray.MustParse("0000-1"))
   619  	add(bitarray.MustParse("0000-01"))
   620  	add(bitarray.MustParse("0000-001"))
   621  	add(bitarray.MustParse("0000-0001"))
   622  	add(bitarray.MustParse("0000-0000 1"))
   623  	add(bitarray.MustParse("0000-0000 01"))
   624  
   625  	want := 200 + 199 + 9 + 9
   626  	if len(m) != want {
   627  		t.Errorf("unexpected number of keys: got %d, want %d", len(m), want)
   628  	}
   629  }
   630  
   631  func TestBitArray_ToPadded8(t *testing.T) {
   632  	tdt := []string{
   633  		"", "",
   634  		"0", "0000-0000",
   635  		"00", "0000-0000",
   636  		"000", "0000-0000",
   637  		"0000", "0000-0000",
   638  		"0000-0", "0000-0000",
   639  		"0000-00", "0000-0000",
   640  		"0000-000", "0000-0000",
   641  		"0000-0000", "0000-0000",
   642  		"0000-0000 0", "0000-0000 0000-0000",
   643  		"0000-0000 00", "0000-0000 0000-0000",
   644  		"0000-0000 1010", "0000-0000 1010-0000",
   645  		"1", "1000-0000",
   646  		"11", "1100-0000",
   647  		"111", "1110-0000",
   648  		"1111", "1111-0000",
   649  		"1111-1", "1111-1000",
   650  		"1111-11", "1111-1100",
   651  		"1111-111", "1111-1110",
   652  		"1111-1111", "1111-1111",
   653  		"1111-1111 1", "1111-1111 1000-0000",
   654  		"1111-1111 0", "1111-1111 0000-0000",
   655  		"0xffffffff 0", "0xffffffff 0000-0000",
   656  	}
   657  	chk := func(got, want *bitarray.BitArray) {
   658  		t.Helper()
   659  		got.V()
   660  		if !got.Equal(want) {
   661  			t.Error("unexpected result:")
   662  			t.Logf(" got: %#b", got)
   663  			t.Logf(" got: %s", got.D())
   664  			t.Logf("want: %#b", want)
   665  		}
   666  	}
   667  	for i := 0; i < len(tdt); i += 2 {
   668  		ba0 := bitarray.MustParse(tdt[i]).ZOptimize()
   669  		want := bitarray.MustParse(tdt[i+1])
   670  		got := ba0.ToPadded8()
   671  		gotE := ba0.ZExpand().ToPadded8()
   672  		chk(got, want)
   673  		chk(gotE, want)
   674  	}
   675  }
   676  
   677  func TestBitArray_ToPadded64(t *testing.T) {
   678  	tdt := []string{
   679  		"", "",
   680  		"0", "0x_0000_0000_0000_0000",
   681  		"1", "0x_8000_0000_0000_0000",
   682  		"0x_0000_0000_0000_0000 0x_0000_0000_0000_000", "0x_0000_0000_0000_0000 0x_0000_0000_0000_0000",
   683  		"0x_0000_0000_0000_0000 0x_0000_0000_0000_0000", "0x_0000_0000_0000_0000 0x_0000_0000_0000_0000",
   684  		"0x_0000_dead_beef_cafe 0x_0000_8888_0000_000", "0x_0000_dead_beef_cafe 0x_0000_8888_0000_0000",
   685  		"0x_0000_dead_beef_cafe 0x_0000_8888_0000_0000", "0x_0000_dead_beef_cafe 0x_0000_8888_0000_0000",
   686  		"0x_f0f0_f0f0_f0f0_f0f0 100", "0x_f0f0_f0f0_f0f0_f0f0 0x_8000_0000_0000_0000",
   687  	}
   688  	chk := func(got, want *bitarray.BitArray) {
   689  		t.Helper()
   690  		got.V()
   691  		if !got.Equal(want) {
   692  			t.Error("unexpected result:")
   693  			t.Logf(" got: %#b", got)
   694  			t.Logf(" got: %s", got.D())
   695  			t.Logf("want: %#b", want)
   696  		}
   697  	}
   698  	for i := 0; i < len(tdt); i += 2 {
   699  		ba0 := bitarray.MustParse(tdt[i]).ZOptimize()
   700  		want := bitarray.MustParse(tdt[i+1])
   701  		got := ba0.ToPadded64()
   702  		gotE := ba0.ZExpand().ToPadded64()
   703  		chk(got, want)
   704  		chk(gotE, want)
   705  	}
   706  }
   707  
   708  func TestBitArray_ToByteBits(t *testing.T) {
   709  	tcs := []struct {
   710  		s    string
   711  		want []byte
   712  	}{
   713  		{"", []byte{}},
   714  		{"0", []byte{0}},
   715  		{"1", []byte{1}},
   716  		{"0000-000", []byte{0, 0, 0, 0, 0, 0, 0}},
   717  		{"0000-0000", []byte{0, 0, 0, 0, 0, 0, 0, 0}},
   718  		{"0000-0000 0", []byte{0, 0, 0, 0, 0, 0, 0, 0, 0}},
   719  		{"1111-111", []byte{1, 1, 1, 1, 1, 1, 1}},
   720  		{"1111-1111", []byte{1, 1, 1, 1, 1, 1, 1, 1}},
   721  		{"1111-1111 1", []byte{1, 1, 1, 1, 1, 1, 1, 1, 1}},
   722  		{"1010-0101 1111-0011 101", []byte{1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1}},
   723  	}
   724  	chk := func(got, want []byte) {
   725  		if !bytes.Equal(got, want) {
   726  			t.Error("unexpected result:")
   727  			t.Logf(" got: %d", got)
   728  			t.Logf("want: %d", want)
   729  		}
   730  	}
   731  	for _, tc := range tcs {
   732  		ba0 := bitarray.MustParse(tc.s).ZOptimize()
   733  		got := ba0.ToByteBits()
   734  		gotE := ba0.ZExpand().ToByteBits()
   735  		chk(got, tc.want)
   736  		chk(gotE, tc.want)
   737  	}
   738  }
   739  
   740  func TestBitArray_RepeatEach(t *testing.T) {
   741  	tcs := []struct {
   742  		n        int
   743  		src, dst string
   744  	}{
   745  		{0, "", ""},
   746  		{1, "", ""},
   747  		{0, "0000", ""},
   748  		{0, "1111", ""},
   749  		{1, "0000", "0000"},
   750  		{1, "0000-0000", "0000-0000"},
   751  		{1, "1111-1111", "1111-1111"},
   752  		{2, "0000-0000", "0000-0000 0000-0000"},
   753  		{2, "0000-0000 00", "0000-0000 0000-0000 0000"},
   754  		{3, "0000-0000 00", "0000-0000 0000-0000 0000-0000 0000-00"},
   755  		{2, "1111-1111", "1111-1111 1111-1111"},
   756  		{2, "1111-1111 111", "1111-1111 1111-1111 1111-11"},
   757  		{2, "1010-0101", "1100-1100 0011-0011"},
   758  		{2, "1010-0101 11", "1100-1100 0011-0011 1111"},
   759  		{4, "1010-1100 01", "1111-0000 1111-0000 1111-1111 0000-0000 0000-1111"},
   760  	}
   761  	chk := func(n int, src, want *bitarray.BitArray) {
   762  		t.Helper()
   763  		got := src.RepeatEach(n)
   764  		got.V()
   765  		if !got.Equal(want) {
   766  			t.Errorf("unexpected: n=%d", n)
   767  			t.Logf(" src: %#b", src)
   768  			t.Logf(" got: %#b", got)
   769  			t.Logf(" got: %s", got.D())
   770  			t.Logf("want: %#b", want)
   771  			t.FailNow()
   772  		}
   773  	}
   774  	for _, tc := range tcs {
   775  		ba0 := bitarray.MustParse(tc.src).ZOptimize()
   776  		ba0E := ba0.ZExpand()
   777  		exp := bitarray.MustParse(tc.dst)
   778  		chk(tc.n, ba0, exp)
   779  		chk(tc.n, ba0E, exp)
   780  	}
   781  	func() {
   782  		var ba *bitarray.BitArray
   783  		defer func() {
   784  			if recover() == nil {
   785  				t.Errorf("panic expected: got %#b", ba)
   786  			}
   787  		}()
   788  		src := bitarray.MustParse("0101-0101 01")
   789  		ba = src.RepeatEach(-1)
   790  	}()
   791  }