github.com/pingcap/chaos@v0.0.0-20190710112158-c86faf4b3719/pkg/history/history_test.go (about) 1 package history 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path" 7 "testing" 8 9 "github.com/pingcap/chaos/pkg/core" 10 ) 11 12 func TestRecordAndReadHistory(t *testing.T) { 13 tmpDir, err := ioutil.TempDir(".", "var") 14 if err != nil { 15 t.Fatalf("create temp dir failed %v", err) 16 } 17 18 defer os.RemoveAll(tmpDir) 19 20 var r *Recorder 21 name := path.Join(tmpDir, "history.log") 22 r, err = NewRecorder(name) 23 if err != nil { 24 t.Fatalf("create recorder failed %v", err) 25 } 26 27 defer r.Close() 28 29 actions := []action{ 30 {1, NoopRequest{Op: 0}}, 31 {1, NoopResponse{Value: 10}}, 32 {2, NoopRequest{Op: 1, Value: 15}}, 33 {2, NoopResponse{Value: 15}}, 34 {3, NoopRequest{Op: 0}}, 35 {3, NoopResponse{Value: 15}}, 36 } 37 parserState := 7 38 39 for _, action := range actions { 40 switch v := action.op.(type) { 41 case NoopRequest: 42 if err = r.RecordRequest(action.proc, v); err != nil { 43 t.Fatalf("record request failed %v", err) 44 } 45 case NoopResponse: 46 if err = r.RecordResponse(action.proc, v); err != nil { 47 t.Fatalf("record response failed %v", err) 48 } 49 } 50 } 51 if err = r.RecordState(parserState); err != nil { 52 t.Fatalf("record dump failed %v", err) 53 } 54 55 ops, state, err := ReadHistory(name, NoopParser{State: parserState}) 56 if err != nil { 57 t.Fatal(err) 58 } 59 60 if state.(int) != parserState { 61 t.Fatalf("expect state to be %v, got %v", parserState, state) 62 } 63 64 if len(ops) != len(actions) { 65 t.Fatalf("actions %v mismatchs ops %v", actions, ops) 66 } 67 68 for idx, ac := range actions { 69 switch v := ac.op.(type) { 70 case NoopRequest: 71 a, ok := ops[idx].Data.(NoopRequest) 72 if !ok { 73 t.Fatalf("unexpected: %#v", ops[idx]) 74 } 75 if a != v { 76 t.Fatalf("actions %#v mismatchs ops %#v", a, ops[idx]) 77 } 78 case NoopResponse: 79 a, ok := ops[idx].Data.(NoopResponse) 80 if !ok { 81 t.Fatalf("unexpected: %#v", ops[idx]) 82 } 83 if a != v { 84 t.Fatalf("actions %#v mismatchs ops %#v", a, ops[idx]) 85 } 86 } 87 } 88 } 89 90 func TestCompleteOperation(t *testing.T) { 91 cases := []struct { 92 ops []core.Operation 93 compOps []core.Operation 94 }{ 95 // A complete history of operations. 96 { 97 ops: []core.Operation{ 98 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 99 {core.ReturnOperation, 1, NoopResponse{Value: 10}}, 100 {core.InvokeOperation, 2, NoopRequest{Op: 1, Value: 15}}, 101 {core.ReturnOperation, 2, NoopResponse{Value: 15}}, 102 }, 103 compOps: []core.Operation{ 104 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 105 {core.ReturnOperation, 1, NoopResponse{Value: 10}}, 106 {core.InvokeOperation, 2, NoopRequest{Op: 1, Value: 15}}, 107 {core.ReturnOperation, 2, NoopResponse{Value: 15}}, 108 }, 109 }, 110 // A complete but repeated proc operations. 111 { 112 ops: []core.Operation{ 113 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 114 {core.ReturnOperation, 1, NoopResponse{Value: 10}}, 115 {core.InvokeOperation, 2, NoopRequest{Op: 1, Value: 15}}, 116 {core.ReturnOperation, 2, NoopResponse{Value: 15}}, 117 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 118 {core.ReturnOperation, 1, NoopResponse{Value: 15}}, 119 }, 120 compOps: []core.Operation{ 121 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 122 {core.ReturnOperation, 1, NoopResponse{Value: 10}}, 123 {core.InvokeOperation, 2, NoopRequest{Op: 1, Value: 15}}, 124 {core.ReturnOperation, 2, NoopResponse{Value: 15}}, 125 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 126 {core.ReturnOperation, 1, NoopResponse{Value: 15}}, 127 }, 128 }, 129 130 // Pending requests. 131 { 132 ops: []core.Operation{ 133 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 134 {core.ReturnOperation, 1, nil}, 135 }, 136 compOps: []core.Operation{ 137 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 138 {core.ReturnOperation, 1, NoopResponse{Unknown: true}}, 139 }, 140 }, 141 142 // Missing a response 143 { 144 ops: []core.Operation{ 145 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 146 }, 147 compOps: []core.Operation{ 148 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 149 {core.ReturnOperation, 1, NoopResponse{Unknown: true}}, 150 }, 151 }, 152 153 // A complex out of order history. 154 { 155 ops: []core.Operation{ 156 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 157 {core.InvokeOperation, 3, NoopRequest{Op: 0}}, 158 {core.InvokeOperation, 2, NoopRequest{Op: 1, Value: 15}}, 159 {core.ReturnOperation, 2, nil}, 160 {core.InvokeOperation, 4, NoopRequest{Op: 1, Value: 16}}, 161 {core.ReturnOperation, 3, nil}, 162 }, 163 compOps: []core.Operation{ 164 {core.InvokeOperation, 1, NoopRequest{Op: 0}}, 165 {core.InvokeOperation, 3, NoopRequest{Op: 0}}, 166 {core.InvokeOperation, 2, NoopRequest{Op: 1, Value: 15}}, 167 {core.InvokeOperation, 4, NoopRequest{Op: 1, Value: 16}}, 168 {core.ReturnOperation, 1, NoopResponse{Unknown: true}}, 169 {core.ReturnOperation, 2, NoopResponse{Unknown: true}}, 170 {core.ReturnOperation, 3, NoopResponse{Unknown: true}}, 171 {core.ReturnOperation, 4, NoopResponse{Unknown: true}}, 172 }, 173 }, 174 } 175 176 for i, cs := range cases { 177 compOps, err := CompleteOperations(cs.ops, NoopParser{}) 178 if err != nil { 179 t.Fatalf("err: %s, case %#v", err, cs) 180 } 181 for idx, op := range compOps { 182 if op != cs.compOps[idx] { 183 t.Fatalf("op %#v, compOps %#v, case %d", op, cs.compOps[idx], i) 184 } 185 } 186 } 187 }