github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/concurrency/datadriven_util_test.go (about) 1 // Copyright 2020 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 concurrency_test 12 13 import ( 14 "strconv" 15 "strings" 16 "testing" 17 18 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/concurrency/lock" 19 "github.com/cockroachdb/cockroach/pkg/roachpb" 20 "github.com/cockroachdb/cockroach/pkg/storage/enginepb" 21 "github.com/cockroachdb/cockroach/pkg/util/hlc" 22 "github.com/cockroachdb/cockroach/pkg/util/uint128" 23 "github.com/cockroachdb/cockroach/pkg/util/uuid" 24 "github.com/cockroachdb/datadriven" 25 ) 26 27 func nextUUID(counter *uint32) uuid.UUID { 28 *counter = *counter + 1 29 hi := uint64(*counter) << 32 30 return uuid.FromUint128(uint128.Uint128{Hi: hi}) 31 } 32 33 func scanTimestamp(t *testing.T, d *datadriven.TestData) hlc.Timestamp { 34 return scanTimestampWithName(t, d, "ts") 35 } 36 37 func scanTimestampWithName(t *testing.T, d *datadriven.TestData, name string) hlc.Timestamp { 38 var ts hlc.Timestamp 39 var tsS string 40 d.ScanArgs(t, name, &tsS) 41 parts := strings.Split(tsS, ",") 42 43 // Find the wall time part. 44 tsW, err := strconv.ParseInt(parts[0], 10, 64) 45 if err != nil { 46 d.Fatalf(t, "%v", err) 47 } 48 ts.WallTime = tsW 49 50 // Find the logical part, if there is one. 51 var tsL int64 52 if len(parts) > 1 { 53 tsL, err = strconv.ParseInt(parts[1], 10, 32) 54 if err != nil { 55 d.Fatalf(t, "%v", err) 56 } 57 } 58 ts.Logical = int32(tsL) 59 return ts 60 } 61 62 func scanLockDurability(t *testing.T, d *datadriven.TestData) lock.Durability { 63 var durS string 64 d.ScanArgs(t, "dur", &durS) 65 switch durS { 66 case "r": 67 return lock.Replicated 68 case "u": 69 return lock.Unreplicated 70 default: 71 d.Fatalf(t, "unknown lock durability: %s", durS) 72 return 0 73 } 74 } 75 76 func scanSingleRequest( 77 t *testing.T, d *datadriven.TestData, line string, txns map[string]*roachpb.Transaction, 78 ) roachpb.Request { 79 cmd, cmdArgs, err := datadriven.ParseLine(line) 80 if err != nil { 81 d.Fatalf(t, "error parsing single request: %v", err) 82 return nil 83 } 84 85 fields := make(map[string]string, len(cmdArgs)) 86 for _, cmdArg := range cmdArgs { 87 if len(cmdArg.Vals) != 1 { 88 d.Fatalf(t, "unexpected command values: %+v", cmdArg) 89 return nil 90 } 91 fields[cmdArg.Key] = cmdArg.Vals[0] 92 } 93 mustGetField := func(f string) string { 94 v, ok := fields[f] 95 if !ok { 96 d.Fatalf(t, "missing required field: %s", f) 97 } 98 return v 99 } 100 maybeGetSeq := func() enginepb.TxnSeq { 101 s, ok := fields["seq"] 102 if !ok { 103 return 0 104 } 105 n, err := strconv.ParseInt(s, 10, 64) 106 if err != nil { 107 d.Fatalf(t, "could not parse seq num: %v", err) 108 } 109 return enginepb.TxnSeq(n) 110 } 111 112 switch cmd { 113 case "get": 114 var r roachpb.GetRequest 115 r.Sequence = maybeGetSeq() 116 r.Key = roachpb.Key(mustGetField("key")) 117 return &r 118 119 case "scan": 120 var r roachpb.ScanRequest 121 r.Sequence = maybeGetSeq() 122 r.Key = roachpb.Key(mustGetField("key")) 123 if v, ok := fields["endkey"]; ok { 124 r.EndKey = roachpb.Key(v) 125 } 126 return &r 127 128 case "put": 129 var r roachpb.PutRequest 130 r.Sequence = maybeGetSeq() 131 r.Key = roachpb.Key(mustGetField("key")) 132 r.Value.SetString(mustGetField("value")) 133 return &r 134 135 case "resolve-intent": 136 var r roachpb.ResolveIntentRequest 137 r.IntentTxn = txns[mustGetField("txn")].TxnMeta 138 r.Key = roachpb.Key(mustGetField("key")) 139 r.Status = parseTxnStatus(t, d, mustGetField("status")) 140 return &r 141 142 case "request-lease": 143 var r roachpb.RequestLeaseRequest 144 return &r 145 146 default: 147 d.Fatalf(t, "unknown request type: %s", cmd) 148 return nil 149 } 150 } 151 152 func scanTxnStatus(t *testing.T, d *datadriven.TestData) (roachpb.TransactionStatus, string) { 153 var statusStr string 154 d.ScanArgs(t, "status", &statusStr) 155 status := parseTxnStatus(t, d, statusStr) 156 var verb string 157 switch status { 158 case roachpb.COMMITTED: 159 verb = "committing" 160 case roachpb.ABORTED: 161 verb = "aborting" 162 case roachpb.PENDING: 163 verb = "increasing timestamp of" 164 default: 165 d.Fatalf(t, "unknown txn status: %s", status) 166 } 167 return status, verb 168 } 169 170 func parseTxnStatus(t *testing.T, d *datadriven.TestData, s string) roachpb.TransactionStatus { 171 switch s { 172 case "committed": 173 return roachpb.COMMITTED 174 case "aborted": 175 return roachpb.ABORTED 176 case "pending": 177 return roachpb.PENDING 178 default: 179 d.Fatalf(t, "unknown txn status: %s", s) 180 return 0 181 } 182 }