From b18883989054a128a5a31d4099af2feed9adce8c Mon Sep 17 00:00:00 2001 From: Yvonnick Esnault Date: Wed, 8 Aug 2018 20:39:47 +0200 Subject: [PATCH] fix(venom): re-templating vars (#161) --- process_files.go | 4 ++-- process_testcase.go | 2 +- process_teststep.go | 17 +++++++++++++++++ templater.go | 32 ++++++++++++++++++-------------- tests/TestVars.yml | 25 +++++++++++++++++++++++++ venom_output.go | 5 ++++- 6 files changed, 67 insertions(+), 18 deletions(-) create mode 100644 tests/TestVars.yml diff --git a/process_files.go b/process_files.go index 95b37be1..aa26d5eb 100644 --- a/process_files.go +++ b/process_files.go @@ -80,9 +80,9 @@ func (v *Venom) readFiles(filesPath []string) (err error) { // Apply templater unitl there is no more modifications // it permits to include testcase from env - out := ts.Templater.apply(dat) + _, out := ts.Templater.apply(dat) for i := 0; i < 10; i++ { - tmp := ts.Templater.apply(out) + _, tmp := ts.Templater.apply(out) if string(tmp) == string(out) { break } diff --git a/process_testcase.go b/process_testcase.go index 2c85db84..e233075c 100644 --- a/process_testcase.go +++ b/process_testcase.go @@ -10,7 +10,7 @@ import ( func (v *Venom) initTestCaseContext(ts *TestSuite, tc *TestCase) (TestCaseContext, error) { var errContext error - tc.Context, errContext = ts.Templater.ApplyOnContext(tc.Context) + _, tc.Context, errContext = ts.Templater.ApplyOnMap(tc.Context) if errContext != nil { return nil, errContext } diff --git a/process_teststep.go b/process_teststep.go index 0b2d0135..4a16237a 100644 --- a/process_teststep.go +++ b/process_teststep.go @@ -4,6 +4,9 @@ import ( "context" "fmt" "time" + + dump "github.com/fsamin/go-dump" + log "github.com/sirupsen/logrus" ) //RunTestStep executes a venom testcase is a venom context @@ -38,6 +41,20 @@ func (v *Venom) RunTestStep(tcc TestCaseContext, e *ExecutorWrap, ts *TestSuite, // add result again for extracts values ts.Templater.Add(tc.Name, stringifyExecutorResult(result)) + // then template the TestSuite vars if needed + var applied bool + applied, ts.Vars, err = ts.Templater.ApplyOnMap(ts.Vars) + if err != nil { + log.Errorf("err:%s", err) + } + if applied { + d, err := dump.ToStringMap(ts.Vars) + if err != nil { + log.Errorf("err:%s", err) + } + ts.Templater.Add("", d) + } + if assertRes.ok { break } diff --git a/templater.go b/templater.go index 73fc9b16..5c8a827d 100644 --- a/templater.go +++ b/templater.go @@ -50,7 +50,7 @@ func (tmpl *Templater) ApplyOnStep(stepNumber int, step TestStep) (TestStep, err if stepNumber >= 0 { tmpl.Add("", map[string]string{"venom.teststep.number": fmt.Sprintf("%d", stepNumber)}) } - sb = tmpl.apply(s) + _, sb = tmpl.apply(s) } var t TestStep @@ -61,38 +61,42 @@ func (tmpl *Templater) ApplyOnStep(stepNumber int, step TestStep) (TestStep, err return t, nil } -//ApplyOnContext executes the template on a context -func (tmpl *Templater) ApplyOnContext(ctx map[string]interface{}) (map[string]interface{}, error) { +//ApplyOnMap executes the template on a context +// return true if there is an variable replaced +func (tmpl *Templater) ApplyOnMap(mapStringInterface map[string]interface{}) (bool, map[string]interface{}, error) { var t map[string]interface{} - if len(ctx) == 0 { - return t, nil + if len(mapStringInterface) == 0 { + return false, t, nil } // Using yaml to encode/decode, it generates map[interface{}]interface{} typed data that json does not like - s, err := yaml.Marshal(ctx) + s, err := yaml.Marshal(mapStringInterface) if err != nil { - return nil, fmt.Errorf("templater> Error while marshaling: %s", err) + return false, nil, fmt.Errorf("templater> Error while marshaling: %s", err) } sb := s - // if the context use some variable, we run tmpl.apply on it + var applied bool + // if the mapStringInterface use some variable, we run tmpl.apply on it if strings.Contains(string(s), "{{") { - sb = tmpl.apply(s) + applied, sb = tmpl.apply(s) } if err := yaml.Unmarshal([]byte(sb), &t); err != nil { - return nil, fmt.Errorf("templater> Error while unmarshal: %s, content:%s", err, sb) + return applied, nil, fmt.Errorf("templater> Error while unmarshal: %s, content:%s", err, sb) } - return t, nil + return applied, t, nil } -func (tmpl *Templater) apply(in []byte) []byte { +func (tmpl *Templater) apply(in []byte) (bool, []byte) { tmpl.Add("", map[string]string{ "venom.datetime": time.Now().Format(time.RFC3339), "venom.timestamp": fmt.Sprintf("%d", time.Now().Unix()), }) + var applied bool out := string(in) for k, v := range tmpl.Values { + applied = true var buffer bytes.Buffer buffer.WriteString("{{.") buffer.WriteString(k) @@ -100,8 +104,8 @@ func (tmpl *Templater) apply(in []byte) []byte { out = strings.Replace(out, buffer.String(), v, -1) // if no more variable to replace, exit if !strings.Contains(out, "{{") { - return []byte(out) + return applied, []byte(out) } } - return []byte(out) + return applied, []byte(out) } diff --git a/tests/TestVars.yml b/tests/TestVars.yml new file mode 100644 index 00000000..a6b5d2f6 --- /dev/null +++ b/tests/TestVars.yml @@ -0,0 +1,25 @@ +name: testVars + +vars: + service.id: '{{.CreateService.id}}' + thevar: 'thevalue' + +testcases: + +- name: CreateService + steps: + - type: exec + script: echo 'foo with a bar here' + assertions: + - result.code ShouldEqual 0 + - result.timeseconds ShouldBeLessThan 1 + extracts: + result.systemout: foo with a {{id=[a-z]+}} here + +- name: WriteServiceIdForNextTestSuites + steps: + - script: "echo 'value:{{.service.id}} - end value'" + assertions: + - result.code ShouldEqual 0 + - result.systemout ShouldContainSubstring bar + diff --git a/venom_output.go b/venom_output.go index 8ec92e73..38774f20 100644 --- a/venom_output.go +++ b/venom_output.go @@ -89,7 +89,10 @@ func (v *Venom) OutputResult(tests Tests, elapsed time.Duration) error { dumpEncoder.Fdump(f.Result) } - output := f.Value + "\n ------ \n" + sdump.String() + output := f.Value + "\n ------ Result: \n" + sdump.String() + "\n ------ Variables:\n" + for k, v := range ts.Templater.Values { + output += fmt.Sprintf("%s:%s\n", k, v) + } if err := ioutil.WriteFile(filename, []byte(output), 0644); err != nil { return fmt.Errorf("Error while creating file %s: %v", filename, err) }