From f6a51e7ff1acb8a5c5186e27f60d653f883b6f9b Mon Sep 17 00:00:00 2001 From: Paul Andersen Date: Sun, 25 Aug 2024 14:43:25 -0500 Subject: [PATCH] fix issue #34, add stepDefs mutex and lock in appropriate places to prevent races --- find_step.go | 23 ++++++++++++++++++----- runner.go | 3 +++ step_def.go | 9 ++++++--- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/find_step.go b/find_step.go index 361c664..bf09d24 100644 --- a/find_step.go +++ b/find_step.go @@ -9,11 +9,11 @@ import ( func (r *Runner) findStep(t *testing.T, step *messages.PickleStep) *stepDef { t.Helper() - for _, def := range r.stepDefs { - matches := def.regex.FindSubmatch([]byte(step.Text)) - if len(matches) != 0 { - return def - } + r.stepDefsMutex.RLock() + def := findSubmatch(t, step.Text, r.stepDefs) + r.stepDefsMutex.RUnlock() + if def != nil { + return def } sig := guessMethodSig(step) @@ -30,3 +30,16 @@ func (r *Runner) findStep(t *testing.T, step *messages.PickleStep) *stepDef { return nil } + +func findSubmatch(t *testing.T, stepText string, stepDefs []*stepDef) *stepDef { + t.Helper() + + for _, def := range stepDefs { + matches := def.regex.FindSubmatch([]byte(stepText)) + if len(matches) != 0 { + return def + } + } + + return nil +} \ No newline at end of file diff --git a/runner.go b/runner.go index 2795328..4a848d9 100644 --- a/runner.go +++ b/runner.go @@ -2,6 +2,7 @@ package gocuke import ( "reflect" + "sync" "testing" messages "github.com/cucumber/messages/go/v22" @@ -17,6 +18,7 @@ type Runner struct { paths []string parallel bool stepDefs []*stepDef + stepDefsMutex *sync.RWMutex haveSuggestion map[string]bool suggestions []methodSig supportedSpecialArgs map[reflect.Type]specialArgGetter @@ -84,6 +86,7 @@ func NewRunner(t *testing.T, suiteType interface{}) *Runner { }, }, suiteUsesRapid: false, + stepDefsMutex: &sync.RWMutex{}, } r.registerSuite(suiteType) diff --git a/step_def.go b/step_def.go index a3446a1..6de8f3a 100644 --- a/step_def.go +++ b/step_def.go @@ -5,6 +5,7 @@ import ( "reflect" "regexp" "runtime" + "sync" "testing" "gotest.tools/v3/assert" @@ -54,7 +55,9 @@ func (r *Runner) Step(step interface{}, definition interface{}) *Runner { func (r *Runner) addStepDef(t *testing.T, exp *regexp.Regexp, definition reflect.Value) *stepDef { t.Helper() + defer r.stepDefsMutex.Unlock() + r.stepDefsMutex.Lock() def := r.newStepDefOrHook(t, exp, definition) r.stepDefs = append(r.stepDefs, def) return def @@ -73,9 +76,9 @@ func (r *Runner) newStepDefOrHook(t *testing.T, exp *regexp.Regexp, f reflect.Va file, line := rfunc.FileLine(funcPtr) def := &stepDef{ - regex: exp, - theFunc: f, - funcLoc: fmt.Sprintf("%s (%s:%d)", rfunc.Name(), file, line), + regex: exp, + theFunc: f, + funcLoc: fmt.Sprintf("%s (%s:%d)", rfunc.Name(), file, line), } for i := 0; i < typ.NumIn(); i++ {