Skip to content

Commit

Permalink
fix: user_executor inside user_executor (#380)
Browse files Browse the repository at this point in the history
close #371
fix display info from user executor

Signed-off-by: Yvonnick Esnault <[email protected]>
  • Loading branch information
yesnault authored Mar 5, 2021
1 parent 02751cc commit 019b1b5
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 23 deletions.
2 changes: 2 additions & 0 deletions dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func Dump(v interface{}) (map[string]interface{}, error) {
return e.ToMap(v)
}

// DumpString dumps v as a map[string]string{}, key in lowercase
func DumpString(v interface{}) (map[string]string, error) {
e := dump.NewDefaultEncoder()
e.ExtraFields.Len = true
Expand All @@ -26,6 +27,7 @@ func DumpString(v interface{}) (map[string]string, error) {
return e.ToStringMap(v)
}

// DumpStringPreserveCase dumps v as a map[string]string{}
func DumpStringPreserveCase(v interface{}) (map[string]string, error) {
e := dump.NewDefaultEncoder()
e.ExtraFields.Len = true
Expand Down
1 change: 1 addition & 0 deletions process_testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ func (v *Venom) parseTestCase(ts *TestSuite, tc *TestCase) ([]string, []string,

func (v *Venom) runTestCase(ctx context.Context, ts *TestSuite, tc *TestCase) {
ctx = context.WithValue(ctx, ContextKey("testcase"), tc.Name)
tc.TestSuiteVars = ts.Vars.Clone()
tc.Vars = ts.Vars.Clone()
tc.Vars.Add("venom.testcase", tc.Name)
tc.Vars.AddAll(ts.ComputedVars)
Expand Down
13 changes: 12 additions & 1 deletion process_teststep.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,18 @@ func (v *Venom) RunTestStep(ctx context.Context, e ExecutorRunner, tc *TestCase,
continue
}
filename := StringVarFromCtx(ctx, "venom.testsuite.filename")
info += fmt.Sprintf(" (%s:%d)", filename, findLineNumber(filename, tc.originalName, stepNumber, i, ninfo+1))
originalName := tc.originalName
lineNumber := findLineNumber(filename, tc.originalName, stepNumber, i, ninfo+1)
if lineNumber > 0 {
info += fmt.Sprintf(" (%s:%d)", filename, lineNumber)
} else if tc.IsExecutor {
filename = StringVarFromCtx(ctx, "venom.executor.filename")
originalName = StringVarFromCtx(ctx, "venom.executor.name")
lineNumber = findLineNumber(filename, originalName, stepNumber, i, ninfo+1)
}
if lineNumber > 0 {
info += fmt.Sprintf(" (%s:%d)", filename, lineNumber)
}
Info(ctx, info)
tc.computedInfo = append(tc.computedInfo, info)
}
Expand Down
2 changes: 0 additions & 2 deletions process_testsuite.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import (
log "github.com/sirupsen/logrus"
)

type ContextKey string

func (v *Venom) runTestSuite(ctx context.Context, ts *TestSuite) {
if v.Verbose == 3 {
var filename, filenameCPU, filenameMem string
Expand Down
2 changes: 1 addition & 1 deletion read_partial.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/pkg/errors"
)

func getUserExecutorPartialYML(ctx context.Context, btesIn []byte) (H, error) {
func getUserExecutorInputYML(ctx context.Context, btesIn []byte) (H, error) {
btes := readPartialYML(btesIn, "input")

var result = map[string]interface{}{}
Expand Down
10 changes: 10 additions & 0 deletions tests/lib/user_executor_A.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
executor: userExecutorA
input:
foo: defaultValueA
steps:
- script: echo '{{.input.foo}}'
info: 'value on A: {{.input.foo}}'
assertions:
- result.code ShouldEqual 0
- type: userExecutorB
foo: '{{.input.foo}}_on_b'
12 changes: 12 additions & 0 deletions tests/lib/user_executor_B.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
executor: userExecutorB
input:
foo: defaultValueB
steps:

- script: echo '{{.input.foo}}'
info: 'value on B: {{.input.foo}}'
- type: exec
script: echo 'input.foo {{.input.foo}}; fooFromEnv {{.foo}}'
assertions:
- result.code ShouldEqual 0
- result.systemout ShouldEqual input.foo foo_from_vars_on_b; fooFromEnv foo_from_vars
12 changes: 12 additions & 0 deletions tests/user_executor_many.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Many user executor
vars:
foo: "foo_from_vars"

testcases:
- name: info
steps:
- script: echo "foo"
info: 'value foo vars {{.foo}}'
- name: mytc
steps:
- type: userExecutorA
2 changes: 2 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,13 @@ type TestCase struct {
Time string `xml:"time,attr,omitempty" json:"time" yaml:"time,omitempty"`
RawTestSteps []json.RawMessage `xml:"-" json:"steps" yaml:"steps"`
testSteps []TestStep
TestSuiteVars H `xml:"-" json:"-" yaml:"-"`
Vars H `xml:"-" json:"-" yaml:"vars"`
computedVars H
computedInfo []string
computedVerbose []string
Skip []string `xml:"-" json:"skip" yaml:"skip"`
IsExecutor bool `xml:"-" json:"-" yaml:"-"`
}

// TestStep represents a testStep
Expand Down
19 changes: 14 additions & 5 deletions types_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,10 @@ type UserExecutor struct {
Input H `json:"input" yaml:"input"`
RawTestSteps []json.RawMessage `json:"steps" yaml:"steps"`
Output json.RawMessage `json:"output" yaml:"output"`
Filename string `json:"-" yaml:"-"`
}

// Run is not implemented on user executor
func (ux UserExecutor) Run(ctx context.Context, step TestStep) (interface{}, error) {
return nil, errors.New("Run not implemented for user interface, use RunUserExecutor instead")
}
Expand All @@ -172,11 +174,14 @@ func (ux UserExecutor) ZeroValueResult() interface{} {
}

func (v *Venom) RunUserExecutor(ctx context.Context, runner ExecutorRunner, tcIn *TestCase, step TestStep) (interface{}, error) {
vrs := H{}
vrs := tcIn.TestSuiteVars.Clone()
uxIn := runner.GetExecutor().(UserExecutor)

for k, va := range uxIn.Input {
if !strings.HasPrefix(k, "venom") {
if strings.HasPrefix(k, "input.") {
// do not reinject input.vars from parent user executor if exists
continue
} else if !strings.HasPrefix(k, "venom") {
if vl, ok := step[k]; ok && vl != "" { // value from step
vrs.AddWithPrefix("input", k, vl)
} else { // default value from executor
Expand All @@ -191,14 +196,18 @@ func (v *Venom) RunUserExecutor(ctx context.Context, runner ExecutorRunner, tcIn
ux := exe.GetExecutor().(UserExecutor)

tc := &TestCase{
Name: ux.Executor,
RawTestSteps: ux.RawTestSteps,
Vars: vrs,
Name: ux.Executor,
RawTestSteps: ux.RawTestSteps,
Vars: vrs,
TestSuiteVars: tcIn.TestSuiteVars,
IsExecutor: true,
}

tc.originalName = tc.Name
tc.Name = slug.Make(tc.Name)
tc.Vars.Add("venom.testcase", tc.Name)
tc.Vars.Add("venom.executor.filename", ux.Filename)
tc.Vars.Add("venom.executor.name", ux.Executor)
tc.computedVars = H{}

Debug(ctx, "running user executor %v", tc.Name)
Expand Down
32 changes: 18 additions & 14 deletions venom.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ var (
Version = "snapshot"
)

// ContextKey can be added in context to store contextual infos. Also used by logger.
type ContextKey string

// New instanciates a new venom on venom run cmd
func New() *Venom {
v := &Venom{
LogOutput: os.Stdout,
Expand Down Expand Up @@ -93,25 +97,25 @@ func (v *Venom) RegisterExecutorUser(name string, e Executor) {

// GetExecutorRunner initializes a test by name
// no type -> exec is default
func (v *Venom) GetExecutorRunner(ctx context.Context, t TestStep, h H) (context.Context, ExecutorRunner, error) {
name, _ := t.StringValue("type")
func (v *Venom) GetExecutorRunner(ctx context.Context, ts TestStep, h H) (context.Context, ExecutorRunner, error) {
name, _ := ts.StringValue("type")
if name == "" {
name = "exec"
}
retry, err := t.IntValue("retry")
retry, err := ts.IntValue("retry")
if err != nil {
return nil, nil, err
}
delay, err := t.IntValue("delay")
delay, err := ts.IntValue("delay")
if err != nil {
return nil, nil, err
}
timeout, err := t.IntValue("timeout")
timeout, err := ts.IntValue("timeout")
if err != nil {
return nil, nil, err
}

info, _ := t.StringSliceValue("info")
info, _ := ts.StringSliceValue("info")
vars, err := DumpStringPreserveCase(h)
if err != nil {
return ctx, nil, err
Expand All @@ -128,7 +132,7 @@ func (v *Venom) GetExecutorRunner(ctx context.Context, t TestStep, h H) (context
return ctx, newExecutorRunner(ex, name, "builtin", retry, delay, timeout, info), nil
}

if err := v.registerUserExecutors(ctx, name, vars); err != nil {
if err := v.registerUserExecutors(ctx, name, ts, vars); err != nil {
Debug(ctx, "executor %q is not implemented as user executor - err:%v", name, err)
}

Expand Down Expand Up @@ -175,7 +179,7 @@ func (v *Venom) getUserExecutorFilesPath(vars map[string]string) (filePaths []st
return filePaths, nil
}

func (v *Venom) registerUserExecutors(ctx context.Context, name string, vars map[string]string) error {
func (v *Venom) registerUserExecutors(ctx context.Context, name string, ts TestStep, vars map[string]string) error {
executorsPath, err := v.getUserExecutorFilesPath(vars)
if err != nil {
return err
Expand All @@ -188,13 +192,13 @@ func (v *Venom) registerUserExecutors(ctx context.Context, name string, vars map
return errors.Wrapf(err, "unable to read file %q", f)
}

varsFromPartial, err := getUserExecutorPartialYML(ctx, btes)
varsFromInput, err := getUserExecutorInputYML(ctx, btes)
if err != nil {
return err
}

// varsFromPartial contains the default vars from the executor
varsFromPartialMap, err := DumpStringPreserveCase(varsFromPartial)
// varsFromInput contains the default vars from the executor
varsFromInputMap, err := DumpStringPreserveCase(varsFromInput)
if err != nil {
return errors.Wrapf(err, "unable to parse variables")
}
Expand All @@ -203,8 +207,8 @@ func (v *Venom) registerUserExecutors(ctx context.Context, name string, vars map
for k, v := range vars {
varsComputed[k] = v
}
for k, v := range varsFromPartialMap {
// we only take vars from varsFromPartialMap if it's not already exist in vars from arg
for k, v := range varsFromInputMap {
// we only take vars from varsFromInputMap if it's not already exist in vars from teststep vars
if _, ok := vars[k]; !ok {
varsComputed[k] = v
}
Expand All @@ -215,7 +219,7 @@ func (v *Venom) registerUserExecutors(ctx context.Context, name string, vars map
return err
}

ux := UserExecutor{}
ux := UserExecutor{Filename: f}
if err := yaml.Unmarshal([]byte(content), &ux); err != nil {
return errors.Wrapf(err, "unable to parse file %q", f)
}
Expand Down

0 comments on commit 019b1b5

Please sign in to comment.