github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/fsm/match_test.go (about)

     1  // Copyright 2017 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 fsm
    12  
    13  import (
    14  	"testing"
    15  
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func TestMatchPattern(t *testing.T) {
    20  	// No expansion patterns.
    21  	p1 := expandPattern(Pattern{
    22  		state1{}: {
    23  			event1{}: {state2{}, noAction, ""},
    24  		},
    25  		state2{}: {
    26  			event1{}: {state1{}, noAction, ""},
    27  			event2{}: {state2{}, noAction, ""},
    28  		},
    29  	})
    30  	require.Equal(t, len(p1), 2)
    31  	require.Equal(t, len(p1[state1{}]), 1)
    32  	require.Equal(t, len(p1[state2{}]), 2)
    33  	require.Equal(t, len(p1[state3{}]), 0)
    34  
    35  	// State expansion match patterns.
    36  	p2 := expandPattern(Pattern{
    37  		state3{True}: {
    38  			event1{}: {state2{}, noAction, ""},
    39  		},
    40  	})
    41  	require.Equal(t, len(p2), 1)
    42  	require.Equal(t, len(p2[state1{}]), 0)
    43  	require.Equal(t, len(p2[state3{True}]), 1)
    44  	require.Equal(t, len(p2[state3{False}]), 0)
    45  
    46  	p3 := expandPattern(Pattern{
    47  		state3{False}: {
    48  			event1{}: {state2{}, noAction, ""},
    49  		},
    50  	})
    51  	require.Equal(t, len(p3), 1)
    52  	require.Equal(t, len(p3[state1{}]), 0)
    53  	require.Equal(t, len(p3[state3{True}]), 0)
    54  	require.Equal(t, len(p3[state3{False}]), 1)
    55  
    56  	p4 := expandPattern(Pattern{
    57  		state3{Any}: {
    58  			event1{}: {state2{}, noAction, ""},
    59  		},
    60  	})
    61  	require.Equal(t, len(p4), 2)
    62  	require.Equal(t, len(p4[state1{}]), 0)
    63  	require.Equal(t, len(p4[state3{True}]), 1)
    64  	require.Equal(t, len(p4[state3{False}]), 1)
    65  
    66  	p5 := expandPattern(Pattern{
    67  		state4{Any, True}: {
    68  			event1{}: {state2{}, noAction, ""},
    69  		},
    70  	})
    71  	require.Equal(t, len(p5), 2)
    72  	require.Equal(t, len(p5[state1{}]), 0)
    73  	require.Equal(t, len(p5[state3{}]), 0)
    74  	require.Equal(t, len(p5[state4{True, True}]), 1)
    75  	require.Equal(t, len(p5[state4{True, False}]), 0)
    76  	require.Equal(t, len(p5[state4{False, True}]), 1)
    77  	require.Equal(t, len(p5[state4{False, False}]), 0)
    78  
    79  	p6 := expandPattern(Pattern{
    80  		state4{False, Any}: {
    81  			event1{}: {state2{}, noAction, ""},
    82  		},
    83  	})
    84  	require.Equal(t, len(p6), 2)
    85  	require.Equal(t, len(p6[state1{}]), 0)
    86  	require.Equal(t, len(p6[state3{}]), 0)
    87  	require.Equal(t, len(p6[state4{True, True}]), 0)
    88  	require.Equal(t, len(p6[state4{True, False}]), 0)
    89  	require.Equal(t, len(p6[state4{False, True}]), 1)
    90  	require.Equal(t, len(p6[state4{False, False}]), 1)
    91  
    92  	p7 := expandPattern(Pattern{
    93  		state4{Any, Any}: {
    94  			event1{}: {state2{}, noAction, ""},
    95  		},
    96  	})
    97  	require.Equal(t, len(p7), 4)
    98  	require.Equal(t, len(p7[state1{}]), 0)
    99  	require.Equal(t, len(p7[state3{}]), 0)
   100  	require.Equal(t, len(p7[state4{True, True}]), 1)
   101  	require.Equal(t, len(p7[state4{True, False}]), 1)
   102  	require.Equal(t, len(p7[state4{False, True}]), 1)
   103  	require.Equal(t, len(p7[state4{False, False}]), 1)
   104  
   105  	// Event expansion match patterns.
   106  	p8 := expandPattern(Pattern{
   107  		state1{}: {
   108  			event3{True}: {state2{}, noAction, ""},
   109  		},
   110  		state2{}: {
   111  			event3{Any}: {state2{}, noAction, ""},
   112  		},
   113  	})
   114  	require.Equal(t, len(p8), 2)
   115  	require.Equal(t, len(p8[state1{}]), 1)
   116  	require.Equal(t, len(p8[state2{}]), 2)
   117  
   118  	p9 := expandPattern(Pattern{
   119  		state1{}: {
   120  			event4{True, Any}: {state2{}, noAction, ""},
   121  		},
   122  		state2{}: {
   123  			event4{Any, Any}: {state2{}, noAction, ""},
   124  		},
   125  	})
   126  	require.Equal(t, len(p9), 2)
   127  	require.Equal(t, len(p9[state1{}]), 2)
   128  	require.Equal(t, len(p9[state2{}]), 4)
   129  
   130  	// State and Event expansion match patterns.
   131  	p10 := expandPattern(Pattern{
   132  		state3{Any}: {
   133  			event4{Any, Any}: {state2{}, noAction, ""},
   134  		},
   135  		state4{Any, True}: {
   136  			event3{Any}: {state2{}, noAction, ""},
   137  		},
   138  	})
   139  	require.Equal(t, len(p10), 4)
   140  	require.Equal(t, len(p10[state3{True}]), 4)
   141  	require.Equal(t, len(p10[state3{False}]), 4)
   142  	require.Equal(t, len(p10[state4{True, True}]), 2)
   143  	require.Equal(t, len(p10[state4{True, False}]), 0)
   144  	require.Equal(t, len(p10[state4{False, True}]), 2)
   145  	require.Equal(t, len(p10[state4{False, False}]), 0)
   146  }
   147  
   148  func TestMatchVariableVar(t *testing.T) {
   149  	p := expandPattern(Pattern{
   150  		state3{Var("a")}: {
   151  			event3{Var("b")}: {state4{Var("b"), Var("a")}, noAction, ""},
   152  		},
   153  	})
   154  
   155  	require.Equal(t, len(p), 2)
   156  	require.Equal(t, len(p[state3{True}]), 2)
   157  	require.Equal(t, len(p[state3{False}]), 2)
   158  	require.Equal(t, p[state3{True}][event3{True}].Next, state4{True, True})
   159  	require.Equal(t, p[state3{True}][event3{False}].Next, state4{False, True})
   160  	require.Equal(t, p[state3{False}][event3{True}].Next, state4{True, False})
   161  	require.Equal(t, p[state3{False}][event3{False}].Next, state4{False, False})
   162  }
   163  
   164  func TestInvalidPattern(t *testing.T) {
   165  	// Patterns not-mutually exclusive.
   166  	require.Panics(t, func() {
   167  		expandPattern(Pattern{
   168  			state3{Any}: {
   169  				event1{}: {state2{}, noAction, ""},
   170  			},
   171  			state3{True}: {
   172  				event1{}: {state2{}, noAction, ""},
   173  			},
   174  		})
   175  	})
   176  	require.Panics(t, func() {
   177  		expandPattern(Pattern{
   178  			state4{Any, True}: {
   179  				event1{}: {state2{}, noAction, ""},
   180  			},
   181  			state4{False, Any}: {
   182  				event1{}: {state2{}, noAction, ""},
   183  			},
   184  		})
   185  	})
   186  	require.Panics(t, func() {
   187  		expandPattern(Pattern{
   188  			state1{}: {
   189  				event3{Any}:  {state2{}, noAction, ""},
   190  				event3{True}: {state2{}, noAction, ""},
   191  			},
   192  		})
   193  	})
   194  	require.Panics(t, func() {
   195  		expandPattern(Pattern{
   196  			state1{}: {
   197  				event4{Any, False}: {state2{}, noAction, ""},
   198  				event4{True, Any}:  {state2{}, noAction, ""},
   199  			},
   200  		})
   201  	})
   202  
   203  	// Same binding multiple times in pattern.
   204  	require.Panics(t, func() {
   205  		expandPattern(Pattern{
   206  			state3{Var("a")}: {
   207  				event3{Var("a")}: {state2{}, noAction, ""},
   208  			},
   209  		})
   210  	})
   211  	require.Panics(t, func() {
   212  		expandPattern(Pattern{
   213  			state4{Var("a"), Var("a")}: {
   214  				event1{}: {state2{}, noAction, ""},
   215  			},
   216  		})
   217  	})
   218  	require.Panics(t, func() {
   219  		expandPattern(Pattern{
   220  			state1{}: {
   221  				event4{Var("a"), Var("a")}: {state2{}, noAction, ""},
   222  			},
   223  		})
   224  	})
   225  
   226  	// Nil states and events.
   227  	require.Panics(t, func() {
   228  		expandPattern(Pattern{
   229  			nil: {
   230  				event1{}: {state1{}, noAction, ""},
   231  			},
   232  		})
   233  	})
   234  	require.Panics(t, func() {
   235  		expandPattern(Pattern{
   236  			state1{}: {
   237  				nil: {state1{}, noAction, ""},
   238  			},
   239  		})
   240  	})
   241  	require.Panics(t, func() {
   242  		expandPattern(Pattern{
   243  			state1{}: {
   244  				event1{}: {nil, noAction, ""},
   245  			},
   246  		})
   247  	})
   248  
   249  	// Nil variables.
   250  	require.Panics(t, func() {
   251  		expandPattern(Pattern{
   252  			state3{nil}: {
   253  				event1{}: {state1{}, noAction, ""},
   254  			},
   255  		})
   256  	})
   257  	require.Panics(t, func() {
   258  		expandPattern(Pattern{
   259  			state1{}: {
   260  				event3{nil}: {state1{}, noAction, ""},
   261  			},
   262  		})
   263  	})
   264  	require.Panics(t, func() {
   265  		expandPattern(Pattern{
   266  			state1{}: {
   267  				event1{}: {state3{nil}, noAction, ""},
   268  			},
   269  		})
   270  	})
   271  
   272  	// Binding not found.
   273  	require.Panics(t, func() {
   274  		expandPattern(Pattern{
   275  			state1{}: {
   276  				event3{Var("a")}: {state3{Var("b")}, noAction, ""},
   277  			},
   278  		})
   279  	})
   280  
   281  	// Wildcard in expression.
   282  	require.Panics(t, func() {
   283  		expandPattern(Pattern{
   284  			state1{}: {
   285  				event1{}: {state3{Any}, noAction, ""},
   286  			},
   287  		})
   288  	})
   289  }
   290  
   291  func TestFromBool(t *testing.T) {
   292  	if !FromBool(true).Get() {
   293  		t.Fatalf("conversion failed")
   294  	}
   295  	if FromBool(false).Get() {
   296  		t.Fatalf("conversion failed")
   297  	}
   298  }