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 }