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  }