github.com/tunabay/go-bitarray@v1.3.1/bitarray_compare_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  	"fmt"
     9  	"math/rand"
    10  	"sort"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/tunabay/go-bitarray"
    16  )
    17  
    18  func TestBitArray_Equal(t *testing.T) {
    19  	const nillit = "<nil>"
    20  	fail := func(x, y *bitarray.BitArray) {
    21  		t.Helper()
    22  		if t.Failed() {
    23  			t.Logf("x: [%# b]", x)
    24  			t.Logf("y: [%# b]", y)
    25  			t.Logf("x: %s", x.D())
    26  			t.Logf("y: %s", y.D())
    27  			t.FailNow()
    28  		}
    29  	}
    30  	test := func(x, y *bitarray.BitArray, exp bool) {
    31  		t.Helper()
    32  		if x.Equal(y) != exp {
    33  			t.Errorf("unexpected x.Equal(y): got %t, want %t", !exp, exp)
    34  		}
    35  		fail(x, y)
    36  		if x == nil || y == nil {
    37  			return
    38  		}
    39  		xe, ye := x.ZExpand(), y.ZExpand()
    40  		xo, yo := x.ZOptimize(), y.ZOptimize()
    41  		switch {
    42  		case xe.Equal(ye) != exp:
    43  			t.Errorf("unexpected xe.Equal(ye): got %t, want %t", !exp, exp)
    44  		case xe.Equal(yo) != exp:
    45  			t.Errorf("unexpected xe.Equal(yo): got %t, want %t", !exp, exp)
    46  		case xo.Equal(yo) != exp:
    47  			t.Errorf("unexpected xo.Equal(yo): got %t, want %t", !exp, exp)
    48  		}
    49  		fail(x, y)
    50  	}
    51  	ptwo := func(xs, ys string) (x, y *bitarray.BitArray) {
    52  		t.Helper()
    53  		if xs != nillit {
    54  			x = bitarray.MustParse(xs)
    55  		}
    56  		if ys != nillit {
    57  			y = bitarray.MustParse(ys)
    58  		}
    59  		return
    60  	}
    61  	equal := func(xs, ys string) {
    62  		t.Helper()
    63  		x, y := ptwo(xs, ys)
    64  		test(x, y, true)
    65  		test(y, x, true)
    66  	}
    67  	differ := func(xs, ys string) {
    68  		t.Helper()
    69  		x, y := ptwo(xs, ys)
    70  		test(x, y, false)
    71  		test(y, x, false)
    72  	}
    73  
    74  	equal(nillit, nillit)
    75  	equal(nillit, "")
    76  	differ(nillit, "0")
    77  	equal("0", "0")
    78  	equal("00", "00")
    79  	equal("000", "000")
    80  	equal("0000", "0000")
    81  	equal("0000-0", "0000-0")
    82  	equal("0000-00", "0000-00")
    83  	equal("0000-000", "0000-000")
    84  	equal("0000-0000", "0000-0000")
    85  	equal("0000-0000 0", "0000-0000 0")
    86  	equal("0000-0000 0000-0000", "0000-0000 0000-0000")
    87  	equal("0000-0000 0000-0000 0000-000", "0000-0000 0000-0000 0000-000")
    88  	differ("0000-0000 0000-0000 0000-000", "0000-0000 0000-0000 0000-0000")
    89  	differ("0000-0000 0000-0000 0000-0000", "0000-0000 0000-0000 0000-0000 0")
    90  	differ("0", "00")
    91  	differ("0", "000")
    92  	differ("0", "0000")
    93  	differ("0", "0000-0")
    94  	differ("0", "0000-00")
    95  	differ("0", "0000-000")
    96  	differ("0", "0000-0000")
    97  	differ("0", "0000-0000 0")
    98  	differ("0", "0000-0000 00")
    99  	differ("0000-000", "0000-0000")
   100  	differ("0000-0000", "0000-0000 0")
   101  	differ("0000-001", "0000-0010")
   102  	differ("0000-0000 10", "0000-0000 100")
   103  	equal("1", "1")
   104  	differ("1", "0")
   105  	differ("1", "10")
   106  	differ("1", "100")
   107  	differ("1", "1000")
   108  	differ("1", "1000-0000")
   109  	differ("1", "0000-0001")
   110  	differ("1", "0000-0000 1")
   111  	differ("1", "1000-0000 00")
   112  	equal("0000-1111 1111-0000 0000-1111", "0000-1111 1111-0000 0000-1111")
   113  	differ("0000-1111 1111-0000 0000-1111", "0000-1111 1111-0000 0000-1111 0")
   114  	differ("0000-1111 1111-0000 0000-1111 1", "0000-1111 1111-0000 0000-1111 0")
   115  	differ("0000-1111 1111-0000 0000-1111 1", "0000-1111 1011-0000 0000-1111 1")
   116  	differ("0000-1110 1111-0000 0000-1111 1", "0000-1111 1111-0000 0000-1111 1")
   117  }
   118  
   119  func TestBitArray_Compare(t *testing.T) {
   120  	src := []string{
   121  		"",
   122  		"0",
   123  		"00",
   124  		"000",
   125  		"0000",
   126  		"0000-0",
   127  		"0000-00",
   128  		"0000-000",
   129  		"0000-0000",
   130  		"0000-0000 0",
   131  		"0000-0000 00",
   132  		"0000-0000 000",
   133  		"0000-0000 0000",
   134  		"0000-0000 0000-0",
   135  		"0000-0000 0000-00",
   136  		"0000-0000 0000-000",
   137  		"0000-0000 0000-0000",
   138  		"0000-0000 0000-0000 0",
   139  		"0000-0000 0000-0000 00",
   140  		"0000-0001",
   141  		"0000-0001 00",
   142  		"0000-0001 0000-0000 0000-0000",
   143  		"0000-0001 0000-0000 0000-0000 0",
   144  		"0000-0001 0000-0000 0000-0000 1",
   145  		"0000-0001 0000-0000 0000-0001",
   146  		"0000-0001 0000-0000 0000-0001 0",
   147  		"0000-0001 0000-0000 0000-0001 1",
   148  		"0000-0001 0000-0001",
   149  		"0000-0001 01",
   150  		"0000-0001 1",
   151  		"0000-0001 11",
   152  		"0000-0010",
   153  		"0000-0100",
   154  		"0000-1000",
   155  		"0000-1100 0000-0000 0000-0000 0000-0000 0000-000",
   156  		"0000-1100 0000-0000 0000-0000 0000-0000 0000-0000",
   157  		"0000-1100 0000-0000 0000-0000 0000-0000 0000-0000 0",
   158  		"0000-1100 0000-0000 0000-0000 0000-0000 0000-0000 00",
   159  		"0000-1100 0000-0000 0000-0000 0000-0000 0000-0000 0000",
   160  		"0000-1100 0000-0000 0000-0000 0000-0000 0000-0000 0011",
   161  		"0000-1100 0000-0000 0000-0000 0000-0000 0000-0000 01",
   162  		"0000-1100 0000-0000 0000-0000 0100-0000 0000-000",
   163  		"0000-1100 0000-0000 0000-0000 1000-0000 0000-00",
   164  		"0000-1100 0000-0000 0000-0000 1000-0000 0000-000",
   165  		"0000-1101 1111-1110 0000-0000",
   166  		"0000-1101 1111-1110 0000-0000 0",
   167  		"0000-1101 1111-1110 0000-0001",
   168  		"0000-1101 1111-1110 0000-001",
   169  		"0000-1101 1111-1110 0000-01",
   170  		"0000-1101 1111-1110 0000-1",
   171  		"0000-1101 1111-1110 0000-10",
   172  		"0000-1101 1111-1110 0000-100",
   173  		"0000-1101 1111-1110 0000-1000",
   174  		"0000-1101 1111-1110 0000-11",
   175  		"0000-1101 1111-1110 0001",
   176  		"0000-1101 1111-1111 0",
   177  		"0000-1101 1111-1111 00",
   178  		"0000-1101 1111-1111 000",
   179  		"0000-1101 1111-1111 1",
   180  		"0000-1101 1111-1111 11",
   181  		"0000-1101 1111-1111 111",
   182  		"0000-1111",
   183  		"0000-1111 0",
   184  		"0000-1111 00",
   185  		"0000-1111 1",
   186  		"0000-1111 10",
   187  		"0000-1111 11",
   188  		"0000-1111 1100",
   189  		"0000-1111 1100-1100",
   190  		"0000-1111 1100-1100 0",
   191  		"0000-1111 1100-1100 00",
   192  		"0000-1111 1100-1100 01",
   193  		"0000-1111 1100-1100 1",
   194  		"0000-1111 1100-1100 10",
   195  		"0000-1111 1100-1100 11",
   196  		"01",
   197  		"010",
   198  		"0101",
   199  		"0101-0",
   200  		"0101-01",
   201  		"0101-010",
   202  		"0101-0101",
   203  		"0101-0101 0",
   204  		"0101-0101 01",
   205  		"0111",
   206  		"0111-0",
   207  		"0111-00",
   208  		"0111-01",
   209  		"0111-1",
   210  		"0111-10",
   211  		"0111-101",
   212  		"0111-11",
   213  		"0111-1100",
   214  		"0111-1100 0",
   215  		"0111-1101",
   216  		"1",
   217  		"10",
   218  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0",
   219  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-00",
   220  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0000",
   221  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0",
   222  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 00",
   223  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 000",
   224  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 1",
   225  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 10",
   226  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 100",
   227  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 11",
   228  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0001",
   229  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-001",
   230  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-01",
   231  		"1000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-1",
   232  		"11",
   233  		"111",
   234  		"1111",
   235  		"1111-1",
   236  		"1111-11",
   237  		"1111-111",
   238  		"1111-1111",
   239  		"1111-1111 1",
   240  		"1111-1111 11",
   241  		"1111-1111 111",
   242  		"1111-1111 1111",
   243  		"1111-1111 1111-1",
   244  		"1111-1111 1111-11",
   245  		"1111-1111 1111-110",
   246  		"1111-1111 1111-111",
   247  		"1111-1111 1111-1111",
   248  		"1111-1111 1111-1111 1",
   249  		"1111-1111 1111-1111 11",
   250  	}
   251  	dat := make([]*bitarray.BitArray, len(src))
   252  	for i, s := range src {
   253  		if i+1 < len(src) {
   254  			next := src[i+1]
   255  			if next <= s {
   256  				t.Errorf("misordered data samples:")
   257  				t.Logf("#%3d: %q", i, s)
   258  				t.Logf("#%3d: %q", i+1, next)
   259  				t.FailNow()
   260  			}
   261  		}
   262  		dat[i] = bitarray.MustParse(s)
   263  		// t.Logf("data: %s", dat[i].D())
   264  	}
   265  	for i := 0; i < len(dat); i++ {
   266  		x := dat[i]
   267  		xe := x.ZExpand()
   268  		xo := x.ZOptimize()
   269  		for j := 0; j < len(dat); j++ {
   270  			y := dat[j]
   271  			ye := y.ZExpand()
   272  			yo := y.ZOptimize()
   273  			c := bitarray.Compare(x, y)
   274  			switch {
   275  			case i == j && c != 0:
   276  				t.Errorf("unexpected result: got %d, want 0, x == y:", c)
   277  			case i < j && c != -1:
   278  				t.Errorf("unexpected result: got %d, want -1, x < y:", c)
   279  			case j < i && c != +1:
   280  				t.Errorf("unexpected result: got %d, want +1, y < x:", c)
   281  			}
   282  			if ca := bitarray.Compare(xe, ye); ca != c {
   283  				t.Errorf("unexpected result (e,e): got %d, want %d", ca, c)
   284  			}
   285  			if ca := bitarray.Compare(xe, yo); ca != c {
   286  				t.Errorf("unexpected result (e,o): got %d, want %d", ca, c)
   287  			}
   288  			if ca := bitarray.Compare(xo, yo); ca != c {
   289  				t.Errorf("unexpected result (o,o): got %d, want %d", ca, c)
   290  			}
   291  			if t.Failed() {
   292  				t.Logf("x: [%# b]", x)
   293  				t.Logf("y: [%# b]", y)
   294  				t.Logf("x: %s", x.D())
   295  				t.Logf("y: %s", y.D())
   296  				t.FailNow()
   297  			}
   298  			// t.Logf("passed: [%# b] %c [%# b]", x, "<=>"[c+1], y)
   299  		}
   300  	}
   301  }
   302  
   303  func TestBitArray_Compare_rand(t *testing.T) {
   304  	const testIterations = 256
   305  	const listSize = 256
   306  	rand.Seed(time.Now().UnixNano())
   307  	mkdat := func() []*bitarray.BitArray {
   308  		t.Helper()
   309  		src := make([]string, listSize)
   310  		for i := range src {
   311  			n := rand.Intn(256)
   312  			if n == 0 || rand.Intn(64) == 0 {
   313  				continue
   314  			}
   315  			b := make([]byte, (n+7)>>3)
   316  			rand.Read(b)
   317  			s := fmt.Sprintf("%08b", b)
   318  			s = strings.Trim(s, "[]")
   319  			s = strings.ReplaceAll(s, " ", "")
   320  			src[i] = s[:n]
   321  		}
   322  		sort.Strings(src)
   323  		bas := make([]*bitarray.BitArray, 0, listSize)
   324  		for i, s := range src {
   325  			if 0 < i && s == src[i-1] {
   326  				continue
   327  			}
   328  			ba := bitarray.MustParse(s)
   329  			bas = append(bas, ba)
   330  			// t.Logf("dat: %# b", ba)
   331  		}
   332  		return bas
   333  	}
   334  	for i := 0; i < testIterations; i++ {
   335  		dat := mkdat()
   336  		for xi, x := range dat {
   337  			for yi, y := range dat {
   338  				c := bitarray.Compare(x, y)
   339  				switch {
   340  				case xi == yi && c != 0:
   341  					t.Errorf("unexpected result: got %d, want 0, x == y:", c)
   342  				case xi < yi && c != -1:
   343  					t.Errorf("unexpected result: got %d, want -1, x < y:", c)
   344  				case yi < xi && c != +1:
   345  					t.Errorf("unexpected result: got %d, want +1, y < x:", c)
   346  				}
   347  				if t.Failed() {
   348  					t.Logf("x: [%# b]", x)
   349  					t.Logf("y: [%# b]", y)
   350  					t.Logf("x: %s", x.D())
   351  					t.Logf("y: %s", y.D())
   352  					t.FailNow()
   353  				}
   354  				// t.Logf("passed: [%# b] %c [%# b]", x, "<=>"[c+1], y)
   355  			}
   356  		}
   357  	}
   358  }