github.com/tunabay/go-bitarray@v1.3.1/bitarray_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  	"math/rand"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/tunabay/go-bitarray"
    13  )
    14  
    15  func TestBitArray_Slice(t *testing.T) {
    16  	bs := ""
    17  	set := func(s string) {
    18  		t.Helper()
    19  		bs = s
    20  		// t.Logf("data: %q", bs)
    21  	}
    22  	test := func(s, e int, exp string) {
    23  		t.Helper()
    24  		ba := bitarray.MustParse(bs)
    25  		sliced := ba.Slice(s, e)
    26  		sliced.V()
    27  		slicedE := sliced.ZExpand()
    28  		slicedO := sliced.ZOptimize()
    29  		expected := bitarray.MustParse(exp)
    30  		switch {
    31  		case !sliced.Equal(expected):
    32  			t.Errorf("% b: [%d:%d]: unexpected slice:", ba, s, e)
    33  			t.Logf(" got: %#b", sliced)
    34  			t.Logf(" got: %s", sliced.D())
    35  		case !slicedE.Equal(expected):
    36  			t.Errorf("% b: [%d:%d]: unexpected slice (e):", ba, s, e)
    37  			t.Logf(" got: %#b", slicedE)
    38  			t.Logf(" got: %s", slicedE.D())
    39  		case !slicedO.Equal(expected):
    40  			t.Errorf("% b: [%d:%d]: unexpected slice (o):", ba, s, e)
    41  			t.Logf(" got: %#b", slicedO)
    42  			t.Logf(" got: %s", slicedO.D())
    43  		}
    44  		if t.Failed() {
    45  			t.Logf("want: %#b", expected)
    46  			t.FailNow()
    47  		}
    48  		// t.Logf("pass: [%d:%d]: % b", s, e, sliced)
    49  	}
    50  	testPanic := func(s, e int) {
    51  		t.Helper()
    52  		ba := bitarray.MustParse(bs)
    53  		var rba *bitarray.BitArray
    54  		defer func() {
    55  			if recover() == nil {
    56  				t.Errorf("panic expected:")
    57  				t.Logf(" got: %#b", rba)
    58  				t.Logf(" got: %s", rba.D())
    59  			}
    60  		}()
    61  		rba = ba.Slice(s, e)
    62  	}
    63  
    64  	set("")
    65  	test(0, 0, "")
    66  	testPanic(0, 1)
    67  
    68  	set("1111-11")
    69  	test(0, 0, "")
    70  	test(4, 4, "")
    71  	test(0, 3, "111")
    72  	test(0, 6, "1111-11")
    73  	testPanic(-1, 1)
    74  	testPanic(1, 0)
    75  	testPanic(5, 0)
    76  	testPanic(5, 3)
    77  	testPanic(99, 3)
    78  	testPanic(0, -1)
    79  
    80  	set("1111-0000 1010-0101 1100-11")
    81  	test(0, 0, "")
    82  	test(0, 1, "1")
    83  	test(1, 3, "11")
    84  	test(0, 3, "111")
    85  	test(0, 8, "1111-0000")
    86  	test(2, 8, "11-0000")
    87  	test(3, 11, "1-0000 101")
    88  	test(9, 15, "010-010")
    89  	test(0, 22, "1111-0000 1010-0101 1100-11")
    90  	test(18, 22, "0011")
    91  	test(21, 22, "1")
    92  
    93  	set("0000-0000 0000-0000 0000-0000 0000-0000")
    94  	test(0, 0, "")
    95  	test(0, 1, "0")
    96  	test(0, 7, "0000-000")
    97  	test(0, 8, "0000-0000")
    98  	test(0, 9, "0000-0000 0")
    99  	test(0, 15, "0000-0000 0000-000")
   100  	test(0, 16, "0000-0000 0000-0000")
   101  	test(0, 17, "0000-0000 0000-0000 0")
   102  	test(6, 15, "00 0000-000")
   103  	test(6, 16, "00 0000-0000")
   104  	test(6, 17, "00 0000-0000 0")
   105  	test(0, 31, "0000-0000 0000-0000 0000-0000 0000-000")
   106  	test(0, 32, "0000-0000 0000-0000 0000-0000 0000-0000")
   107  	test(15, 31, "0 0000-0000 0000-000")
   108  	test(15, 32, "0 0000-0000 0000-0000")
   109  	test(16, 31, "0000-0000 0000-000")
   110  	test(16, 32, "0000-0000 0000-0000")
   111  	test(19, 31, "0-0000 0000-000")
   112  	test(19, 32, "0-0000 0000-0000")
   113  	test(24, 31, "0000-000")
   114  	test(24, 32, "0000-0000")
   115  	test(27, 31, "0-000")
   116  	test(27, 32, "0-0000")
   117  
   118  	set("0000-0000 0")
   119  	test(0, 9, "0000-0000 0")
   120  	testPanic(0, 10)
   121  	testPanic(9, 10)
   122  
   123  	set("1010-0101 1010-0101 1010-0101 1010-0101")
   124  	test(0, 0, "")
   125  	test(0, 1, "1")
   126  	test(3, 6, "0-01")
   127  	test(7, 8, "1")
   128  	test(8, 9, "1")
   129  	test(0, 7, "1010-010")
   130  	test(0, 8, "1010-0101")
   131  	test(0, 9, "1010-0101 1")
   132  	test(0, 15, "1010-0101 1010-010")
   133  	test(0, 16, "1010-0101 1010-0101")
   134  	test(0, 17, "1010-0101 1010-0101 1")
   135  	test(6, 15, "01 1010-010")
   136  	test(6, 16, "01 1010-0101")
   137  	test(6, 17, "01 1010-0101 1")
   138  	test(10, 14, "10-01")
   139  	test(0, 31, "1010-0101 1010-0101 1010-0101 1010-010")
   140  	test(0, 32, "1010-0101 1010-0101 1010-0101 1010-0101")
   141  	test(15, 31, "1 1010-0101 1010-010")
   142  	test(15, 32, "1 1010-0101 1010-0101")
   143  	test(16, 31, "1010-0101 1010-010")
   144  	test(16, 32, "1010-0101 1010-0101")
   145  	test(19, 31, "0-0101 1010-010")
   146  	test(19, 32, "0-0101 1010-0101")
   147  	test(24, 31, "1010-010")
   148  	test(24, 32, "1010-0101")
   149  	test(26, 29, "10-0")
   150  	test(27, 31, "0-010")
   151  	test(27, 32, "0-0101")
   152  
   153  	set("1110-0011 1000-1110 0011-1000 1110-0011 1000")
   154  	test(0, 0, "")
   155  	test(0, 1, "1")
   156  	test(2, 6, "10-00")
   157  	test(6, 8, "11")
   158  	test(8, 10, "10")
   159  	test(0, 7, "1110-001")
   160  	test(0, 8, "1110-0011")
   161  	test(0, 9, "1110-0011 1")
   162  	test(0, 15, "1110-0011 1000-111")
   163  	test(0, 16, "1110-0011 1000-1110")
   164  	test(0, 17, "1110-0011 1000-1110 0")
   165  	test(5, 15, "011 1000-111")
   166  	test(5, 16, "011 1000-1110")
   167  	test(5, 17, "011 1000-1110 0")
   168  	test(10, 14, "00-11")
   169  	test(0, 31, "1110-0011 1000-1110 0011-1000 1110-001")
   170  	test(0, 32, "1110-0011 1000-1110 0011-1000 1110-0011")
   171  	test(0, 33, "1110-0011 1000-1110 0011-1000 1110-0011 1")
   172  	test(0, 34, "1110-0011 1000-1110 0011-1000 1110-0011 10")
   173  	test(0, 35, "1110-0011 1000-1110 0011-1000 1110-0011 100")
   174  	test(0, 36, "1110-0011 1000-1110 0011-1000 1110-0011 1000")
   175  	test(14, 31, "10 0011-1000 1110-001")
   176  	test(14, 32, "10 0011-1000 1110-0011")
   177  	test(14, 33, "10 0011-1000 1110-0011 1")
   178  	test(14, 34, "10 0011-1000 1110-0011 10")
   179  	test(14, 35, "10 0011-1000 1110-0011 100")
   180  	test(14, 36, "10 0011-1000 1110-0011 1000")
   181  	test(16, 31, "0011-1000 1110-001")
   182  	test(16, 32, "0011-1000 1110-0011")
   183  	test(16, 33, "0011-1000 1110-0011 1")
   184  	test(16, 36, "0011-1000 1110-0011 1000")
   185  	test(19, 31, "1-1000 1110-001")
   186  	test(19, 32, "1-1000 1110-0011")
   187  	test(19, 33, "1-1000 1110-0011 1")
   188  	test(19, 36, "1-1000 1110-0011 1000")
   189  	test(24, 31, "1110-001")
   190  	test(24, 32, "1110-0011")
   191  	test(25, 31, "110-001")
   192  	test(26, 29, "10-0")
   193  	test(27, 31, "0-001")
   194  	test(27, 32, "0-0011")
   195  }
   196  
   197  func TestBitArray_Slice_rand(t *testing.T) {
   198  	const testIterations = 50000
   199  	rand.Seed(time.Now().UnixNano())
   200  
   201  	n := 0
   202  	for i := 0; i < testIterations/1000; i++ {
   203  		ba := bitarray.PseudoRand(0x100, nil) // random 256 bits
   204  		srcStr := ba.String()
   205  		for j := 0; j < 1000 && n < testIterations; j++ {
   206  			ss := rand.Intn(0x101)      // 0 .. 256
   207  			sl := rand.Intn(0x101 - ss) // 0 .. 256-ss
   208  			se := ss + sl               // ss .. 256
   209  
   210  			expected := bitarray.MustParse(srcStr[ss:se])
   211  			sliced := ba.Slice(ss, se)
   212  			sliced.V()
   213  			slicedE := sliced.ZExpand()
   214  			slicedO := sliced.ZOptimize()
   215  			if !sliced.Equal(expected) || !slicedE.Equal(expected) || !slicedO.Equal(expected) {
   216  				t.Errorf("unxepected slice of [%d:%d] len=%d:", ss, se, se-ss)
   217  				t.Logf(" all: % s", ba)
   218  				t.Logf("want: % s", expected)
   219  				t.Logf("want: %s", expected.D())
   220  				t.Logf(" got: % s", sliced)
   221  				t.Logf(" got: %s", sliced.D())
   222  				t.FailNow()
   223  			}
   224  			if i == 0 && j < 32 {
   225  				// t.Logf("pass: [%d:%d] % s", ss, se, sliced)
   226  			}
   227  			n++
   228  		}
   229  	}
   230  }
   231  
   232  func TestBitArray_ToWidth(t *testing.T) {
   233  	tcs := []struct {
   234  		w       int
   235  		s, l, r string
   236  	}{
   237  		{0, "0000-0000", "", ""},
   238  		{0, "1111-1111", "", ""},
   239  		{12, "1111-1111 1100", "1111-1111 1100", "1111-1111 1100"},
   240  		{1, "1010-1010", "1", "0"},
   241  		{5, "0000-000", "00000", "00000"},
   242  		{4, "1100-0001", "1100", "0001"},
   243  		// TODO: more
   244  	}
   245  	chk := func(got, want *bitarray.BitArray) {
   246  		t.Helper()
   247  		got.V()
   248  		if !got.Equal(want) {
   249  			t.Error("unexpected result:")
   250  			t.Logf(" got: %#b", got)
   251  			t.Logf(" got: %s", got.D())
   252  			t.Logf("want: %#b", want)
   253  			t.FailNow()
   254  		}
   255  	}
   256  	for _, tc := range tcs {
   257  		expL := bitarray.MustParse(tc.l).ZOptimize()
   258  		expR := bitarray.MustParse(tc.r).ZOptimize()
   259  		ba := bitarray.MustParse(tc.s)
   260  		baE := ba.ZExpand()
   261  
   262  		chk(ba.ToWidth(tc.w, bitarray.AlignLeft), expL)
   263  		chk(baE.ToWidth(tc.w, bitarray.AlignLeft), expL)
   264  		chk(ba.ToWidth(tc.w, bitarray.AlignRight), expR)
   265  		chk(baE.ToWidth(tc.w, bitarray.AlignRight), expR)
   266  	}
   267  	func() {
   268  		var ba *bitarray.BitArray
   269  		defer func() {
   270  			if recover() == nil {
   271  				t.Errorf("panic expected: got %#b", ba)
   272  			}
   273  		}()
   274  		ba = bitarray.MustParse("10101").ToWidth(-1, bitarray.AlignLeft)
   275  	}()
   276  }
   277  
   278  func TestBitArray_TrimPrefix(t *testing.T) {
   279  	tdt := []string{
   280  		"", "", "",
   281  		"", "0011", "",
   282  		"", "1", "",
   283  		"0", "", "0",
   284  		"0", "0", "",
   285  		"0", "1", "0",
   286  		"1", "", "1",
   287  		"1", "0", "1",
   288  		"1", "1", "",
   289  		"0000-0000 0000-0000", "", "0000-0000 0000-0000",
   290  		"0000-0000 0000-0000", "0", "0000-0000 0000-000",
   291  		"0000-0000 0000-0000", "0000", "0000-0000 0000",
   292  		"0000-0000 0000-0000", "0001", "0000-0000 0000-0000",
   293  		"1111-1111 0000-0011", "0000", "1111-1111 0000-0011",
   294  		"1111-1111 0000-0011", "111", "1111-1000 0001-1",
   295  		"1111-1111 0000-0011", "1111-1111 00", "0000-11",
   296  		"0101-1111 0101-1111 0101-11", "01", "0111-1101 0111-1101 0111",
   297  	}
   298  	chk := func(got, want *bitarray.BitArray) {
   299  		t.Helper()
   300  		got.V()
   301  		if !got.Equal(want) {
   302  			t.Error("unexpected result:")
   303  			t.Logf(" got: %#b", got)
   304  			t.Logf(" got: %s", got.D())
   305  			t.Logf("want: %#b", want)
   306  			t.FailNow()
   307  		}
   308  	}
   309  	for i := 0; i < len(tdt); i += 3 {
   310  		ba0 := bitarray.MustParse(tdt[i]).ZOptimize()
   311  		ba1 := bitarray.MustParse(tdt[i+1]).ZOptimize()
   312  		exp := bitarray.MustParse(tdt[i+2])
   313  		ba0E := ba0.ZExpand()
   314  		ba1E := ba1.ZExpand()
   315  
   316  		chk(ba0.TrimPrefix(ba1), exp)
   317  		chk(ba0.TrimPrefix(ba1E), exp)
   318  		chk(ba0E.TrimPrefix(ba1), exp)
   319  		chk(ba0E.TrimPrefix(ba1E), exp)
   320  	}
   321  }
   322  
   323  func TestBitArray_TrimSuffix(t *testing.T) {
   324  	tdt := []string{
   325  		"", "", "",
   326  		"", "0011", "",
   327  		"", "1", "",
   328  		"0", "", "0",
   329  		"0", "0", "",
   330  		"0", "1", "0",
   331  		"1", "", "1",
   332  		"1", "0", "1",
   333  		"1", "1", "",
   334  		"0000-0000 0000-0000", "", "0000-0000 0000-0000",
   335  		"0000-0000 0000-0000", "0", "0000-0000 0000-000",
   336  		"0000-0000 0000-0000", "0000", "0000-0000 0000",
   337  		"0000-0000 0000-0000", "0001", "0000-0000 0000-0000",
   338  		"1111-1111 0000-0011", "0000", "1111-1111 0000-0011",
   339  		"1111-1111 0000-0011", "011", "1111-1111 0000-0",
   340  		"1111-1111 0000-0011", "1111 0000-0011", "1111",
   341  		"0101-1111 0101-1111 0101-11", "0111", "0101-1111 0101-1111 01",
   342  	}
   343  	chk := func(got, want *bitarray.BitArray) {
   344  		t.Helper()
   345  		got.V()
   346  		if !got.Equal(want) {
   347  			t.Error("unexpected result:")
   348  			t.Logf(" got: %#b", got)
   349  			t.Logf(" got: %s", got.D())
   350  			t.Logf("want: %#b", want)
   351  			t.FailNow()
   352  		}
   353  	}
   354  	for i := 0; i < len(tdt); i += 3 {
   355  		ba0 := bitarray.MustParse(tdt[i]).ZOptimize()
   356  		ba1 := bitarray.MustParse(tdt[i+1]).ZOptimize()
   357  		exp := bitarray.MustParse(tdt[i+2])
   358  		ba0E := ba0.ZExpand()
   359  		ba1E := ba1.ZExpand()
   360  		chk(ba0.TrimSuffix(ba1), exp)
   361  		chk(ba0.TrimSuffix(ba1E), exp)
   362  		chk(ba0E.TrimSuffix(ba1), exp)
   363  		chk(ba0E.TrimSuffix(ba1E), exp)
   364  	}
   365  }
   366  
   367  func TestBitArray_TrimLeadingZeros(t *testing.T) {
   368  	tdt := []string{
   369  		"", "",
   370  		"0", "",
   371  		"1", "1",
   372  		"1100", "1100",
   373  		"0011", "11",
   374  		"0000-0000", "",
   375  		"0000-1010", "1010",
   376  		"0000-0000 0000", "",
   377  		"0000-0000 1010", "1010",
   378  		"0000-0000 0000-1010", "1010",
   379  		"0000-0000 0000-0001 010", "1010",
   380  		"0000-0000 0000-0000 0010-10", "1010",
   381  		"0000-0000 0000-0000 0000-0101 0", "1010",
   382  		"0x_0000_0000 0x_0000_0000 0x_0000 0b_0011_11", "1111",
   383  	}
   384  	chk := func(got, want *bitarray.BitArray) {
   385  		t.Helper()
   386  		got.V()
   387  		if !got.Equal(want) {
   388  			t.Error("unexpected result:")
   389  			t.Logf(" got: %#b", got)
   390  			t.Logf(" got: %s", got.D())
   391  			t.Logf("want: %#b", want)
   392  			t.FailNow()
   393  		}
   394  	}
   395  	for i := 0; i < len(tdt); i += 2 {
   396  		ba0 := bitarray.MustParse(tdt[i]).ZOptimize()
   397  		exp := bitarray.MustParse(tdt[i+1])
   398  		ba0E := ba0.ZExpand()
   399  		chk(ba0.TrimLeadingZeros(), exp)
   400  		chk(ba0E.TrimLeadingZeros(), exp)
   401  	}
   402  }
   403  
   404  func TestBitArray_TrimTrailingZeros(t *testing.T) {
   405  	tdt := []string{
   406  		"", "",
   407  		"0", "",
   408  		"1", "1",
   409  		"1100", "11",
   410  		"0011", "0011",
   411  		"0000-0000", "",
   412  		"0000-1010", "0000-101",
   413  		"0000-0101", "0000-0101",
   414  		"1010-0000", "101",
   415  		"0000-0000 0000", "",
   416  		"0101-0000 0000", "0101",
   417  		"0000-0000 0101", "0000-0000 0101",
   418  		"0101-0000 0000-0000", "0101",
   419  		"0101-0000 0000-0000 000", "0101",
   420  		"0101-0000 0000-0000 0000-00", "0101",
   421  		"0101-0000 0000-0000 0000-0000 0", "0101",
   422  		"0101-0000 0000-0000 0000-0001 0", "0101-0000 0000-0000 0000-0001",
   423  		"1111 0x_0000_0000 0x_0000_0000 0x_0000 0", "1111",
   424  	}
   425  	chk := func(got, want *bitarray.BitArray) {
   426  		t.Helper()
   427  		got.V()
   428  		if !got.Equal(want) {
   429  			t.Error("unexpected result:")
   430  			t.Logf(" got: %#b", got)
   431  			t.Logf(" got: %s", got.D())
   432  			t.Logf("want: %#b", want)
   433  			t.FailNow()
   434  		}
   435  	}
   436  	for i := 0; i < len(tdt); i += 2 {
   437  		ba0 := bitarray.MustParse(tdt[i]).ZOptimize()
   438  		exp := bitarray.MustParse(tdt[i+1])
   439  		ba0E := ba0.ZExpand()
   440  		chk(ba0.TrimTrailingZeros(), exp)
   441  		chk(ba0E.TrimTrailingZeros(), exp)
   442  	}
   443  }