github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/rditer/replica_data_iter_test.go (about) 1 // Copyright 2015 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 rditer 12 13 import ( 14 "bytes" 15 "context" 16 "fmt" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/keys" 20 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/spanset" 21 "github.com/cockroachdb/cockroach/pkg/roachpb" 22 "github.com/cockroachdb/cockroach/pkg/storage" 23 "github.com/cockroachdb/cockroach/pkg/testutils" 24 "github.com/cockroachdb/cockroach/pkg/util/hlc" 25 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 26 "github.com/cockroachdb/cockroach/pkg/util/uuid" 27 ) 28 29 func fakePrevKey(k []byte) roachpb.Key { 30 const maxLen = 100 31 length := len(k) 32 33 // When the byte array is empty. 34 if length == 0 { 35 panic("cannot get the prev key of an empty key") 36 } 37 if length > maxLen { 38 panic(fmt.Sprintf("test does not support key longer than %d characters: %q", maxLen, k)) 39 } 40 41 // If the last byte is a 0, then drop it. 42 if k[length-1] == 0 { 43 return k[0 : length-1] 44 } 45 46 // If the last byte isn't 0, subtract one from it and append "\xff"s 47 // until the end of the key space. 48 return bytes.Join([][]byte{ 49 k[0 : length-1], 50 {k[length-1] - 1}, 51 bytes.Repeat([]byte{0xff}, maxLen-length), 52 }, nil) 53 } 54 55 func uuidFromString(input string) uuid.UUID { 56 u, err := uuid.FromString(input) 57 if err != nil { 58 panic(err) 59 } 60 return u 61 } 62 63 // createRangeData creates sample range data in all possible areas of 64 // the key space. Returns a slice of the encoded keys of all created 65 // data. 66 func createRangeData( 67 t *testing.T, eng storage.Engine, desc roachpb.RangeDescriptor, 68 ) []storage.MVCCKey { 69 testTxnID := uuidFromString("0ce61c17-5eb4-4587-8c36-dcf4062ada4c") 70 testTxnID2 := uuidFromString("9855a1ef-8eb9-4c06-a106-cab1dda78a2b") 71 72 ts0 := hlc.Timestamp{} 73 ts := hlc.Timestamp{WallTime: 1} 74 keyTSs := []struct { 75 key roachpb.Key 76 ts hlc.Timestamp 77 }{ 78 {keys.AbortSpanKey(desc.RangeID, testTxnID), ts0}, 79 {keys.AbortSpanKey(desc.RangeID, testTxnID2), ts0}, 80 {keys.RangeLastGCKey(desc.RangeID), ts0}, 81 {keys.RangeAppliedStateKey(desc.RangeID), ts0}, 82 {keys.RaftAppliedIndexLegacyKey(desc.RangeID), ts0}, 83 {keys.RaftTruncatedStateLegacyKey(desc.RangeID), ts0}, 84 {keys.RangeLeaseKey(desc.RangeID), ts0}, 85 {keys.LeaseAppliedIndexLegacyKey(desc.RangeID), ts0}, 86 {keys.RangeStatsLegacyKey(desc.RangeID), ts0}, 87 {keys.RangeTombstoneKey(desc.RangeID), ts0}, 88 {keys.RaftHardStateKey(desc.RangeID), ts0}, 89 {keys.RaftLogKey(desc.RangeID, 1), ts0}, 90 {keys.RaftLogKey(desc.RangeID, 2), ts0}, 91 {keys.RangeLastReplicaGCTimestampKey(desc.RangeID), ts0}, 92 {keys.RangeDescriptorKey(desc.StartKey), ts}, 93 {keys.TransactionKey(roachpb.Key(desc.StartKey), uuid.MakeV4()), ts0}, 94 {keys.TransactionKey(roachpb.Key(desc.StartKey.Next()), uuid.MakeV4()), ts0}, 95 {keys.TransactionKey(fakePrevKey(desc.EndKey), uuid.MakeV4()), ts0}, 96 // TODO(bdarnell): KeyMin.Next() results in a key in the reserved system-local space. 97 // Once we have resolved https://github.com/cockroachdb/cockroach/issues/437, 98 // replace this with something that reliably generates the first valid key in the range. 99 //{r.Desc().StartKey.Next(), ts}, 100 // The following line is similar to StartKey.Next() but adds more to the key to 101 // avoid falling into the system-local space. 102 {append(append([]byte{}, desc.StartKey...), '\x02'), ts}, 103 {fakePrevKey(desc.EndKey), ts}, 104 } 105 106 keys := []storage.MVCCKey{} 107 for _, keyTS := range keyTSs { 108 if err := storage.MVCCPut(context.Background(), eng, nil, keyTS.key, keyTS.ts, roachpb.MakeValueFromString("value"), nil); err != nil { 109 t.Fatal(err) 110 } 111 keys = append(keys, storage.MVCCKey{Key: keyTS.key, Timestamp: keyTS.ts}) 112 } 113 return keys 114 } 115 116 func verifyRDIter( 117 t *testing.T, 118 desc *roachpb.RangeDescriptor, 119 readWriter storage.ReadWriter, 120 replicatedOnly bool, 121 expectedKeys []storage.MVCCKey, 122 ) { 123 t.Helper() 124 verify := func(t *testing.T, useSpanSet, reverse bool) { 125 if useSpanSet { 126 var spans spanset.SpanSet 127 spans.AddNonMVCC(spanset.SpanReadOnly, roachpb.Span{ 128 Key: keys.MakeRangeIDPrefix(desc.RangeID), 129 EndKey: keys.MakeRangeIDPrefix(desc.RangeID).PrefixEnd(), 130 }) 131 spans.AddNonMVCC(spanset.SpanReadOnly, roachpb.Span{ 132 Key: keys.MakeRangeKeyPrefix(desc.StartKey), 133 EndKey: keys.MakeRangeKeyPrefix(desc.EndKey), 134 }) 135 spans.AddMVCC(spanset.SpanReadOnly, roachpb.Span{ 136 Key: desc.StartKey.AsRawKey(), 137 EndKey: desc.EndKey.AsRawKey(), 138 }, hlc.Timestamp{WallTime: 42}) 139 readWriter = spanset.NewReadWriterAt(readWriter, &spans, hlc.Timestamp{WallTime: 42}) 140 } 141 iter := NewReplicaDataIterator(desc, readWriter, replicatedOnly, reverse /* seekEnd */) 142 defer iter.Close() 143 i := 0 144 if reverse { 145 i = len(expectedKeys) - 1 146 } 147 for { 148 if ok, err := iter.Valid(); err != nil { 149 t.Fatal(err) 150 } else if !ok { 151 break 152 } 153 if !reverse && i >= len(expectedKeys) { 154 t.Fatal("there are more keys in the iteration than expected") 155 } 156 if reverse && i < 0 { 157 t.Fatal("there are more keys in the iteration than expected") 158 } 159 if key := iter.Key(); !key.Equal(expectedKeys[i]) { 160 k1, ts1 := key.Key, key.Timestamp 161 k2, ts2 := expectedKeys[i].Key, expectedKeys[i].Timestamp 162 t.Errorf("%d: expected %q(%d); got %q(%d)", i, k2, ts2, k1, ts1) 163 } 164 if reverse { 165 i-- 166 iter.Prev() 167 } else { 168 i++ 169 iter.Next() 170 } 171 } 172 if (reverse && i >= 0) || (!reverse && i != len(expectedKeys)) { 173 t.Fatal("there are fewer keys in the iteration than expected") 174 } 175 } 176 testutils.RunTrueAndFalse(t, "reverse", func(t *testing.T, reverse bool) { 177 testutils.RunTrueAndFalse(t, "spanset", func(t *testing.T, useSpanSet bool) { 178 verify(t, useSpanSet, reverse) 179 }) 180 }) 181 } 182 183 // TestReplicaDataIterator verifies correct operation of iterator if 184 // a range contains no data and never has. 185 func TestReplicaDataIteratorEmptyRange(t *testing.T) { 186 defer leaktest.AfterTest(t)() 187 188 eng := storage.NewDefaultInMem() 189 defer eng.Close() 190 191 desc := &roachpb.RangeDescriptor{ 192 RangeID: 12345, 193 StartKey: roachpb.RKey("a"), 194 EndKey: roachpb.RKey("z"), 195 } 196 197 verifyRDIter(t, desc, eng, false /* replicatedOnly */, []storage.MVCCKey{}) 198 } 199 200 // TestReplicaDataIterator creates three ranges {"a"-"b" (pre), "b"-"c" 201 // (main test range), "c"-"d" (post)} and fills each with data. It 202 // first verifies the contents of the "b"-"c" range. Next, it makes sure 203 // a replicated-only iterator does not show any unreplicated keys from 204 // the range. Then, it deletes the range and verifies it's empty. Finally, 205 // it verifies the pre and post ranges still contain the expected data. 206 func TestReplicaDataIterator(t *testing.T) { 207 defer leaktest.AfterTest(t)() 208 209 eng := storage.NewDefaultInMem() 210 defer eng.Close() 211 212 descPre := roachpb.RangeDescriptor{ 213 RangeID: 1, 214 StartKey: roachpb.RKeyMin, 215 EndKey: roachpb.RKey("b"), 216 } 217 desc := roachpb.RangeDescriptor{ 218 RangeID: 2, 219 StartKey: roachpb.RKey("b"), 220 EndKey: roachpb.RKey("c"), 221 } 222 descPost := roachpb.RangeDescriptor{ 223 RangeID: 3, 224 StartKey: roachpb.RKey("c"), 225 EndKey: roachpb.RKeyMax, 226 } 227 228 // Create range data for all three ranges. 229 preKeys := createRangeData(t, eng, descPre) 230 curKeys := createRangeData(t, eng, desc) 231 postKeys := createRangeData(t, eng, descPost) 232 233 // Verify the contents of the "b"-"c" range. 234 t.Run("cur", func(t *testing.T) { 235 verifyRDIter(t, &desc, eng, false /* replicatedOnly */, curKeys) 236 }) 237 238 // Verify that the replicated-only iterator ignores unreplicated keys. 239 unreplicatedPrefix := keys.MakeRangeIDUnreplicatedPrefix(desc.RangeID) 240 iter := NewReplicaDataIterator(&desc, eng, 241 true /* replicatedOnly */, false /* seekEnd */) 242 defer iter.Close() 243 for ; ; iter.Next() { 244 if ok, err := iter.Valid(); err != nil { 245 t.Fatal(err) 246 } else if !ok { 247 break 248 } 249 if bytes.HasPrefix(iter.Key().Key, unreplicatedPrefix) { 250 t.Fatalf("unexpected unreplicated key: %s", iter.Key().Key) 251 } 252 } 253 254 // Verify the keys in pre & post ranges. 255 for _, test := range []struct { 256 name string 257 desc *roachpb.RangeDescriptor 258 keys []storage.MVCCKey 259 }{ 260 {"pre", &descPre, preKeys}, 261 {"post", &descPost, postKeys}, 262 } { 263 t.Run(test.name, func(t *testing.T) { 264 verifyRDIter(t, test.desc, eng, false /* replicatedOnly */, test.keys) 265 }) 266 } 267 }