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  }