Skip to content

Commit 9b07945

Browse files
committed
tests: Patch unique non-put ops in robustness
Signed-off-by: Ashwani Kumar Kamal <[email protected]>
1 parent 1b2ed5a commit 9b07945

File tree

3 files changed

+191
-9
lines changed

3 files changed

+191
-9
lines changed

tests/robustness/model/types.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,20 @@ type EtcdCondition struct {
9696
}
9797

9898
type EtcdOperation struct {
99-
Type OperationType
100-
Range RangeOptions
101-
Put PutOptions
102-
Delete DeleteOptions
99+
Type OperationType
100+
Range RangeOptions
101+
Put PutOptions
102+
Delete DeleteOptions
103+
Compact CompactRequest
103104
}
104105

105106
type OperationType string
106107

107108
const (
108-
RangeOperation OperationType = "range-operation"
109-
PutOperation OperationType = "put-operation"
110-
DeleteOperation OperationType = "delete-operation"
109+
RangeOperation OperationType = "range-operation"
110+
PutOperation OperationType = "put-operation"
111+
DeleteOperation OperationType = "delete-operation"
112+
CompactOperation OperationType = "compact-operation"
111113
)
112114

113115
type LeaseGrantRequest struct {

tests/robustness/validate/patch_history.go

Lines changed: 134 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,21 @@ func patchLinearizableOperations(operations []porcupine.Operation, reports []rep
2929
persistedPutCount := countPersistedPuts(persistedRequests)
3030
clientPutCount := countClientPuts(reports)
3131
putReturnTime := uniquePutReturnTime(operations, persistedRequests, clientPutCount)
32-
return patchOperations(operations, putRevision, putReturnTime, clientPutCount, persistedPutCount)
32+
33+
persistedDeleteCount := countPersistedDeletes(persistedRequests)
34+
clientDeleteCount := countClientDeletes(reports)
35+
deleteReturnTime := uniqueDeleteReturnTime(operations, persistedRequests, clientDeleteCount)
36+
37+
persistedCompactCount := countPersistedCompacts(persistedRequests)
38+
clientCompactCount := countClientCompacts(reports)
39+
compactReturnTime := uniqueCompactReturnTime(operations, persistedRequests, clientCompactCount)
40+
41+
return patchOperations(
42+
operations, putRevision, putReturnTime, clientPutCount, persistedPutCount,
43+
clientDeleteCount, persistedDeleteCount,
44+
clientCompactCount, persistedCompactCount,
45+
deleteReturnTime, compactReturnTime,
46+
)
3347
}
3448

3549
func putRevision(reports []report.ClientReport) map[keyValue]int64 {
@@ -54,7 +68,14 @@ func putRevision(reports []report.ClientReport) map[keyValue]int64 {
5468
return requestRevision
5569
}
5670

57-
func patchOperations(operations []porcupine.Operation, watchRevision, putReturnTime, clientPutCount, persistedPutCount map[keyValue]int64) []porcupine.Operation {
71+
func patchOperations(
72+
operations []porcupine.Operation,
73+
watchRevision, putReturnTime, clientPutCount, persistedPutCount map[keyValue]int64,
74+
clientDeleteCount, persistedDeleteCount map[string]int64,
75+
clientCompactCount, persistedCompactCount map[int64]int64,
76+
deleteReturnTime map[string]int64,
77+
compactReturnTime map[int64]int64,
78+
) []porcupine.Operation {
5879
newOperations := make([]porcupine.Operation, 0, len(operations))
5980

6081
for _, op := range operations {
@@ -84,6 +105,27 @@ func patchOperations(operations []porcupine.Operation, watchRevision, putReturnT
84105
op.Return = min(op.Return, returnTime)
85106
}
86107
case model.DeleteOperation:
108+
key := etcdOp.Delete.Key
109+
if _, ok := persistedDeleteCount[key]; ok {
110+
persisted = true
111+
}
112+
if count := clientDeleteCount[key]; count != 1 {
113+
continue
114+
}
115+
if returnTime, ok := deleteReturnTime[key]; ok {
116+
op.Return = min(op.Return, returnTime)
117+
}
118+
case model.CompactOperation:
119+
rev := etcdOp.Compact.Revision
120+
if _, ok := persistedCompactCount[rev]; ok {
121+
persisted = true
122+
}
123+
if count := clientCompactCount[rev]; count != 1 {
124+
continue
125+
}
126+
if returnTime, ok := compactReturnTime[rev]; ok {
127+
op.Return = min(op.Return, returnTime)
128+
}
87129
case model.RangeOperation:
88130
default:
89131
panic(fmt.Sprintf("unknown operation type %q", etcdOp.Type))
@@ -247,6 +289,96 @@ func countPuts(counter map[keyValue]int64, request model.EtcdRequest) {
247289
}
248290
}
249291

292+
func uniqueDeleteReturnTime(allOps []porcupine.Operation, persisted []model.EtcdRequest, clientDeleteCount map[string]int64) map[string]int64 {
293+
times := map[string]int64{}
294+
for _, op := range allOps {
295+
req := op.Input.(model.EtcdRequest)
296+
if req.Type == model.Txn {
297+
for _, e := range append(req.Txn.OperationsOnSuccess, req.Txn.OperationsOnFailure...) {
298+
if e.Type != model.DeleteOperation {
299+
continue
300+
}
301+
k := e.Delete.Key
302+
if clientDeleteCount[k] == 1 {
303+
if t, ok := times[k]; !ok || op.Return < t {
304+
times[k] = op.Return
305+
}
306+
}
307+
}
308+
}
309+
}
310+
return times
311+
}
312+
313+
func countClientDeletes(reports []report.ClientReport) map[string]int64 {
314+
counter := map[string]int64{}
315+
for _, client := range reports {
316+
for _, op := range client.KeyValue {
317+
request := op.Input.(model.EtcdRequest)
318+
countDeletes(counter, request)
319+
}
320+
}
321+
return counter
322+
}
323+
324+
func countPersistedDeletes(requests []model.EtcdRequest) map[string]int64 {
325+
counter := map[string]int64{}
326+
for _, req := range requests {
327+
countDeletes(counter, req)
328+
}
329+
return counter
330+
}
331+
332+
func countDeletes(counter map[string]int64, request model.EtcdRequest) {
333+
if request.Type != model.Txn {
334+
return
335+
}
336+
for _, operation := range append(request.Txn.OperationsOnSuccess, request.Txn.OperationsOnFailure...) {
337+
if operation.Type == model.DeleteOperation {
338+
counter[operation.Delete.Key]++
339+
}
340+
}
341+
}
342+
343+
func uniqueCompactReturnTime(allOps []porcupine.Operation, persisted []model.EtcdRequest, clientCompactCount map[int64]int64) map[int64]int64 {
344+
times := map[int64]int64{}
345+
for _, op := range allOps {
346+
req := op.Input.(model.EtcdRequest)
347+
if req.Type == model.Compact {
348+
rev := req.Compact.Revision
349+
if clientCompactCount[rev] == 1 {
350+
if t, ok := times[rev]; !ok || op.Return < t {
351+
times[rev] = op.Return
352+
}
353+
}
354+
}
355+
}
356+
return times
357+
}
358+
359+
func countClientCompacts(reports []report.ClientReport) map[int64]int64 {
360+
counter := map[int64]int64{}
361+
for _, client := range reports {
362+
for _, op := range client.KeyValue {
363+
request := op.Input.(model.EtcdRequest)
364+
if request.Type == model.Compact {
365+
counter[request.Compact.Revision]++
366+
}
367+
}
368+
}
369+
return counter
370+
}
371+
372+
func countPersistedCompacts(requests []model.EtcdRequest) map[int64]int64 {
373+
counter := map[int64]int64{}
374+
for _, req := range requests {
375+
if req.Type == model.Compact {
376+
counter[req.Compact.Revision]++
377+
}
378+
}
379+
return counter
380+
}
381+
250382
type keyValue struct {
251383
Key string
252384
Value model.ValueOrHash

tests/robustness/validate/patch_history_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,47 @@ func TestPatchHistory(t *testing.T) {
401401
},
402402
expectedRemainingOperations: []porcupine.Operation{},
403403
},
404+
{
405+
name: "successful compact remains",
406+
historyFunc: func(h *model.AppendableHistory) {
407+
h.AppendCompact(42, 100, 200, &clientv3.CompactResponse{}, nil)
408+
},
409+
persistedRequest: []model.EtcdRequest{
410+
compactRequest(42),
411+
},
412+
expectedRemainingOperations: []porcupine.Operation{
413+
{
414+
Output: model.MaybeEtcdResponse{
415+
EtcdResponse: model.EtcdResponse{
416+
Compact: &model.CompactResponse{},
417+
Revision: -1,
418+
},
419+
Persisted: false,
420+
Error: "",
421+
},
422+
Return: 200,
423+
},
424+
},
425+
},
426+
{
427+
name: "failed compact remains if there is a matching persisted request",
428+
historyFunc: func(h *model.AppendableHistory) {
429+
h.AppendCompact(100, 100, 200, nil, errors.New("failed"))
430+
},
431+
persistedRequest: []model.EtcdRequest{
432+
compactRequest(100),
433+
},
434+
expectedRemainingOperations: []porcupine.Operation{
435+
{
436+
Output: model.MaybeEtcdResponse{
437+
EtcdResponse: model.EtcdResponse{},
438+
Persisted: false,
439+
Error: "failed",
440+
},
441+
Return: infinite,
442+
},
443+
},
444+
},
404445
} {
405446
t.Run(tc.name, func(t *testing.T) {
406447
history := model.NewAppendableHistory(identity.NewIDProvider())
@@ -465,3 +506,10 @@ func deleteEvent(key string, revision int64) model.WatchEvent {
465506
},
466507
}
467508
}
509+
510+
func compactRequest(rev int64) model.EtcdRequest {
511+
return model.EtcdRequest{
512+
Type: model.Compact,
513+
Compact: &model.CompactRequest{Revision: rev},
514+
}
515+
}

0 commit comments

Comments
 (0)