github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/span/frontier_test.go (about) 1 // Copyright 2018 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 span 12 13 import ( 14 "container/heap" 15 "fmt" 16 "strings" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/roachpb" 20 "github.com/cockroachdb/cockroach/pkg/util/hlc" 21 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 22 "github.com/stretchr/testify/require" 23 ) 24 25 func (f *Frontier) entriesStr() string { 26 var buf strings.Builder 27 f.Entries(func(sp roachpb.Span, ts hlc.Timestamp) { 28 if buf.Len() != 0 { 29 buf.WriteString(` `) 30 } 31 fmt.Fprintf(&buf, `%s@%d`, sp, ts.WallTime) 32 }) 33 return buf.String() 34 } 35 36 func TestSpanFrontier(t *testing.T) { 37 defer leaktest.AfterTest(t)() 38 39 keyA, keyB := roachpb.Key("a"), roachpb.Key("b") 40 keyC, keyD := roachpb.Key("c"), roachpb.Key("d") 41 42 spAB := roachpb.Span{Key: keyA, EndKey: keyB} 43 spAC := roachpb.Span{Key: keyA, EndKey: keyC} 44 spAD := roachpb.Span{Key: keyA, EndKey: keyD} 45 spBC := roachpb.Span{Key: keyB, EndKey: keyC} 46 spBD := roachpb.Span{Key: keyB, EndKey: keyD} 47 spCD := roachpb.Span{Key: keyC, EndKey: keyD} 48 49 f := MakeFrontier(spAD) 50 require.Equal(t, hlc.Timestamp{}, f.Frontier()) 51 require.Equal(t, `{a-d}@0`, f.entriesStr()) 52 53 // Untracked spans are ignored 54 adv := f.Forward( 55 roachpb.Span{Key: []byte("d"), EndKey: []byte("e")}, 56 hlc.Timestamp{WallTime: 1}, 57 ) 58 require.Equal(t, false, adv) 59 require.Equal(t, hlc.Timestamp{}, f.Frontier()) 60 require.Equal(t, `{a-d}@0`, f.entriesStr()) 61 62 // Forward the entire tracked spanspace. 63 adv = f.Forward(spAD, hlc.Timestamp{WallTime: 1}) 64 require.Equal(t, true, adv) 65 require.Equal(t, hlc.Timestamp{WallTime: 1}, f.Frontier()) 66 require.Equal(t, `{a-d}@1`, f.entriesStr()) 67 68 // Forward it again. 69 adv = f.Forward(spAD, hlc.Timestamp{WallTime: 2}) 70 require.Equal(t, true, adv) 71 require.Equal(t, hlc.Timestamp{WallTime: 2}, f.Frontier()) 72 require.Equal(t, `{a-d}@2`, f.entriesStr()) 73 74 // Forward to the previous frontier. 75 adv = f.Forward(spAD, hlc.Timestamp{WallTime: 2}) 76 require.Equal(t, false, adv) 77 require.Equal(t, hlc.Timestamp{WallTime: 2}, f.Frontier()) 78 require.Equal(t, `{a-d}@2`, f.entriesStr()) 79 80 // Forward into the past is ignored. 81 adv = f.Forward(spAD, hlc.Timestamp{WallTime: 1}) 82 require.Equal(t, false, adv) 83 require.Equal(t, hlc.Timestamp{WallTime: 2}, f.Frontier()) 84 require.Equal(t, `{a-d}@2`, f.entriesStr()) 85 86 // Forward a subset. 87 adv = f.Forward(spBC, hlc.Timestamp{WallTime: 3}) 88 require.Equal(t, false, adv) 89 require.Equal(t, hlc.Timestamp{WallTime: 2}, f.Frontier()) 90 require.Equal(t, `{a-b}@2 {b-c}@3 {c-d}@2`, f.entriesStr()) 91 92 // Forward it more. 93 adv = f.Forward(spBC, hlc.Timestamp{WallTime: 4}) 94 require.Equal(t, false, adv) 95 require.Equal(t, hlc.Timestamp{WallTime: 2}, f.Frontier()) 96 require.Equal(t, `{a-b}@2 {b-c}@4 {c-d}@2`, f.entriesStr()) 97 98 // Forward all tracked spans to timestamp before BC (currently at 4). 99 // Advances to the min of tracked spans. Note that this requires the 100 // forwarded span to be split into two spans, one on each side of BC. 101 adv = f.Forward(spAD, hlc.Timestamp{WallTime: 3}) 102 require.Equal(t, true, adv) 103 require.Equal(t, hlc.Timestamp{WallTime: 3}, f.Frontier()) 104 require.Equal(t, `{a-b}@3 {b-c}@4 {c-d}@3`, f.entriesStr()) 105 106 // Forward everything but BC, advances to the min of tracked spans. 107 adv = f.Forward(spAB, hlc.Timestamp{WallTime: 5}) 108 require.Equal(t, false, adv) 109 require.Equal(t, hlc.Timestamp{WallTime: 3}, f.Frontier()) 110 adv = f.Forward(spCD, hlc.Timestamp{WallTime: 5}) 111 require.Equal(t, true, adv) 112 require.Equal(t, hlc.Timestamp{WallTime: 4}, f.Frontier()) 113 require.Equal(t, `{a-b}@5 {b-c}@4 {c-d}@5`, f.entriesStr()) 114 115 // Catch BC up. 116 adv = f.Forward(spBC, hlc.Timestamp{WallTime: 5}) 117 require.Equal(t, true, adv) 118 require.Equal(t, hlc.Timestamp{WallTime: 5}, f.Frontier()) 119 require.Equal(t, `{a-b}@5 {b-c}@5 {c-d}@5`, f.entriesStr()) 120 121 // Forward them all at once (spans don't collapse for now, this is a TODO). 122 adv = f.Forward(spAD, hlc.Timestamp{WallTime: 6}) 123 require.Equal(t, true, adv) 124 require.Equal(t, hlc.Timestamp{WallTime: 6}, f.Frontier()) 125 require.Equal(t, `{a-b}@6 {b-c}@6 {c-d}@6`, f.entriesStr()) 126 127 // Split AC with BD. 128 adv = f.Forward(spCD, hlc.Timestamp{WallTime: 7}) 129 require.Equal(t, false, adv) 130 require.Equal(t, hlc.Timestamp{WallTime: 6}, f.Frontier()) 131 require.Equal(t, `{a-b}@6 {b-c}@6 {c-d}@7`, f.entriesStr()) 132 adv = f.Forward(spBD, hlc.Timestamp{WallTime: 8}) 133 require.Equal(t, false, adv) 134 require.Equal(t, hlc.Timestamp{WallTime: 6}, f.Frontier()) 135 require.Equal(t, `{a-b}@6 {b-c}@8 {c-d}@8`, f.entriesStr()) 136 adv = f.Forward(spAB, hlc.Timestamp{WallTime: 8}) 137 require.Equal(t, true, adv) 138 require.Equal(t, hlc.Timestamp{WallTime: 8}, f.Frontier()) 139 require.Equal(t, `{a-b}@8 {b-c}@8 {c-d}@8`, f.entriesStr()) 140 141 // Split BD with AC. 142 adv = f.Forward(spAC, hlc.Timestamp{WallTime: 9}) 143 require.Equal(t, false, adv) 144 require.Equal(t, hlc.Timestamp{WallTime: 8}, f.Frontier()) 145 require.Equal(t, `{a-b}@9 {b-c}@9 {c-d}@8`, f.entriesStr()) 146 adv = f.Forward(spCD, hlc.Timestamp{WallTime: 9}) 147 require.Equal(t, true, adv) 148 require.Equal(t, hlc.Timestamp{WallTime: 9}, f.Frontier()) 149 require.Equal(t, `{a-b}@9 {b-c}@9 {c-d}@9`, f.entriesStr()) 150 } 151 152 func TestSpanFrontierDisjointSpans(t *testing.T) { 153 defer leaktest.AfterTest(t)() 154 keyA, keyB, keyC := roachpb.Key("a"), roachpb.Key("b"), roachpb.Key("c") 155 keyD, keyE, keyF := roachpb.Key("d"), roachpb.Key("e"), roachpb.Key("f") 156 spAB := roachpb.Span{Key: keyA, EndKey: keyB} 157 spAD := roachpb.Span{Key: keyA, EndKey: keyD} 158 spCE := roachpb.Span{Key: keyC, EndKey: keyE} 159 spDF := roachpb.Span{Key: keyD, EndKey: keyF} 160 161 f := MakeFrontier(spAB, spCE) 162 require.Equal(t, hlc.Timestamp{}, f.Frontier()) 163 require.Equal(t, `{a-b}@0 {c-e}@0`, f.entriesStr()) 164 165 // Advance just the tracked spans 166 adv := f.Forward(spCE, hlc.Timestamp{WallTime: 1}) 167 require.Equal(t, false, adv) 168 require.Equal(t, hlc.Timestamp{}, f.Frontier()) 169 require.Equal(t, `{a-b}@0 {c-e}@1`, f.entriesStr()) 170 adv = f.Forward(spAB, hlc.Timestamp{WallTime: 1}) 171 require.Equal(t, true, adv) 172 require.Equal(t, hlc.Timestamp{WallTime: 1}, f.Frontier()) 173 require.Equal(t, `{a-b}@1 {c-e}@1`, f.entriesStr()) 174 175 // Advance a span that partially overlaps the tracked spans 176 adv = f.Forward(spDF, hlc.Timestamp{WallTime: 2}) 177 require.Equal(t, false, adv) 178 require.Equal(t, hlc.Timestamp{WallTime: 1}, f.Frontier()) 179 require.Equal(t, `{a-b}@1 {c-d}@1 {d-e}@2`, f.entriesStr()) 180 181 // Advance one span that covers two tracked spans and so needs two entries. 182 adv = f.Forward(spAD, hlc.Timestamp{WallTime: 3}) 183 require.Equal(t, true, adv) 184 require.Equal(t, hlc.Timestamp{WallTime: 2}, f.Frontier()) 185 require.Equal(t, `{a-b}@3 {c-d}@3 {d-e}@2`, f.entriesStr()) 186 } 187 188 func TestSpanFrontierHeap(t *testing.T) { 189 defer leaktest.AfterTest(t)() 190 191 keyA, keyB, keyC := roachpb.Key("a"), roachpb.Key("b"), roachpb.Key("c") 192 spAB := roachpb.Span{Key: keyA, EndKey: keyB} 193 spBC := roachpb.Span{Key: keyB, EndKey: keyC} 194 195 var fh frontierHeap 196 197 eAB1 := &frontierEntry{span: spAB, ts: hlc.Timestamp{WallTime: 1}} 198 eBC1 := &frontierEntry{span: spBC, ts: hlc.Timestamp{WallTime: 1}} 199 eAB2 := &frontierEntry{span: spAB, ts: hlc.Timestamp{WallTime: 2}} 200 201 // Push one 202 heap.Push(&fh, eAB1) 203 require.Equal(t, eAB1, heap.Pop(&fh)) 204 205 // Push different spans and times 206 heap.Push(&fh, eAB1) 207 heap.Push(&fh, eBC1) 208 heap.Push(&fh, eAB2) 209 require.Equal(t, eAB1, heap.Pop(&fh)) 210 require.Equal(t, eBC1, heap.Pop(&fh)) 211 require.Equal(t, eAB2, heap.Pop(&fh)) 212 213 // Push in a different span order 214 heap.Push(&fh, eBC1) 215 heap.Push(&fh, eAB1) 216 heap.Push(&fh, eAB2) 217 require.Equal(t, eAB1, heap.Pop(&fh)) 218 require.Equal(t, eBC1, heap.Pop(&fh)) 219 require.Equal(t, eAB2, heap.Pop(&fh)) 220 221 // Push in a different time order 222 heap.Push(&fh, eAB2) 223 heap.Push(&fh, eAB1) 224 heap.Push(&fh, eBC1) 225 require.Equal(t, eAB1, heap.Pop(&fh)) 226 require.Equal(t, eBC1, heap.Pop(&fh)) 227 require.Equal(t, eAB2, heap.Pop(&fh)) 228 }