// Copyright 2021 Molecula Corp. All rights reserved. package pilosa_test import ( "fmt" "reflect" "testing" "github.com/molecula/featurebase/v3" ) // Ensure a row can be merged func TestRow_Merge(t *testing.T) { tests := []struct { r1 *pilosa.Row r2 *pilosa.Row exp uint64 }{ { r1: pilosa.NewRow(1, 2, 3, ShardWidth+1, 2*ShardWidth), r2: pilosa.NewRow(3, 4, 5), exp: 7, }, { r1: pilosa.NewRow(), r2: pilosa.NewRow(2, 66000, 70000, 70001, 70002, 70003, 70004), exp: 7, }, } for i, test := range tests { t.Run(fmt.Sprintf("#%d:", i), func(t *testing.T) { test.r1.Merge(test.r2) if cnt := test.r1.Count(); cnt != test.exp { t.Fatalf("merged count %d is not %d", cnt, test.exp) } if length := len(test.r1.Columns()); uint64(length) != test.exp { t.Fatalf("merged length %d is not %d", length, test.exp) } }) } } // Ensure a row can Xor'ed func TestRow_Xor(t *testing.T) { r1 := pilosa.NewRow(0, 1, ShardWidth) r2 := pilosa.NewRow(0, 2*ShardWidth) exp := []uint64{1, ShardWidth, 2 * ShardWidth} res := r1.Xor(r2) if res.Count() != 3 { t.Fatalf("Test 1 Count after xor %d != 3\n", res.Count()) } if !reflect.DeepEqual(res.Columns(), exp) { t.Fatalf("Test 2 Results %v != expected %v\n", res.Columns(), exp) } res = r2.Xor(r1) if res.Count() != 3 { t.Fatalf("Test 3 Count after xor %d != 3\n", res.Count()) } if !reflect.DeepEqual(res.Columns(), exp) { t.Fatalf("Test 4 Results %v != expected %v\n", res.Columns(), exp) } } func TestRow_Union_Segment(t *testing.T) { r1 := pilosa.NewRow(0, 1, ShardWidth) r2 := pilosa.NewRow(0, 2*ShardWidth) exp := []uint64{0, 1, ShardWidth, 2 * ShardWidth} res := r1.Union(r2) if res.Count() != 4 { t.Fatalf("Test 1 Count after Union %d != 5\n", res.Count()) } if !reflect.DeepEqual(res.Columns(), exp) { t.Fatalf("Test 2 Union Results %v != expected %v\n", res.Columns(), exp) } res = r2.Union(r1) if res.Count() != 4 { t.Fatalf("Test 3 Count after xor %d != 5\n", res.Count()) } if !reflect.DeepEqual(res.Columns(), exp) { t.Fatalf("Test 2 Union Results %v != expected %v\n", res.Columns(), exp) } } func TestRow_Difference_Segment(t *testing.T) { r1 := pilosa.NewRow(0, 1, ShardWidth) r2 := pilosa.NewRow(0, 2*ShardWidth) exp := []uint64{1, ShardWidth} res := r1.Difference(r2) if res.Count() != 2 { t.Fatalf("Test 1 Count after Difference %d != 5\n", res.Count()) } if !reflect.DeepEqual(res.Columns(), exp) { t.Fatalf("Test 2 Difference Results %v != expected %v\n", res.Columns(), exp) } } func TestRow_IsEmpty(t *testing.T) { r1 := pilosa.NewRow(1, ShardWidth) r2 := pilosa.NewRow(0, 2*ShardWidth) res := r2.Intersect(r1) if r1.IsEmpty() { t.Fatal("r1 Should Not Be Empty\n") } if !res.IsEmpty() { t.Fatal("Result Should Be Empty\n") } } func TestRow_Includes(t *testing.T) { row := pilosa.NewRow(0, 2*ShardWidth) if !row.Includes(0) { t.Fatal("row should include 0") } if row.Includes(1) { t.Fatal("row should not include 1") } if !row.Includes(2 * ShardWidth) { t.Fatalf("row should include %d", 2*ShardWidth) } } func TestRow_DifferenceInPlace(t *testing.T) { row0 := pilosa.NewRow(0) row1 := pilosa.NewRow() row2 := pilosa.NewRow(0) res := row0.Difference(row1, row2) if !row0.Includes(0) { t.Fatal("row should include 0") } if res.Count() != 0 { t.Fatal("results should be empty") } } func eq(a, b []uint64) bool { if len(a) != len(b) { return false } for i, v := range a { if v != b[i] { return false } } return true } func TestRow_DifferenceInPlace2(t *testing.T) { lucky := []uint64{1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, 87, 93, 99, 105, 111, 115, 127, 129, 133, 135, 141, 151, 159, 163, 169, 171, 189, 193, 195, 201, 205, 211, 219, 223, 231, 235, 237, 241, 259, 261, 267, 273, 283, 285, 289, 297} src := pilosa.NewRow(lucky...) row1 := pilosa.NewRow() m := uint64(9) for i := m; i <= lucky[len(lucky)-1]; i += m { row1.SetBit(i) } m = uint64(3) row2 := pilosa.NewRow() for i := m; i <= lucky[len(lucky)-1]; i += m { row2.SetBit(i) } row3 := pilosa.NewRow() m = uint64(5) for i := m; i <= lucky[len(lucky)-1]; i += m { row3.SetBit(i) } row4 := pilosa.NewRow() m = uint64(7) for i := m; i <= lucky[len(lucky)-1]; i += m { row4.SetBit(i) } res5 := src.Difference(row1, row2, row3, row4) res6 := src.Difference(row4, row3, row2, row1) res7 := src.Difference(row4).Difference(row3).Difference(row2).Difference(row1) if !eq(res5.Columns(), res6.Columns()) { t.Fatalf("results do not match: %v, %v", res5.Columns(), res6.Columns()) } if !eq(res6.Columns(), res7.Columns()) { t.Fatalf("results do not match: %v, %v", res6.Columns(), res7.Columns()) } }