// Copyright 2022 Molecula Corp. (DBA FeatureBase). // SPDX-License-Identifier: Apache-2.0 package ingest import ( "math/rand" "testing" "github.com/featurebasedb/featurebase/v3/shardwidth" ) type opShardingTestCase struct { name string input *Request output *ShardedRequest } var opShardingTestCases = []opShardingTestCase{ { name: "sample", input: &Request{ Ops: []*Operation{ { OpType: OpSet, FieldOps: map[string]*FieldOperation{ "shard0": { RecordIDs: []uint64{0, 1}, }, "shard0-1": { RecordIDs: []uint64{ 0, 1 << shardwidth.Exponent, }, }, "shard1": { RecordIDs: []uint64{ 1 << shardwidth.Exponent, 1< 1 { valuesPerRecord-- } } } } op.FieldOps["set"] = &FieldOperation{ RecordIDs: recordIDs, Values: values, } fieldTypes := codec.FieldTypes() sharded, err := req.ByShard(fieldTypes) if err != nil { t.Errorf("sharding: unexpected error %v", err) } merged := sharded.merge() if err := req.Compare(merged); err != nil { t.Fatalf("merge comparison: %v", err) } } func TestFancySharding(t *testing.T) { const shardLimit = 700 const recordCount = 5000 grr := rand.New(rand.NewSource(0)) for i := 0; i < 100; i++ { f := &FieldOperation{RecordIDs: make([]uint64, recordCount), Values: make([]uint64, recordCount)} shards := make([]int, shardLimit) for j := range f.RecordIDs { v := uint64(grr.Int63n(shardLimit << shardwidth.Exponent)) f.RecordIDs[j] = v f.Values[j] = uint64(grr.Int63n(8)) shards[v>>shardwidth.Exponent]++ } sharded := f.SortToShards() for shard, data := range sharded { if len(data.RecordIDs) != shards[shard] { t.Errorf("shard %d: expected %d items, got %d", shard, shards[shard], len(data.RecordIDs)) } for _, v := range data.RecordIDs { if (v >> shardwidth.Exponent) != shard { t.Errorf("shard %d: got %x, which should be in %d", shard, v, v>>shardwidth.Exponent) } } // expect sorted-ness data.SortByRecords() prev := data.RecordIDs[0] for i, next := range data.RecordIDs[1:] { if next < prev { t.Errorf("index %d: prev %d, next %d", i+1, prev, next) } prev = next } data.SortByValues() prevV, prevRec := data.Values[0], data.RecordIDs[0] for i, nextRec := range data.RecordIDs[1:] { nextV := data.Values[i+1] if nextV < prevV { t.Errorf("index %d: prev value %d, next value %d", i+1, prevV, nextV) } if nextV == prevV { if nextRec < prevRec { t.Errorf("index %d, value %d: prev rec %d, next rec %d", i+1, nextV, prevRec, nextRec) } } prevV = nextV prevRec = nextRec } } } }