github.com/tunabay/go-bitarray@v1.3.1/bitarray_search_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 "reflect" 9 "strconv" 10 "strings" 11 "testing" 12 13 "github.com/tunabay/go-bitarray" 14 ) 15 16 func TestBitArray_HasPrefix(t *testing.T) { 17 tcs := []struct { 18 b, p string 19 h bool 20 }{ 21 {"", "", true}, 22 {"", "0", false}, 23 {"", "1", false}, 24 {"0", "", true}, 25 {"1", "", true}, 26 {"0", "00", false}, 27 {"1", "11", false}, 28 {"0000-0000 0000", "0000-0000 000", true}, 29 {"0000-0000 0000", "0000-0000 0000", true}, 30 {"0000-0000 0000", "0000-0000 0000-0", false}, 31 {"1111-1111 1111", "1111-1111 111", true}, 32 {"1111-1111 1111", "1111-1111 1111-1", false}, 33 {"0111-1111 1111-1111 1111", "1111", false}, 34 {"1000-0000 0000-0000 0000", "0000", false}, 35 {"1111-0000 0000-0000 0000", "1111", true}, 36 {"0000-1111 1111-1111 1111", "0000", true}, 37 {"0000-0011 1111-1111 1111", "0000-00", true}, 38 {"1111-1100 0000-0000 0000", "1111-11", true}, 39 {"0000-0000 0000-1111 1111", "0000-0001", false}, 40 {"0000-0000 0000-1111 1111", "0000-0000 0000", true}, 41 {"1111-1111 1111-1000 0000", "1111-1111 1111", true}, 42 // TODO: more cases 43 } 44 chk := func(ba, prefix *bitarray.BitArray, want bool) { 45 t.Helper() 46 if got := ba.HasPrefix(prefix); got != want { 47 t.Errorf("unexpected result: got %t, want %t", got, want) 48 t.Logf("target: %#b", ba) 49 t.Logf("prefix: %#b", prefix) 50 } 51 } 52 for _, tc := range tcs { 53 baO := bitarray.MustParse(tc.b).ZOptimize() 54 baE := baO.ZExpand() 55 preO := bitarray.MustParse(tc.p).ZOptimize() 56 preE := preO.ZExpand() 57 chk(baO, preO, tc.h) 58 chk(baO, preE, tc.h) 59 chk(baE, preO, tc.h) 60 chk(baE, preE, tc.h) 61 } 62 63 var nilba *bitarray.BitArray 64 zeroba := bitarray.New() 65 ba := bitarray.MustParse("0101") 66 switch { 67 case !nilba.HasPrefix(nil): // untyped nil 68 t.Error("unexpected result: got false, want true") 69 case !nilba.HasPrefix(nilba): 70 t.Error("unexpected result: got false, want true") 71 case !nilba.HasPrefix(zeroba): 72 t.Error("unexpected result: got false, want true") 73 case !zeroba.HasPrefix(nilba): 74 t.Error("unexpected result: got false, want true") 75 case !ba.HasPrefix(nilba): 76 t.Error("unexpected result: got false, want true") 77 case nilba.HasPrefix(ba): 78 t.Error("unexpected result: got true, want false") 79 } 80 } 81 82 func TestBitArray_HasSuffix(t *testing.T) { 83 tcs := []struct { 84 b, s string 85 h bool 86 }{ 87 {"", "", true}, 88 {"", "0", false}, 89 {"", "1", false}, 90 {"0", "", true}, 91 {"1", "", true}, 92 {"0", "00", false}, 93 {"1", "11", false}, 94 {"0000-0000 0000", "0000-0000 000", true}, 95 {"0000-0000 0000", "0000-0000 0000", true}, 96 {"0000-0000 0000", "0000-0000 0000-0", false}, 97 {"1111-1111 1111", "1111-1111 111", true}, 98 {"1111-1111 1111", "1111-1111 1111-1", false}, 99 {"1111-1111 1111-1111 1110", "1111", false}, 100 {"0000-0000 0000-0000 0001", "0000", false}, 101 {"0000-0000 0000-0000 1111", "1111", true}, 102 {"1111-1111 1111-1111 0000", "0000", true}, 103 {"1111-1111 1111-1100 0000", "0000-00", true}, 104 // TODO: more cases 105 } 106 chk := func(ba, suffix *bitarray.BitArray, want bool) { 107 t.Helper() 108 if got := ba.HasSuffix(suffix); got != want { 109 t.Errorf("unexpected result: got %t, want %t", got, want) 110 t.Logf("target: %#b", ba) 111 t.Logf("suffix: %#b", suffix) 112 } 113 } 114 for _, tc := range tcs { 115 baO := bitarray.MustParse(tc.b).ZOptimize() 116 baE := baO.ZExpand() 117 sufO := bitarray.MustParse(tc.s).ZOptimize() 118 sufE := sufO.ZExpand() 119 chk(baO, sufO, tc.h) 120 chk(baO, sufE, tc.h) 121 chk(baE, sufO, tc.h) 122 chk(baE, sufE, tc.h) 123 } 124 125 var nilba *bitarray.BitArray 126 zeroba := bitarray.New() 127 ba := bitarray.MustParse("0101") 128 switch { 129 case !nilba.HasSuffix(nil): // untyped nil 130 t.Error("unexpected result: got false, want true") 131 case !nilba.HasSuffix(nilba): 132 t.Error("unexpected result: got false, want true") 133 case !nilba.HasSuffix(zeroba): 134 t.Error("unexpected result: got false, want true") 135 case !zeroba.HasSuffix(nilba): 136 t.Error("unexpected result: got false, want true") 137 case !ba.HasSuffix(nilba): 138 t.Error("unexpected result: got false, want true") 139 case nilba.HasSuffix(ba): 140 t.Error("unexpected result: got true, want false") 141 } 142 } 143 144 func TestBitArray_Index(t *testing.T) { 145 tcs := []struct { 146 h, n string 147 i int 148 }{ 149 {"", "", 0}, 150 {"", "0", -1}, 151 {"", "1", -1}, 152 {"0", "", 0}, 153 {"1", "", 0}, 154 {"0", "00", -1}, 155 {"1", "11", -1}, 156 {"0000-0000 0000", "0000-0000 000", 0}, 157 {"0000-0000 0000", "0000-0000 0000", 0}, 158 {"0000-0000 0000", "0000-0000 0000-0", -1}, 159 {"1111-1111 1111", "1111-1111 111", 0}, 160 {"1111-1111 1111", "1111-1111 1111-1", -1}, 161 {"1111-1111 1111-1111 1110", "1111", 0}, 162 {"1000-0000 0000-0000 0001", "0000", 1}, 163 {"0000-1111 0000-0000 1111", "1111", 4}, 164 {"1111-1111 1111-1111 0000", "0000", 16}, 165 {"1111-1111 1111-1100 0000", "0000-00", 14}, 166 // TODO: more cases 167 } 168 chk := func(haystack, needle *bitarray.BitArray, want int) { 169 t.Helper() 170 if got := haystack.Index(needle); got != want { 171 t.Errorf("unexpected result: got %d, want %d", got, want) 172 t.Logf("haystack: %#b", haystack) 173 t.Logf(" needle: %#b", needle) 174 } 175 } 176 for _, tc := range tcs { 177 haystackO := bitarray.MustParse(tc.h).ZOptimize() 178 haystackE := haystackO.ZExpand() 179 needleO := bitarray.MustParse(tc.n).ZOptimize() 180 needleE := needleO.ZExpand() 181 chk(haystackO, needleO, tc.i) 182 chk(haystackO, needleE, tc.i) 183 chk(haystackE, needleO, tc.i) 184 chk(haystackE, needleE, tc.i) 185 } 186 187 var nilba *bitarray.BitArray 188 zeroba := bitarray.New() 189 ba := bitarray.MustParse("0101") 190 if got := nilba.Index(nil); got != 0 { // untyped nil 191 t.Errorf("unexpected result: got %d, want 0", got) 192 } 193 if got := nilba.Index(nilba); got != 0 { 194 t.Errorf("unexpected result: got %d, want 0", got) 195 } 196 if got := nilba.Index(zeroba); got != 0 { 197 t.Errorf("unexpected result: got %d, want 0", got) 198 } 199 if got := zeroba.Index(nilba); got != 0 { 200 t.Errorf("unexpected result: got %d, want 0", got) 201 } 202 if got := ba.Index(nilba); got != 0 { 203 t.Errorf("unexpected result: got %d, want 0", got) 204 } 205 if got := nilba.Index(ba); got != -1 { 206 t.Errorf("unexpected result: got %d, want -1", got) 207 } 208 } 209 210 func TestBitArray_LastIndex(t *testing.T) { 211 tcs := []struct { 212 h, n string 213 i int 214 }{ 215 {"", "", 0}, 216 {"", "0", -1}, 217 {"", "1", -1}, 218 {"0", "", 1}, 219 {"1", "", 1}, 220 {"0", "00", -1}, 221 {"1", "11", -1}, 222 {"0000-0000 0000", "0000-0000 000", 1}, 223 {"0000-0000 0000", "0000-0000 0000", 0}, 224 {"0000-0000 0000", "0000-0000 0000-0", -1}, 225 {"1111-1111 1111", "1111-1111 111", 1}, 226 {"1111-1111 1111", "1111-1111 1111-1", -1}, 227 {"1111-1111 1111-1111 1110", "1111", 15}, 228 {"1000-0000 0000-0000 0001", "0000", 15}, 229 {"0000-1111 0000-0000 1111", "1111", 16}, 230 {"1111-1111 1111-1111 0000", "0000", 16}, 231 {"1111-1111 1111-1100 0000", "0000-00", 14}, 232 // TODO: more cases 233 } 234 chk := func(haystack, needle *bitarray.BitArray, want int) { 235 t.Helper() 236 if got := haystack.LastIndex(needle); got != want { 237 t.Errorf("unexpected result: got %d, want %d", got, want) 238 t.Logf("haystack: %#b", haystack) 239 t.Logf(" needle: %#b", needle) 240 } 241 } 242 for _, tc := range tcs { 243 haystackO := bitarray.MustParse(tc.h).ZOptimize() 244 haystackE := haystackO.ZExpand() 245 needleO := bitarray.MustParse(tc.n).ZOptimize() 246 needleE := needleO.ZExpand() 247 chk(haystackO, needleO, tc.i) 248 chk(haystackO, needleE, tc.i) 249 chk(haystackE, needleO, tc.i) 250 chk(haystackE, needleE, tc.i) 251 } 252 253 var nilba *bitarray.BitArray 254 zeroba := bitarray.New() 255 ba := bitarray.MustParse("0101") 256 if got := nilba.LastIndex(nil); got != 0 { // untyped nil 257 t.Errorf("unexpected result: got %d, want 0", got) 258 } 259 if got := nilba.LastIndex(nilba); got != 0 { 260 t.Errorf("unexpected result: got %d, want 0", got) 261 } 262 if got := nilba.LastIndex(zeroba); got != 0 { 263 t.Errorf("unexpected result: got %d, want 0", got) 264 } 265 if got := zeroba.LastIndex(nilba); got != 0 { 266 t.Errorf("unexpected result: got %d, want 0", got) 267 } 268 if got := ba.LastIndex(nilba); got != 4 { 269 t.Errorf("unexpected result: got %d, want 0", got) 270 } 271 if got := nilba.LastIndex(ba); got != -1 { 272 t.Errorf("unexpected result: got %d, want -1", got) 273 } 274 } 275 276 func TestBitArray_AllIndex(t *testing.T) { 277 tdt := []string{ 278 "", "", "0", 279 "", "0", "", 280 "", "1", "", 281 "0", "", "0,1", 282 "1", "", "0,1", 283 "0", "00", "", 284 "1", "11", "", 285 "1010", "", "0,1,2,3,4", 286 "0000-0000 0000", "0000-0000 000", "0,1", 287 "0000-0000 0000", "0000-0000 0000", "0", 288 "0000-0000 0000", "0000-0000 0000-0", "", 289 "1111-1111 1111", "1111-1111 111", "0,1", 290 "1111-1111 1111", "1111-1111 1111-1", "", 291 "1111-1111 1011-1101 1111", "1111", "0,1,2,3,4,5,10,15,16", 292 "1110-0000 0000-0000 0111", "00000", "3,4,5,6,7,8,9,10,11,12", 293 "0000-1111 0000-0000 1111", "1111", "4,16", 294 "1111-1111 1111-1111 0000", "0000", "16", 295 "1111-1111 1111-1100 0000", "0000-00", "14", 296 // TODO: more cases 297 } 298 chk := func(haystack, needle *bitarray.BitArray, want []int) { 299 t.Helper() 300 if got := haystack.AllIndex(needle); !reflect.DeepEqual(got, want) { 301 t.Error("unexpected result:") 302 t.Logf("haystack: %#b", haystack) 303 t.Logf(" needle: %#b", needle) 304 t.Logf(" got: %v", got) 305 t.Logf(" want: %v", want) 306 } 307 } 308 for i := 0; i < len(tdt); i += 3 { 309 haystackO := bitarray.MustParse(tdt[i]).ZOptimize() 310 haystackE := haystackO.ZExpand() 311 needleO := bitarray.MustParse(tdt[i+1]).ZOptimize() 312 needleE := needleO.ZExpand() 313 wants := strings.Split(tdt[i+2], ",") 314 want := make([]int, 0, len(wants)) 315 for _, ss := range wants { 316 if s := strings.TrimSpace(ss); s != "" { 317 if v, err := strconv.Atoi(s); err == nil { 318 want = append(want, v) 319 } 320 } 321 } 322 chk(haystackO, needleO, want) 323 chk(haystackO, needleE, want) 324 chk(haystackE, needleO, want) 325 chk(haystackE, needleE, want) 326 } 327 328 var nilba *bitarray.BitArray 329 zeroba := bitarray.New() 330 ba := bitarray.MustParse("0101") 331 if got := nilba.AllIndex(nil); !reflect.DeepEqual(got, []int{0}) { // untyped nil 332 t.Errorf("unexpected result: got %v, want [0]", got) 333 } 334 if got := nilba.AllIndex(nilba); !reflect.DeepEqual(got, []int{0}) { 335 t.Errorf("unexpected result: got %v, want [0]", got) 336 } 337 if got := nilba.AllIndex(zeroba); !reflect.DeepEqual(got, []int{0}) { 338 t.Errorf("unexpected result: got %v, want [0]", got) 339 } 340 if got := zeroba.AllIndex(nilba); !reflect.DeepEqual(got, []int{0}) { 341 t.Errorf("unexpected result: got %v, want [0]", got) 342 } 343 if got := ba.AllIndex(nilba); !reflect.DeepEqual(got, []int{0, 1, 2, 3, 4}) { 344 t.Errorf("unexpected result: got %v, want [0 1 2 3 4]", got) 345 } 346 if got := nilba.AllIndex(ba); !reflect.DeepEqual(got, []int{}) { 347 t.Errorf("unexpected result: got %v, want []", got) 348 } 349 }