client-go/integration_tests/client_fp_test.go

99 lines
2.8 KiB
Go

// Copyright 2021 TiKV Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tikv_test
import (
"context"
"time"
"github.com/pingcap/kvproto/pkg/kvrpcpb"
"github.com/pkg/errors"
tikverr "github.com/tikv/client-go/v2/error"
"github.com/tikv/client-go/v2/tikv"
"github.com/tikv/client-go/v2/tikvrpc"
"github.com/tikv/client-go/v2/util"
)
// mock TiKV RPC client that hooks message by failpoint
type fpClient struct {
tikv.Client
}
func (c fpClient) SendRequest(ctx context.Context, addr string, req *tikvrpc.Request, timeout time.Duration) (*tikvrpc.Response, error) {
switch req.Type {
case tikvrpc.CmdPrewrite:
if val, err := util.EvalFailpoint("rpcPrewriteResult"); err == nil && val != nil {
switch val.(string) {
case "timeout":
return nil, errors.New("timeout")
case "writeConflict":
return &tikvrpc.Response{
Resp: &kvrpcpb.PrewriteResponse{Errors: []*kvrpcpb.KeyError{{Conflict: &kvrpcpb.WriteConflict{}}}},
}, nil
}
}
case tikvrpc.CmdBatchGet:
batchGetReq := req.BatchGet()
if val, err := util.EvalFailpoint("rpcBatchGetResult"); err == nil {
switch val.(string) {
case "keyError":
return &tikvrpc.Response{
Resp: &kvrpcpb.BatchGetResponse{Error: &kvrpcpb.KeyError{
Locked: &kvrpcpb.LockInfo{
PrimaryLock: batchGetReq.Keys[0],
LockVersion: batchGetReq.Version - 1,
Key: batchGetReq.Keys[0],
LockTtl: 50,
TxnSize: 1,
LockType: kvrpcpb.Op_Put,
},
}},
}, nil
}
}
case tikvrpc.CmdScan:
kvScanReq := req.Scan()
if val, err := util.EvalFailpoint("rpcScanResult"); err == nil {
switch val.(string) {
case "keyError":
return &tikvrpc.Response{
Resp: &kvrpcpb.ScanResponse{Error: &kvrpcpb.KeyError{
Locked: &kvrpcpb.LockInfo{
PrimaryLock: kvScanReq.StartKey,
LockVersion: kvScanReq.Version - 1,
Key: kvScanReq.StartKey,
LockTtl: 50,
TxnSize: 1,
LockType: kvrpcpb.Op_Put,
},
}},
}, nil
}
}
}
res, err := c.Client.SendRequest(ctx, addr, req, timeout)
switch req.Type {
case tikvrpc.CmdPrewrite:
if val, err := util.EvalFailpoint("rpcPrewriteTimeout"); err == nil {
if val.(bool) {
return nil, tikverr.ErrResultUndetermined
}
}
}
return res, err
}