github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/covering/overlap_merge_test.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package covering 12 13 import ( 14 "bytes" 15 "fmt" 16 "reflect" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 20 ) 21 22 // TODO(dan): Write a simple version of the algorithm that uses the fact that 23 // the endpoints are small integers (e.g. fill out a [100][]string) and 24 // use it to cross-check the results. This could also be used to generate tests 25 // of random inputs. 26 func TestOverlapCoveringMerge(t *testing.T) { 27 defer leaktest.AfterTest(t)() 28 29 tests := []struct { 30 name string 31 // inputs is a slice of coverings. The inner slice represents a covering 32 // as an even number of ints, which are pairwise endpoints. So (1, 2, 2, 33 // 4) means [/1, /2) and [/2, /4). 34 inputs [][]byte 35 // expectedIntervals is the output ranges in the same format as an input 36 // covering. 37 expectedIntervals []byte 38 // expectedPayloads is the output payloads, corresponding 1:1 with 39 // entries in expectedIntervals. Each input range is given an int 40 // payload from 0..N-1 where N is the total number of ranges in all 41 // input coverings for this test. Each of these is formatted as a string 42 // concatenation of these ints. 43 // 44 // So for covering [1, 2), [2, 3) and covering [1, 3), the output 45 // payloads would be "02" for [1, 2) and "12" for [2, 3). 46 expectedPayloads []string 47 }{ 48 {"no input", 49 [][]byte{}, 50 nil, nil, 51 }, 52 {"one empty covering", 53 [][]byte{{}}, 54 nil, nil, 55 }, 56 {"two empty coverings", 57 [][]byte{{}, {}}, 58 nil, nil, 59 }, 60 {"one", 61 [][]byte{{1, 2}, {}}, 62 []byte{1, 2}, []string{"0"}, 63 }, 64 {"same", 65 [][]byte{{1, 2}, {1, 2}}, 66 []byte{1, 2}, []string{"01"}, 67 }, 68 {"overlap", 69 [][]byte{{1, 3}, {2, 3}}, 70 []byte{1, 2, 2, 3}, []string{"0", "01"}}, 71 {"overlap reversed", 72 [][]byte{{2, 3}, {1, 3}}, 73 []byte{1, 2, 2, 3}, []string{"1", "01"}}, 74 {"no overlap", 75 [][]byte{{1, 2, 5, 6}, {3, 4}}, 76 []byte{1, 2, 3, 4, 5, 6}, []string{"0", "2", "1"}, 77 }, 78 {"cockroach range splits and merges", 79 [][]byte{{1, 3, 3, 4}, {1, 4}, {1, 2, 2, 4}}, 80 []byte{1, 2, 2, 3, 3, 4}, []string{"023", "024", "124"}, 81 }, 82 {"godoc example", 83 [][]byte{{1, 2, 3, 4, 6, 7}, {1, 5}}, 84 []byte{1, 2, 2, 3, 3, 4, 4, 5, 6, 7}, []string{"03", "3", "13", "3", "2"}, 85 }, 86 {"empty", 87 [][]byte{{1, 2, 2, 2, 2, 2, 4, 5}, {1, 5}}, 88 []byte{1, 2, 2, 2, 2, 4, 4, 5}, []string{"04", "124", "4", "34"}, 89 }, 90 } 91 92 for _, test := range tests { 93 t.Run(test.name, func(t *testing.T) { 94 var payload int 95 var inputs []Covering 96 for _, endpoints := range test.inputs { 97 var c Covering 98 for i := 0; i < len(endpoints); i += 2 { 99 c = append(c, Range{ 100 Start: []byte{endpoints[i]}, 101 End: []byte{endpoints[i+1]}, 102 Payload: payload, 103 }) 104 payload++ 105 } 106 inputs = append(inputs, c) 107 } 108 var outputIntervals []byte 109 var outputPayloads []string 110 for _, r := range OverlapCoveringMerge(inputs) { 111 outputIntervals = append(outputIntervals, r.Start[0], r.End[0]) 112 var payload bytes.Buffer 113 for _, p := range r.Payload.([]interface{}) { 114 fmt.Fprintf(&payload, "%d", p.(int)) 115 } 116 outputPayloads = append(outputPayloads, payload.String()) 117 } 118 if !reflect.DeepEqual(outputIntervals, test.expectedIntervals) { 119 t.Errorf("intervals got\n%v\nexpected\n%v", outputIntervals, test.expectedIntervals) 120 } 121 if !reflect.DeepEqual(outputPayloads, test.expectedPayloads) { 122 t.Errorf("payloads got\n%v\nexpected\n%v", outputPayloads, test.expectedPayloads) 123 } 124 }) 125 } 126 }