github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/spanset/spanset_test.go (about) 1 // Copyright 2017 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 spanset 12 13 import ( 14 "reflect" 15 "testing" 16 17 "github.com/cockroachdb/cockroach/pkg/keys" 18 "github.com/cockroachdb/cockroach/pkg/roachpb" 19 "github.com/cockroachdb/cockroach/pkg/testutils" 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 // Test that spans are properly classified as global or local and that 26 // GetSpans respects the scope argument. 27 func TestSpanSetGetSpansScope(t *testing.T) { 28 defer leaktest.AfterTest(t)() 29 30 var ss SpanSet 31 ss.AddNonMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("a")}) 32 ss.AddNonMVCC(SpanReadOnly, roachpb.Span{Key: keys.RangeLastGCKey(1)}) 33 ss.AddNonMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("c")}) 34 35 exp := []Span{ 36 {Span: roachpb.Span{Key: keys.RangeLastGCKey(1)}}, 37 } 38 if act := ss.GetSpans(SpanReadOnly, SpanLocal); !reflect.DeepEqual(act, exp) { 39 t.Errorf("get local spans: got %v, expected %v", act, exp) 40 } 41 42 exp = []Span{ 43 {Span: roachpb.Span{Key: roachpb.Key("a")}}, 44 {Span: roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("c")}}, 45 } 46 47 if act := ss.GetSpans(SpanReadOnly, SpanGlobal); !reflect.DeepEqual(act, exp) { 48 t.Errorf("get global spans: got %v, expected %v", act, exp) 49 } 50 } 51 52 func TestSpanSetMerge(t *testing.T) { 53 defer leaktest.AfterTest(t)() 54 55 spA := roachpb.Span{Key: roachpb.Key("a")} 56 spBC := roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("c")} 57 spCE := roachpb.Span{Key: roachpb.Key("c"), EndKey: roachpb.Key("e")} 58 spBE := roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("e")} 59 spLocal := roachpb.Span{Key: keys.RangeLastGCKey(1)} 60 61 var ss SpanSet 62 ss.AddNonMVCC(SpanReadOnly, spLocal) 63 ss.AddNonMVCC(SpanReadOnly, spA) 64 ss.AddNonMVCC(SpanReadWrite, spBC) 65 require.Equal(t, []Span{{Span: spLocal}}, ss.GetSpans(SpanReadOnly, SpanLocal)) 66 require.Equal(t, []Span{{Span: spA}}, ss.GetSpans(SpanReadOnly, SpanGlobal)) 67 require.Equal(t, []Span{{Span: spBC}}, ss.GetSpans(SpanReadWrite, SpanGlobal)) 68 69 var ss2 SpanSet 70 ss2.AddNonMVCC(SpanReadWrite, spCE) 71 require.Nil(t, ss2.GetSpans(SpanReadOnly, SpanLocal)) 72 require.Nil(t, ss2.GetSpans(SpanReadOnly, SpanGlobal)) 73 require.Equal(t, []Span{{Span: spCE}}, ss2.GetSpans(SpanReadWrite, SpanGlobal)) 74 75 // Merge merges all spans. Notice the new spBE span. 76 ss2.Merge(&ss) 77 require.Equal(t, []Span{{Span: spLocal}}, ss2.GetSpans(SpanReadOnly, SpanLocal)) 78 require.Equal(t, []Span{{Span: spA}}, ss2.GetSpans(SpanReadOnly, SpanGlobal)) 79 require.Equal(t, []Span{{Span: spBE}}, ss2.GetSpans(SpanReadWrite, SpanGlobal)) 80 81 // The source set is not mutated on future changes to the merged set. 82 ss2.AddNonMVCC(SpanReadOnly, spCE) 83 require.Equal(t, []Span{{Span: spLocal}}, ss.GetSpans(SpanReadOnly, SpanLocal)) 84 require.Equal(t, []Span{{Span: spA}}, ss.GetSpans(SpanReadOnly, SpanGlobal)) 85 require.Equal(t, []Span{{Span: spBC}}, ss.GetSpans(SpanReadWrite, SpanGlobal)) 86 require.Equal(t, []Span{{Span: spLocal}}, ss2.GetSpans(SpanReadOnly, SpanLocal)) 87 require.Equal(t, []Span{{Span: spA}, {Span: spCE}}, ss2.GetSpans(SpanReadOnly, SpanGlobal)) 88 require.Equal(t, []Span{{Span: spBE}}, ss2.GetSpans(SpanReadWrite, SpanGlobal)) 89 } 90 91 func TestSpanSetMaxProtectedTimestamp(t *testing.T) { 92 defer leaktest.AfterTest(t)() 93 94 spA := roachpb.Span{Key: roachpb.Key("a")} 95 spBC := roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("c")} 96 spCE := roachpb.Span{Key: roachpb.Key("c"), EndKey: roachpb.Key("e")} 97 spLocal := roachpb.Span{Key: keys.RangeLastGCKey(1)} 98 99 var ss SpanSet 100 ss.AddNonMVCC(SpanReadOnly, spLocal) 101 ss.AddNonMVCC(SpanReadOnly, spA) 102 ss.AddNonMVCC(SpanReadWrite, spBC) 103 require.Equal(t, hlc.MaxTimestamp, ss.MaxProtectedTimestamp()) 104 105 var ss2 SpanSet 106 ss2.AddNonMVCC(SpanReadOnly, spLocal) 107 ss2.AddNonMVCC(SpanReadOnly, spA) 108 ss2.AddMVCC(SpanReadWrite, spBC, hlc.Timestamp{WallTime: 12}) 109 require.Equal(t, hlc.MaxTimestamp, ss2.MaxProtectedTimestamp()) 110 111 var ss3 SpanSet 112 ss3.AddNonMVCC(SpanReadOnly, spLocal) 113 ss3.AddMVCC(SpanReadOnly, spA, hlc.Timestamp{WallTime: 11}) 114 ss3.AddNonMVCC(SpanReadWrite, spCE) 115 ss3.AddMVCC(SpanReadWrite, spBC, hlc.Timestamp{WallTime: 12}) 116 require.Equal(t, hlc.Timestamp{WallTime: 11}, ss3.MaxProtectedTimestamp()) 117 } 118 119 // Test that CheckAllowed properly enforces span boundaries. 120 func TestSpanSetCheckAllowedBoundaries(t *testing.T) { 121 defer leaktest.AfterTest(t)() 122 123 var bdGkq SpanSet 124 bdGkq.AddNonMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("d")}) 125 bdGkq.AddNonMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("g")}) 126 bdGkq.AddNonMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("k"), EndKey: roachpb.Key("q")}) 127 128 allowed := []roachpb.Span{ 129 // Exactly as declared. 130 {Key: roachpb.Key("b"), EndKey: roachpb.Key("d")}, 131 {Key: roachpb.Key("g")}, 132 {Key: roachpb.Key("k"), EndKey: roachpb.Key("q")}, 133 134 // Points within the non-zero-length spans. 135 {Key: roachpb.Key("c")}, 136 {Key: roachpb.Key("l")}, 137 138 // Sub-spans. 139 {Key: roachpb.Key("b"), EndKey: roachpb.Key("c")}, 140 {Key: roachpb.Key("c"), EndKey: roachpb.Key("d")}, 141 {Key: roachpb.Key("l"), EndKey: roachpb.Key("m")}, 142 } 143 for _, span := range allowed { 144 if err := bdGkq.CheckAllowed(SpanReadOnly, span); err != nil { 145 t.Errorf("expected %s to be allowed, but got error: %+v", span, err) 146 } 147 } 148 149 disallowed := []roachpb.Span{ 150 // Points outside the declared spans, and on the endpoints. 151 {Key: roachpb.Key("a")}, 152 {Key: roachpb.Key("d")}, 153 {Key: roachpb.Key("h")}, 154 {Key: roachpb.Key("v")}, 155 {Key: roachpb.Key("q")}, 156 157 // Spans outside the declared spans. 158 {Key: roachpb.Key("a"), EndKey: roachpb.Key("b")}, 159 {Key: roachpb.Key("e"), EndKey: roachpb.Key("f")}, 160 {Key: roachpb.Key("q"), EndKey: roachpb.Key("z")}, 161 162 // Partial overlap. 163 {Key: roachpb.Key("a"), EndKey: roachpb.Key("c")}, 164 {Key: roachpb.Key("c"), EndKey: roachpb.Key("m")}, 165 {Key: roachpb.Key("g"), EndKey: roachpb.Key("k")}, 166 167 // Just past the end. 168 {Key: roachpb.Key("b"), EndKey: roachpb.Key("d").Next()}, 169 {Key: roachpb.Key("g"), EndKey: roachpb.Key("g").Next()}, 170 {Key: roachpb.Key("k"), EndKey: roachpb.Key("q").Next()}, 171 } 172 for _, span := range disallowed { 173 if err := bdGkq.CheckAllowed(SpanReadOnly, span); err == nil { 174 t.Errorf("expected %s to be disallowed", span) 175 } 176 } 177 } 178 179 // Test that CheckAllowedAt properly enforces timestamp control. 180 func TestSpanSetCheckAllowedAtTimestamps(t *testing.T) { 181 defer leaktest.AfterTest(t)() 182 183 var ss SpanSet 184 ss.AddMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("d")}, hlc.Timestamp{WallTime: 2}) 185 ss.AddMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("g")}, hlc.Timestamp{WallTime: 2}) 186 ss.AddMVCC(SpanReadWrite, roachpb.Span{Key: roachpb.Key("m"), EndKey: roachpb.Key("o")}, hlc.Timestamp{WallTime: 2}) 187 ss.AddMVCC(SpanReadWrite, roachpb.Span{Key: roachpb.Key("s")}, hlc.Timestamp{WallTime: 2}) 188 ss.AddNonMVCC(SpanReadWrite, roachpb.Span{Key: keys.RangeLastGCKey(1)}) 189 190 var allowedRO = []struct { 191 span roachpb.Span 192 ts hlc.Timestamp 193 }{ 194 // Read access allowed for a subspan or included point at a timestamp 195 // equal to or below associated timestamp. 196 {roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("d")}, hlc.Timestamp{WallTime: 2}}, 197 {roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("d")}, hlc.Timestamp{WallTime: 1}}, 198 {roachpb.Span{Key: roachpb.Key("m"), EndKey: roachpb.Key("o")}, hlc.Timestamp{WallTime: 3}}, 199 {roachpb.Span{Key: roachpb.Key("m"), EndKey: roachpb.Key("o")}, hlc.Timestamp{WallTime: 2}}, 200 {roachpb.Span{Key: roachpb.Key("m"), EndKey: roachpb.Key("o")}, hlc.Timestamp{WallTime: 1}}, 201 {roachpb.Span{Key: roachpb.Key("g")}, hlc.Timestamp{WallTime: 2}}, 202 {roachpb.Span{Key: roachpb.Key("g")}, hlc.Timestamp{WallTime: 1}}, 203 {roachpb.Span{Key: roachpb.Key("s")}, hlc.Timestamp{WallTime: 3}}, 204 {roachpb.Span{Key: roachpb.Key("s")}, hlc.Timestamp{WallTime: 2}}, 205 {roachpb.Span{Key: roachpb.Key("s")}, hlc.Timestamp{WallTime: 1}}, 206 207 // Local keys. 208 {roachpb.Span{Key: keys.RangeLastGCKey(1)}, hlc.Timestamp{}}, 209 {roachpb.Span{Key: keys.RangeLastGCKey(1)}, hlc.Timestamp{WallTime: 1}}, 210 } 211 for _, tc := range allowedRO { 212 if err := ss.CheckAllowedAt(SpanReadOnly, tc.span, tc.ts); err != nil { 213 t.Errorf("expected %s at %s to be allowed, but got error: %+v", tc.span, tc.ts, err) 214 } 215 } 216 217 var allowedRW = []struct { 218 span roachpb.Span 219 ts hlc.Timestamp 220 }{ 221 // Write access allowed for a subspan or included point at exactly the 222 // declared timestamp. 223 {roachpb.Span{Key: roachpb.Key("m"), EndKey: roachpb.Key("o")}, hlc.Timestamp{WallTime: 2}}, 224 {roachpb.Span{Key: roachpb.Key("m"), EndKey: roachpb.Key("o")}, hlc.Timestamp{WallTime: 3}}, 225 {roachpb.Span{Key: roachpb.Key("s")}, hlc.Timestamp{WallTime: 2}}, 226 {roachpb.Span{Key: roachpb.Key("s")}, hlc.Timestamp{WallTime: 3}}, 227 228 // Points within the non-zero-length span. 229 {roachpb.Span{Key: roachpb.Key("n")}, hlc.Timestamp{WallTime: 2}}, 230 231 // Points within the non-zero-length span at a timestamp higher than what's 232 // declared. 233 {roachpb.Span{Key: roachpb.Key("n")}, hlc.Timestamp{WallTime: 3}}, 234 235 // Sub span at and above the declared timestamp. 236 {roachpb.Span{Key: roachpb.Key("m"), EndKey: roachpb.Key("n")}, hlc.Timestamp{WallTime: 2}}, 237 {roachpb.Span{Key: roachpb.Key("m"), EndKey: roachpb.Key("n")}, hlc.Timestamp{WallTime: 3}}, 238 239 // Local keys. 240 {roachpb.Span{Key: keys.RangeLastGCKey(1)}, hlc.Timestamp{}}, 241 } 242 for _, tc := range allowedRW { 243 if err := ss.CheckAllowedAt(SpanReadWrite, tc.span, tc.ts); err != nil { 244 t.Errorf("expected %s at %s to be allowed, but got error: %+v", tc.span, tc.ts, err) 245 } 246 } 247 248 readErr := "cannot read undeclared span" 249 writeErr := "cannot write undeclared span" 250 251 var disallowedRO = []struct { 252 span roachpb.Span 253 ts hlc.Timestamp 254 }{ 255 // Read access disallowed for subspan or included point at timestamp greater 256 // than the associated timestamp. 257 {roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("d")}, hlc.Timestamp{WallTime: 3}}, 258 {roachpb.Span{Key: roachpb.Key("g")}, hlc.Timestamp{WallTime: 3}}, 259 } 260 for _, tc := range disallowedRO { 261 if err := ss.CheckAllowedAt(SpanReadOnly, tc.span, tc.ts); !testutils.IsError(err, readErr) { 262 t.Errorf("expected %s at %s to be disallowed", tc.span, tc.ts) 263 } 264 } 265 266 var disallowedRW = []struct { 267 span roachpb.Span 268 ts hlc.Timestamp 269 }{ 270 // Write access disallowed for subspan or included point at timestamp 271 // less than the associated timestamp. 272 {roachpb.Span{Key: roachpb.Key("m"), EndKey: roachpb.Key("o")}, hlc.Timestamp{WallTime: 1}}, 273 {roachpb.Span{Key: roachpb.Key("s")}, hlc.Timestamp{WallTime: 1}}, 274 275 // Read only spans. 276 {roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("d")}, hlc.Timestamp{WallTime: 2}}, 277 {roachpb.Span{Key: roachpb.Key("c")}, hlc.Timestamp{WallTime: 2}}, 278 279 // Points within the non-zero-length span at a timestamp lower than what's 280 // declared. 281 {roachpb.Span{Key: roachpb.Key("n")}, hlc.Timestamp{WallTime: 1}}, 282 283 // Sub span below the declared timestamp. 284 {roachpb.Span{Key: roachpb.Key("m"), EndKey: roachpb.Key("n")}, hlc.Timestamp{WallTime: 1}}, 285 } 286 for _, tc := range disallowedRW { 287 if err := ss.CheckAllowedAt(SpanReadWrite, tc.span, tc.ts); !testutils.IsError(err, writeErr) { 288 t.Errorf("expected %s at %s to be disallowed", tc.span, tc.ts) 289 } 290 } 291 } 292 293 func TestSpanSetCheckAllowedReversed(t *testing.T) { 294 defer leaktest.AfterTest(t)() 295 296 var bdGkq SpanSet 297 bdGkq.AddNonMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("d")}) 298 bdGkq.AddNonMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("g")}) 299 bdGkq.AddNonMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("k"), EndKey: roachpb.Key("q")}) 300 301 allowed := []roachpb.Span{ 302 // Exactly as declared. 303 {EndKey: roachpb.Key("d")}, 304 {EndKey: roachpb.Key("q")}, 305 } 306 for _, span := range allowed { 307 if err := bdGkq.CheckAllowed(SpanReadOnly, span); err != nil { 308 t.Errorf("expected %s to be allowed, but got error: %+v", span, err) 309 } 310 } 311 312 disallowed := []roachpb.Span{ 313 // Points outside the declared spans, and on the endpoints. 314 {EndKey: roachpb.Key("b")}, 315 {EndKey: roachpb.Key("g")}, 316 {EndKey: roachpb.Key("k")}, 317 } 318 for _, span := range disallowed { 319 if err := bdGkq.CheckAllowed(SpanReadOnly, span); err == nil { 320 t.Errorf("expected %s to be disallowed", span) 321 } 322 } 323 } 324 325 func TestSpanSetCheckAllowedAtReversed(t *testing.T) { 326 defer leaktest.AfterTest(t)() 327 328 ts := hlc.Timestamp{WallTime: 42} 329 var bdGkq SpanSet 330 bdGkq.AddMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("b"), EndKey: roachpb.Key("d")}, ts) 331 bdGkq.AddMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("g")}, ts) 332 bdGkq.AddMVCC(SpanReadOnly, roachpb.Span{Key: roachpb.Key("k"), EndKey: roachpb.Key("q")}, ts) 333 334 allowed := []roachpb.Span{ 335 // Exactly as declared. 336 {EndKey: roachpb.Key("d")}, 337 {EndKey: roachpb.Key("q")}, 338 } 339 for _, span := range allowed { 340 if err := bdGkq.CheckAllowedAt(SpanReadOnly, span, ts); err != nil { 341 t.Errorf("expected %s to be allowed, but got error: %+v", span, err) 342 } 343 } 344 345 disallowed := []roachpb.Span{ 346 // Points outside the declared spans, and on the endpoints. 347 {EndKey: roachpb.Key("b")}, 348 {EndKey: roachpb.Key("g")}, 349 {EndKey: roachpb.Key("k")}, 350 } 351 for _, span := range disallowed { 352 if err := bdGkq.CheckAllowedAt(SpanReadOnly, span, ts); err == nil { 353 t.Errorf("expected %s to be disallowed", span) 354 } 355 } 356 } 357 358 // Test that a span declared for write access also implies read 359 // access, but not vice-versa. 360 func TestSpanSetWriteImpliesRead(t *testing.T) { 361 defer leaktest.AfterTest(t)() 362 363 var ss SpanSet 364 roSpan := roachpb.Span{Key: roachpb.Key("read-only")} 365 rwSpan := roachpb.Span{Key: roachpb.Key("read-write")} 366 ss.AddNonMVCC(SpanReadOnly, roSpan) 367 ss.AddNonMVCC(SpanReadWrite, rwSpan) 368 369 if err := ss.CheckAllowed(SpanReadOnly, roSpan); err != nil { 370 t.Errorf("expected to be allowed to read roSpan, error: %+v", err) 371 } 372 if err := ss.CheckAllowed(SpanReadWrite, roSpan); err == nil { 373 t.Errorf("expected not to be allowed to write roSpan") 374 } 375 if err := ss.CheckAllowed(SpanReadOnly, rwSpan); err != nil { 376 t.Errorf("expected to be allowed to read rwSpan, error: %+v", err) 377 } 378 if err := ss.CheckAllowed(SpanReadWrite, rwSpan); err != nil { 379 t.Errorf("expected to be allowed to read rwSpan, error: %+v", err) 380 } 381 }