github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/bitarray/bitarray_test.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package bitarray
    12  
    13  import (
    14  	"bytes"
    15  	"fmt"
    16  	"reflect"
    17  	"strconv"
    18  	"strings"
    19  	"testing"
    20  
    21  	"github.com/cockroachdb/cockroach/pkg/util/randutil"
    22  )
    23  
    24  func TestParseFormat(t *testing.T) {
    25  	testData := []struct {
    26  		str string
    27  		ba  BitArray
    28  	}{
    29  		{"", BitArray{words: nil, lastBitsUsed: 0}},
    30  		{"0", BitArray{words: []word{0}, lastBitsUsed: 1}},
    31  		{"1", BitArray{words: []word{0x8000000000000000}, lastBitsUsed: 1}},
    32  		{"0000", BitArray{words: []word{0}, lastBitsUsed: 4}},
    33  		{"1010", BitArray{words: []word{0xA000000000000000}, lastBitsUsed: 4}},
    34  		{"10111010101111101111101011001110" + "11001010111111101011101010111110",
    35  			BitArray{words: []word{0xBABEFACECAFEBABE}, lastBitsUsed: 64}},
    36  		{"10111010101111101111101011001110" + "11001010111111101011101010111110" +
    37  			"110010101101110100011110",
    38  			BitArray{words: []word{0xBABEFACECAFEBABE, 0xCADD1E0000000000}, lastBitsUsed: 24}},
    39  	}
    40  
    41  	for _, test := range testData {
    42  		t.Run(test.str, func(t *testing.T) {
    43  			ba, err := Parse(test.str)
    44  			if err != nil {
    45  				t.Fatalf("error during parse: %v", err)
    46  			}
    47  
    48  			if !reflect.DeepEqual(ba, test.ba) {
    49  				t.Fatalf("expected %+v, got %+v", test.ba, ba)
    50  			}
    51  
    52  			res := ba.String()
    53  			if res != test.str {
    54  				t.Fatalf("format expected %q, got %q", test.str, res)
    55  			}
    56  		})
    57  	}
    58  }
    59  
    60  func TestFromEncodingParts(t *testing.T) {
    61  	testData := []struct {
    62  		words        []uint64
    63  		lastBitsUsed uint64
    64  		ba           BitArray
    65  		err          string
    66  	}{
    67  		{nil, 0, BitArray{words: nil, lastBitsUsed: 0}, ""},
    68  		{[]uint64{0}, 0, BitArray{words: []word{0}, lastBitsUsed: 0}, ""},
    69  		{[]uint64{42}, 3, BitArray{words: []word{42}, lastBitsUsed: 3}, ""},
    70  		{[]uint64{42}, 65, BitArray{}, "FromEncodingParts: lastBitsUsed must not exceed 64, got 65"},
    71  	}
    72  
    73  	for _, test := range testData {
    74  		t.Run(fmt.Sprintf("{%v,%d}", test.words, test.lastBitsUsed), func(t *testing.T) {
    75  			ba, err := FromEncodingParts(test.words, test.lastBitsUsed)
    76  			if test.err != "" && (err == nil || test.err != err.Error()) {
    77  				t.Errorf("expected %q error, but got: %+v", test.err, err)
    78  			} else if test.err == "" && err != nil {
    79  				t.Errorf("unexpected error: %s", err)
    80  			} else if !reflect.DeepEqual(ba, test.ba) {
    81  				t.Errorf("expected %s, got %s", test.ba.viz(), ba.viz())
    82  			}
    83  		})
    84  	}
    85  }
    86  
    87  func (d BitArray) viz() string {
    88  	var buf bytes.Buffer
    89  	buf.WriteString("bitarray{[")
    90  	comma := ""
    91  	for _, w := range d.words {
    92  		buf.WriteString(comma)
    93  		for i := 60; i > 0; i -= 4 {
    94  			if i < 60 {
    95  				buf.WriteByte(' ')
    96  			}
    97  			c := strconv.FormatUint((w>>uint(i))&0xf, 2)
    98  			if len(c) < 4 {
    99  				fmt.Fprintf(&buf, "%0*d", 4-len(c), 0)
   100  			}
   101  			buf.WriteString(c)
   102  		}
   103  		comma = ","
   104  	}
   105  	fmt.Fprintf(&buf, "],%d}", d.lastBitsUsed)
   106  	return buf.String()
   107  }
   108  
   109  func TestToWidth(t *testing.T) {
   110  	testData := []struct {
   111  		str     string
   112  		toWidth uint
   113  		ba      BitArray
   114  	}{
   115  		{"", 0, BitArray{words: nil, lastBitsUsed: 0}},
   116  		{"", 1, BitArray{words: []word{0}, lastBitsUsed: 1}},
   117  		{"", 64, BitArray{words: []word{0}, lastBitsUsed: 64}},
   118  		{"", 100, BitArray{words: []word{0, 0}, lastBitsUsed: 36}},
   119  		{"0", 0, BitArray{words: nil, lastBitsUsed: 0}},
   120  		{"0", 1, BitArray{words: []word{0}, lastBitsUsed: 1}},
   121  		{"0", 100, BitArray{words: []word{0, 0}, lastBitsUsed: 36}},
   122  		{"1", 1, BitArray{words: []word{0x8000000000000000}, lastBitsUsed: 1}},
   123  		{"1", 64, BitArray{words: []word{0x8000000000000000}, lastBitsUsed: 64}},
   124  		{"1", 100, BitArray{words: []word{0x8000000000000000, 0}, lastBitsUsed: 36}},
   125  		{"0000", 4, BitArray{words: []word{0}, lastBitsUsed: 4}},
   126  		{"1010", 4, BitArray{words: []word{0xA000000000000000}, lastBitsUsed: 4}},
   127  		{"0000", 0, BitArray{words: nil, lastBitsUsed: 0}},
   128  		{"1010", 2, BitArray{words: []word{0x8000000000000000}, lastBitsUsed: 2}},
   129  		{"10111010101111101111101011001110" + "11001010111111101011101010111110",
   130  			64,
   131  			BitArray{words: []word{0xBABEFACECAFEBABE}, lastBitsUsed: 64}},
   132  		{"10111010101111101111101011001110" + "11001010111111101011101010111110",
   133  			16,
   134  			BitArray{words: []word{0xBABE000000000000}, lastBitsUsed: 16}},
   135  		{"10111010101111101111101011001110" + "11001010111111101011101010111110" +
   136  			"110010101101110100011110",
   137  			60,
   138  			BitArray{words: []word{0xBABEFACECAFEBAB0}, lastBitsUsed: 60}},
   139  		{"10111010101111101111101011001110" + "11001010111111101011101010111110" +
   140  			"110010101101110100011110",
   141  			100,
   142  			BitArray{words: []word{0xBABEFACECAFEBABE, 0xCADD1E0000000000}, lastBitsUsed: 36}},
   143  	}
   144  
   145  	for _, test := range testData {
   146  		t.Run(fmt.Sprintf("%s/%d", test.str, test.toWidth), func(t *testing.T) {
   147  			ba, err := Parse(test.str)
   148  			if err != nil {
   149  				t.Fatalf("error during parse: %v", err)
   150  			}
   151  
   152  			ba = ba.ToWidth(test.toWidth)
   153  
   154  			if !reflect.DeepEqual(ba, test.ba) {
   155  				t.Fatalf("expected %s, got %s", test.ba.viz(), ba.viz())
   156  			}
   157  
   158  			vs := ba.String()
   159  			if uint(len(vs)) != test.toWidth {
   160  				t.Fatalf("expected len %d in representation, got %d", test.toWidth, len(vs))
   161  			}
   162  			if uint(len(test.str)) < test.toWidth {
   163  				exp := test.str + fmt.Sprintf("%0*d", int(test.toWidth)-len(test.str), 0)
   164  				if vs != exp {
   165  					t.Fatalf("expected %q, got %q", exp, vs)
   166  				}
   167  			} else {
   168  				if test.str[:int(test.toWidth)] != vs {
   169  					t.Fatalf("expected %q, got %q", test.str[:int(test.toWidth)], vs)
   170  				}
   171  			}
   172  		})
   173  	}
   174  }
   175  
   176  func TestToInt(t *testing.T) {
   177  	testData := []struct {
   178  		str     string
   179  		nbits   uint
   180  		exp     int64
   181  		expbits string
   182  	}{
   183  		{"", 0, 0, "0"},
   184  		{"", 1, 0, "0"},
   185  		{"", 64, 0, "0"},
   186  		{"0", 0, 0, "0"},
   187  		{"0", 1, 0, "0"},
   188  		{"0", 64, 0, "0"},
   189  		{"1", 0, 0, "0"},
   190  		{"1", 1, -1, "1111111111111111111111111111111111111111111111111111111111111111"},
   191  		{"1", 64, 1, "1"},
   192  		{"01", 0, 0, "0"},
   193  		{"01", 1, -1, "1111111111111111111111111111111111111111111111111111111111111111"},
   194  		{"01", 2, 1, "1"},
   195  		{"01", 64, 1, "1"},
   196  		{"10111010101111101111101011001110" + "11001010111111101011101010111110" +
   197  			"110010101101110100011110", 6, 30, "11110"},
   198  		{"10111010101111101111101011001110" + "11001010111111101011101000111110" +
   199  			"110010101101110100011110", 32, 0x3ECADD1E,
   200  			"111110" + "110010101101110100011110"},
   201  	}
   202  
   203  	for _, test := range testData {
   204  		t.Run(fmt.Sprintf("%s/%d", test.str, test.nbits), func(t *testing.T) {
   205  			expbits := strconv.FormatUint(uint64(test.exp), 2)
   206  			if expbits != test.expbits {
   207  				t.Fatalf("programming error: invalid expbits: got %q, expected %q", expbits, test.expbits)
   208  			}
   209  			ba, err := Parse(test.str)
   210  			if err != nil {
   211  				t.Fatal(err)
   212  			}
   213  			if ba.String() != test.str {
   214  				t.Fatalf("expected %q, got %q", test.str, ba.String())
   215  			}
   216  			res := ba.AsInt64(test.nbits)
   217  			if res != test.exp {
   218  				t.Fatalf("expected %d (%b), got %d (%b)", test.exp, test.exp, res, uint64(res))
   219  			}
   220  		})
   221  	}
   222  }
   223  
   224  func TestFromInt(t *testing.T) {
   225  	largeVal := uint64(0xCAFEBABEDEADBEEF)
   226  	sLarge := int64(largeVal)
   227  	uLarge := int64(largeVal ^ (1 << 63))
   228  	t.Logf("sLarge = %d (%#x)", sLarge, sLarge)
   229  	t.Logf("uLarge = %d (%#x)", uLarge, uLarge)
   230  	testData := []struct {
   231  		bitlen   uint
   232  		val      int64
   233  		valWidth uint
   234  		exp      string
   235  	}{
   236  		{0, 123, 0, ""},
   237  		{0, 123, 64, ""},
   238  		{1, 0x1, 0, "0"},
   239  		{1, 0x1, 1, "1"},
   240  		{2, 0x1, 1, "11" /* sign extend from 1 to 2 bits */},
   241  		{64, 0x2, 2, "11111111111111111111111111111111" + "11111111111111111111111111111110"},
   242  		{64, 0x2, 3, "00000000000000000000000000000000" + "00000000000000000000000000000010"},
   243  		{67, 0x2, 2, "11111111111111111111111111111111" + "11111111111111111111111111111111" + "110"},
   244  		{67, 0x2, 3, "00000000000000000000000000000000" + "00000000000000000000000000000000" + "010"},
   245  		{131, 0x2, 2,
   246  			"11111111111111111111111111111111" + "11111111111111111111111111111111" +
   247  				"11111111111111111111111111111111" + "11111111111111111111111111111111" + "110"},
   248  		{131, 0x2, 3,
   249  			"00000000000000000000000000000000" + "00000000000000000000000000000000" +
   250  				"00000000000000000000000000000000" + "00000000000000000000000000000000" + "010"},
   251  		{67, 0xAA, 8, "11111111111111111111111111111111" + "11111111111111111111111111110101" + "010"},
   252  		{67, 0xAA, 9, "00000000000000000000000000000000" + "00000000000000000000000000010101" + "010"},
   253  		{131, 0xAA, 8,
   254  			"11111111111111111111111111111111" + "11111111111111111111111111111111" +
   255  				"11111111111111111111111111111111" + "11111111111111111111111111110101" + "010"},
   256  		{131, 0xAA, 9,
   257  			"00000000000000000000000000000000" + "00000000000000000000000000000000" +
   258  				"00000000000000000000000000000000" + "00000000000000000000000000010101" + "010"},
   259  		{12, sLarge, 64, "111011101111"},
   260  		{64, sLarge, 64, "11001010111111101011101010111110" + "11011110101011011011111011101111"},
   261  		{64, uLarge, 64, "01001010111111101011101010111110" + "11011110101011011011111011101111"},
   262  		{67, sLarge, 64, "111" + "11001010111111101011101010111110" + "11011110101011011011111011101111"},
   263  		{67, uLarge, 64, "000" + "01001010111111101011101010111110" + "11011110101011011011111011101111"},
   264  	}
   265  
   266  	for _, test := range testData {
   267  		t.Run(fmt.Sprintf("%d/%0*b", test.bitlen, test.valWidth, test.val), func(t *testing.T) {
   268  			d := MakeBitArrayFromInt64(test.bitlen, test.val, test.valWidth)
   269  			res := d.String()
   270  			if res != test.exp {
   271  				t.Fatalf("expected %q, got %q", test.exp, res)
   272  			}
   273  		})
   274  	}
   275  
   276  }
   277  
   278  func TestAnd(t *testing.T) {
   279  	testData := []struct {
   280  		lhs, rhs, result string
   281  	}{
   282  		{"", "", ""},
   283  		{"0", "0", "0"},
   284  		{"0", "1", "0"},
   285  		{"1", "0", "0"},
   286  		{"1", "1", "1"},
   287  		{"1111", "1100", "1100"},
   288  		{"10111010101111101111101011001110" + "11001010111111101011101010111110" + "010",
   289  			"11001010111111101011101010111110" + "10111010101111101111101011001110" + "011",
   290  			"10001010101111101011101010001110" + "10001010101111101011101010001110" + "010"},
   291  	}
   292  
   293  	for _, test := range testData {
   294  		t.Run(test.lhs+"&"+test.rhs, func(t *testing.T) {
   295  			lhs, err := Parse(test.lhs)
   296  			if err != nil {
   297  				t.Fatalf("error during parse: %v", err)
   298  			}
   299  			rhs, err := Parse(test.rhs)
   300  			if err != nil {
   301  				t.Fatalf("error during parse: %v", err)
   302  			}
   303  			res := And(lhs, rhs)
   304  			resStr := res.String()
   305  			if resStr != test.result {
   306  				t.Fatalf("concat expected %q, got %q", test.result, resStr)
   307  			}
   308  			res2, err := Parse(resStr)
   309  			if err != nil {
   310  				t.Fatal(err)
   311  			}
   312  			if !reflect.DeepEqual(res2, res) {
   313  				t.Fatalf("result does not roundrip, expected %s, got %s", res.viz(), res2.viz())
   314  			}
   315  		})
   316  	}
   317  }
   318  
   319  func TestOr(t *testing.T) {
   320  	testData := []struct {
   321  		lhs, rhs, result string
   322  	}{
   323  		{"", "", ""},
   324  		{"0", "0", "0"},
   325  		{"0", "1", "1"},
   326  		{"1", "0", "1"},
   327  		{"1", "1", "1"},
   328  		{"1100", "0101", "1101"},
   329  		{"10111010101111101111101011001110" + "11001010111111101011101010111110" + "010",
   330  			"11001010111111101011101010111110" + "10111010101111101111101011001110" + "011",
   331  			"11111010111111101111101011111110" + "11111010111111101111101011111110" + "011"},
   332  	}
   333  
   334  	for _, test := range testData {
   335  		t.Run(test.lhs+"|"+test.rhs, func(t *testing.T) {
   336  			lhs, err := Parse(test.lhs)
   337  			if err != nil {
   338  				t.Fatalf("error during parse: %v", err)
   339  			}
   340  			rhs, err := Parse(test.rhs)
   341  			if err != nil {
   342  				t.Fatalf("error during parse: %v", err)
   343  			}
   344  			res := Or(lhs, rhs)
   345  			resStr := res.String()
   346  			if resStr != test.result {
   347  				t.Fatalf("concat expected %q, got %q", test.result, resStr)
   348  			}
   349  
   350  			res2, err := Parse(resStr)
   351  			if err != nil {
   352  				t.Fatal(err)
   353  			}
   354  			if !reflect.DeepEqual(res2, res) {
   355  				t.Fatalf("result does not roundrip, expected %s, got %s", res.viz(), res2.viz())
   356  			}
   357  		})
   358  	}
   359  }
   360  
   361  func TestXor(t *testing.T) {
   362  	testData := []struct {
   363  		lhs, rhs, result string
   364  	}{
   365  		{"", "", ""},
   366  		{"0", "0", "0"},
   367  		{"0", "1", "1"},
   368  		{"1", "0", "1"},
   369  		{"1", "1", "0"},
   370  		{"1100", "0101", "1001"},
   371  		{"10111010101111101111101011001110" + "11001010111111101011101010111110" + "010",
   372  			"11001010111111101011101010111110" + "10111010101111101111101011001110" + "011",
   373  			"01110000010000000100000001110000" + "01110000010000000100000001110000" + "001"},
   374  	}
   375  
   376  	for _, test := range testData {
   377  		t.Run(test.lhs+"^"+test.rhs, func(t *testing.T) {
   378  			lhs, err := Parse(test.lhs)
   379  			if err != nil {
   380  				t.Fatalf("error during parse: %v", err)
   381  			}
   382  			rhs, err := Parse(test.rhs)
   383  			if err != nil {
   384  				t.Fatalf("error during parse: %v", err)
   385  			}
   386  			res := Xor(lhs, rhs)
   387  			resStr := res.String()
   388  			if resStr != test.result {
   389  				t.Fatalf("concat expected %q, got %q", test.result, resStr)
   390  			}
   391  
   392  			res2, err := Parse(resStr)
   393  			if err != nil {
   394  				t.Fatal(err)
   395  			}
   396  			if !reflect.DeepEqual(res2, res) {
   397  				t.Fatalf("result does not roundrip, expected %s, got %s", res.viz(), res2.viz())
   398  			}
   399  		})
   400  	}
   401  }
   402  
   403  func TestNot(t *testing.T) {
   404  	testData := []struct {
   405  		val, res string
   406  	}{
   407  		{"", ""},
   408  		{"0", "1"},
   409  		{"1", "0"},
   410  		{"1100", "0011"},
   411  		{"10111010101111101111101011001110" + "11001010111111101011101010111110",
   412  			"01000101010000010000010100110001" + "00110101000000010100010101000001"},
   413  		{"10111010101111101111101011001110" + "11001010111111101011101010111110" + "111",
   414  			"01000101010000010000010100110001" + "00110101000000010100010101000001" + "000"},
   415  	}
   416  
   417  	for _, test := range testData {
   418  		t.Run(test.val, func(t *testing.T) {
   419  			ba, err := Parse(test.val)
   420  			if err != nil {
   421  				t.Fatal(err)
   422  			}
   423  
   424  			res := Not(ba)
   425  			resStr := res.String()
   426  			if resStr != test.res {
   427  				t.Fatalf("not: expected %q, got %q", test.res, resStr)
   428  			}
   429  
   430  			res2, err := Parse(resStr)
   431  			if err != nil {
   432  				t.Fatal(err)
   433  			}
   434  			if !reflect.DeepEqual(res2, res) {
   435  				t.Fatalf("result does not roundrip, expected %s, got %s", res.viz(), res2.viz())
   436  			}
   437  		})
   438  	}
   439  }
   440  
   441  func TestNext(t *testing.T) {
   442  	testData := []struct {
   443  		val, res string
   444  	}{
   445  		{"", "0"},
   446  		{"0", "00"},
   447  		{"1", "10"},
   448  		{"1100", "11000"},
   449  		{"10111010101111101111101011001110" + "11001010111111101011101010111110",
   450  			"10111010101111101111101011001110" + "11001010111111101011101010111110" + "0"},
   451  	}
   452  
   453  	for _, test := range testData {
   454  		t.Run(test.val, func(t *testing.T) {
   455  			ba, err := Parse(test.val)
   456  			if err != nil {
   457  				t.Fatal(err)
   458  			}
   459  
   460  			res := Next(ba)
   461  			resStr := res.String()
   462  			if resStr != test.res {
   463  				t.Fatalf("not: expected %q, got %q", test.res, resStr)
   464  			}
   465  
   466  			res2, err := Parse(resStr)
   467  			if err != nil {
   468  				t.Fatal(err)
   469  			}
   470  			if !reflect.DeepEqual(res2, res) {
   471  				t.Fatalf("result does not roundrip, expected %s, got %s", res.viz(), res2.viz())
   472  			}
   473  		})
   474  	}
   475  }
   476  
   477  func TestCompare(t *testing.T) {
   478  	const lt = -1
   479  	const eq = 0
   480  	const gt = 1
   481  	const big = "10111010101111101111101011001110" + "11001010111111101011101010111110"
   482  	testData := []struct {
   483  		lhs string
   484  		cmp int
   485  		rhs string
   486  	}{
   487  		{"", eq, ""},
   488  		{"", lt, "0"},
   489  		{"0", lt, "1"},
   490  		{"", lt, "1"},
   491  		{"0", eq, "0"},
   492  		{"0", gt, ""},
   493  		{"1", gt, "0"},
   494  		{"1", gt, ""},
   495  		{"1", eq, "1"},
   496  		{"0", lt, "0000"},
   497  		{"0000", lt, "00001"},
   498  		{"00001", lt, "0001"},
   499  		{"0001", lt, "00100"},
   500  		{"00100", lt, "00110"},
   501  		{"00110", lt, "010"},
   502  		{"010", lt, "01001001010101"},
   503  		{"01001001010101", lt, "1"},
   504  		{"1", lt, "10"},
   505  		{"10", lt, "1001001010101"},
   506  		{"1001001010101", lt, "11"},
   507  		{"11", lt, "11001001010101"},
   508  	}
   509  
   510  	for _, prefix := range []string{"", big} {
   511  		for _, test := range testData {
   512  			const chars = "<=>"
   513  			t.Run(prefix+test.lhs+chars[test.cmp+1:test.cmp+2]+prefix+test.rhs, func(t *testing.T) {
   514  				lhs, err := Parse(prefix + test.lhs)
   515  				if err != nil {
   516  					t.Fatal(err)
   517  				}
   518  				rhs, err := Parse(prefix + test.rhs)
   519  				if err != nil {
   520  					t.Fatal(err)
   521  				}
   522  				cmp := Compare(lhs, rhs)
   523  				if cmp != test.cmp {
   524  					t.Fatalf("compare expected %d, got %d", test.cmp, cmp)
   525  				}
   526  			})
   527  		}
   528  	}
   529  }
   530  
   531  func TestShift(t *testing.T) {
   532  	const big = "10111010101111101111101011001110" + "11001010111111101011101010111110" +
   533  		"11001010111111101011101010111110" + "10111010101111101111101011001110"
   534  
   535  	const big2s = "1111 0101 0011 1011 1110 1001 0010 1100" +
   536  		"0110 1110 1111 0011 0001 1010 1100 0110" +
   537  		"0000 0011 1101 1110 0101 0100 0010 1010"
   538  	big2 := strings.Replace(big2s, " ", "", -1)
   539  
   540  	testData := []struct {
   541  		src string
   542  		sh  int64
   543  		res string
   544  	}{
   545  		{"", 0, ""},
   546  		{"", 1, ""},
   547  		{"", -1, ""},
   548  		{"", 100, ""},
   549  		{"", -100, ""},
   550  		{"0", 0, "0"},
   551  		{"0", 1, "0"},
   552  		{"0", -1, "0"},
   553  		{"0", 100, "0"},
   554  		{"0", -100, "0"},
   555  		{"1", 0, "1"},
   556  		{"1", 1, "0"},
   557  		{"1", -1, "0"},
   558  		{"1", 100, "0"},
   559  		{"1", -100, "0"},
   560  		{"010", 0, "010"},
   561  		{"010", 1, "100"},
   562  		{"010", -1, "001"},
   563  		{"010", 100, "000"},
   564  		{"010", -100, "000"},
   565  		{big, 1, big[1:] + "0"},
   566  		{big, -1, "0" + big[:len(big)-1]},
   567  		{big, 100, big[100:] + fmt.Sprintf("%0*d", 100, 0)},
   568  		{big, -100, fmt.Sprintf("%0*d", 100, 0) + big[:len(big)-100]},
   569  		{big2, 32, big2[32:] + fmt.Sprintf("%0*d", 32, 0)},
   570  		// Regression test for #36606.
   571  		{big2, -32, fmt.Sprintf("%0*d", 32, 0) + big2[:len(big2)-32]},
   572  		{big2, 31, big2[31:] + fmt.Sprintf("%0*d", 31, 0)},
   573  		// Regression test for #36606.
   574  		{big2, -31, fmt.Sprintf("%0*d", 31, 0) + big2[:len(big2)-31]},
   575  	}
   576  
   577  	for _, test := range testData {
   578  		t.Run(fmt.Sprintf("%s<<%d", test.src, test.sh), func(t *testing.T) {
   579  			val, err := Parse(test.src)
   580  			if err != nil {
   581  				t.Fatal(err)
   582  			}
   583  			t.Logf("source val:\n%s", val.viz())
   584  			res := val.LeftShiftAny(test.sh)
   585  			resStr := res.String()
   586  			if resStr != test.res {
   587  				t.Fatalf("expected %q, got %q", test.res, resStr)
   588  			}
   589  
   590  			res2, err := Parse(resStr)
   591  			if err != nil {
   592  				t.Fatal(err)
   593  			}
   594  			if !reflect.DeepEqual(res2, res) {
   595  				t.Fatalf("result does not roundrip, expected:\n%s, got:\n%s", res.viz(), res2.viz())
   596  			}
   597  		})
   598  	}
   599  }
   600  
   601  func TestConcat(t *testing.T) {
   602  	testData := []struct {
   603  		lhs, rhs, result string
   604  	}{
   605  		{"", "", ""},
   606  		{"0", "", "0"},
   607  		{"", "0", "0"},
   608  		{"0", "0", "00"},
   609  		{"1111", "00", "111100"},
   610  		{"11", "0000", "110000"},
   611  		{"10111010101111101111101011001110" + "11001010111111101011101010111110", "000",
   612  			"10111010101111101111101011001110" + "11001010111111101011101010111110" + "000"},
   613  		{"10111010101111101111101011001110", "11001010111111101011101010111110" + "000",
   614  			"10111010101111101111101011001110" + "11001010111111101011101010111110" + "000"},
   615  		{"000", "10111010101111101111101011001110" + "11001010111111101011101010111110",
   616  			"000" + "10111010101111101111101011001110" + "11001010111111101011101010111110"},
   617  		{"000" + "10111010101111101111101011001110", "11001010111111101011101010111110",
   618  			"000" + "10111010101111101111101011001110" + "11001010111111101011101010111110"},
   619  		{"10111010101111101111101011001110" + "11001010111111101011101010111110", "001",
   620  			"10111010101111101111101011001110" + "11001010111111101011101010111110" + "001"},
   621  		{"10111010101111101111101011001110", "11001010111111101011101010111110" + "001",
   622  			"10111010101111101111101011001110" + "11001010111111101011101010111110" + "001"},
   623  		{"001", "10111010101111101111101011001110" + "11001010111111101011101010111110",
   624  			"001" + "10111010101111101111101011001110" + "11001010111111101011101010111110"},
   625  		{"001" + "10111010101111101111101011001110", "11001010111111101011101010111110",
   626  			"001" + "10111010101111101111101011001110" + "11001010111111101011101010111110"},
   627  	}
   628  
   629  	for _, test := range testData {
   630  		t.Run(test.lhs+"+"+test.rhs, func(t *testing.T) {
   631  			lhs, err := Parse(test.lhs)
   632  			if err != nil {
   633  				t.Fatalf("error during parse: %v", err)
   634  			}
   635  			rhs, err := Parse(test.rhs)
   636  			if err != nil {
   637  				t.Fatalf("error during parse: %v", err)
   638  			}
   639  			res := Concat(lhs, rhs)
   640  			resStr := res.String()
   641  			if resStr != test.result {
   642  				t.Fatalf("concat expected %q, got %q", test.result, resStr)
   643  			}
   644  
   645  			res2, err := Parse(resStr)
   646  			if err != nil {
   647  				t.Fatal(err)
   648  			}
   649  			if !reflect.DeepEqual(res2, res) {
   650  				t.Fatalf("result does not roundrip, expected %s, got %s", res.viz(), res2.viz())
   651  			}
   652  		})
   653  	}
   654  }
   655  
   656  func TestConcatRand(t *testing.T) {
   657  	rng, _ := randutil.NewPseudoRand()
   658  
   659  	for i := 0; i < 1000; i++ {
   660  		w1 := uint(rng.Int31n(256))
   661  		w2 := uint(rng.Int31n(256))
   662  		lhs := Rand(rng, w1)
   663  		rhs := Rand(rng, w2)
   664  
   665  		r1c := Concat(lhs, rhs)
   666  		r1 := r1c.String()
   667  		r2 := lhs.String() + rhs.String()
   668  		if r1 != r2 {
   669  			t.Errorf("%q || %q: expected %q, got %q", lhs, rhs, r2, r1)
   670  		}
   671  
   672  		res2, err := Parse(r1)
   673  		if err != nil {
   674  			t.Fatal(err)
   675  		}
   676  		if !reflect.DeepEqual(res2, r1c) {
   677  			t.Fatalf("result does not roundrip, expected %s, got %s", r1c.viz(), res2.viz())
   678  		}
   679  
   680  	}
   681  }
   682  
   683  func TestGetBitAtIndex(t *testing.T) {
   684  	testData := []struct {
   685  		bitString, err string
   686  		index, res     int
   687  	}{
   688  		{"1001010", "", 0, 1},
   689  		{"1010101", "", 1, 0},
   690  		{"111111111111110001010101000000", "", 20, 0},
   691  		{"111111111111110001011101000000", "", 20, 1},
   692  		{"11111111", "", 7, 1},
   693  		{"010110", "GetBitAtIndex: bit index -1 out of valid range (0..5)", -1, 0},
   694  		{"", "GetBitAtIndex: bit index 0 out of valid range (0..-1)", 0, 0},
   695  		{"10100110", "GetBitAtIndex: bit index 8 out of valid range (0..7)", 8, 0},
   696  	}
   697  	for _, test := range testData {
   698  		t.Run(fmt.Sprintf("{%v,%d}", test.bitString, test.index), func(t *testing.T) {
   699  			ba, err := Parse(test.bitString)
   700  			if err != nil {
   701  				t.Fatal(err)
   702  			}
   703  			res, err := ba.GetBitAtIndex(test.index)
   704  			if test.err != "" && (err == nil || test.err != err.Error()) {
   705  				t.Errorf("expected %q error, but got: %+v", test.err, err)
   706  			} else if test.err == "" && err != nil {
   707  				t.Errorf("unexpected error: %s", err.Error())
   708  			} else if !reflect.DeepEqual(test.res, res) {
   709  				t.Errorf("expected %d, got %d", test.res, res)
   710  			}
   711  		})
   712  	}
   713  }
   714  
   715  func TestSetBitAtIndex(t *testing.T) {
   716  	testData := []struct {
   717  		bitString, err, res string
   718  		index, toSet        int
   719  	}{
   720  		{"1001010", "", "1101010", 1, 1},
   721  		{"1010101", "", "0010101", 0, 0},
   722  		{"1010101011", "", "1010101011", 0, 1},
   723  		{"1010101011", "", "1010101011", 1, 0},
   724  		{"111111111111110001010101000000", "", "111111111111110001011101000000", 20, 1},
   725  		{"010110", "SetBitAtIndex: bit index -1 out of valid range (0..5)", "", -1, 0},
   726  		{"10100110", "SetBitAtIndex: bit index 8 out of valid range (0..7)", "", 8, 0},
   727  		{"", "SetBitAtIndex: bit index 0 out of valid range (0..-1)", "", 0, 0},
   728  	}
   729  	for _, test := range testData {
   730  		t.Run(fmt.Sprintf("{%v,%d,%d}", test.bitString, test.index, test.toSet), func(t *testing.T) {
   731  			ba, err := Parse(test.bitString)
   732  			if err != nil {
   733  				t.Fatal(err)
   734  			}
   735  			res, err := ba.SetBitAtIndex(test.index, test.toSet)
   736  			if test.err != "" && (err == nil || test.err != err.Error()) {
   737  				t.Errorf("expected %q error, but got: %+v", test.err, err)
   738  			} else if test.err == "" && err != nil {
   739  				t.Errorf("unexpected error: %s", err.Error())
   740  			} else if !reflect.DeepEqual(test.res, res.String()) {
   741  				t.Errorf("expected %s, got %s", test.res, res.String())
   742  			}
   743  		})
   744  	}
   745  }