diff --git a/cmd/run.go b/cmd/run.go index 292f24ea..a72a96f6 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "path" "path/filepath" "strings" "sync" @@ -218,6 +219,7 @@ func (o *runOption) runSuite(suite string, dataContext map[string]interface{}, c o.limiter.Accept() ctxWithTimeout, _ := context.WithTimeout(ctx, o.requestTimeout) + ctxWithTimeout = context.WithValue(ctxWithTimeout, runner.ContextKey("").ParentDir(), path.Dir(suite)) simpleRunner := runner.NewSimpleTestCaseRunner() simpleRunner.WithTestReporter(o.reporter) diff --git a/go.mod b/go.mod index 1c2052e3..b4cd4714 100644 --- a/go.mod +++ b/go.mod @@ -44,6 +44,6 @@ require ( golang.org/x/text v0.8.0 // indirect google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect google.golang.org/protobuf v1.30.0 // indirect - gopkg.in/yaml.v2 v2.3.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 257c9212..523adeb1 100644 --- a/go.sum +++ b/go.sum @@ -41,10 +41,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/linuxsuren/go-fake-runtime v0.0.0-20230413085645-15e77ab55dbd h1:2Avir30WOgcDqG3sA4hlW4bC4c/tgseAUntPhf5JQ6E= -github.com/linuxsuren/go-fake-runtime v0.0.0-20230413085645-15e77ab55dbd/go.mod h1:zmh6J78hSnWZo68faMA2eKOdaEp8eFbERHi3ZB9xHCQ= -github.com/linuxsuren/go-fake-runtime v0.0.0-20230426143116-85f55baf088f h1:QvE5qCxn6uNxIpF4dnX8O172J12+iOFBcmQ52rvhFFU= -github.com/linuxsuren/go-fake-runtime v0.0.0-20230426143116-85f55baf088f/go.mod h1:zmh6J78hSnWZo68faMA2eKOdaEp8eFbERHi3ZB9xHCQ= github.com/linuxsuren/go-fake-runtime v0.0.0-20230426144714-1a7a0d160d3f h1:TfAzkLxq/agwMBbccTx/f/dlmFWIBLWRGCWjI4IOlK8= github.com/linuxsuren/go-fake-runtime v0.0.0-20230426144714-1a7a0d160d3f/go.mod h1:zmh6J78hSnWZo68faMA2eKOdaEp8eFbERHi3ZB9xHCQ= github.com/linuxsuren/unstructured v0.0.1 h1:ilUA8MUYbR6l9ebo/YPV2bKqlf62bzQursDSE+j00iU= @@ -137,8 +133,9 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/runner/simple.go b/pkg/runner/simple.go index 9461200b..f6a0da6b 100644 --- a/pkg/runner/simple.go +++ b/pkg/runner/simple.go @@ -168,6 +168,27 @@ func NewSimpleTestCaseRunner() TestCaseRunner { WithExecer(fakeruntime.DefaultExecer{}) } +// ContextKey is the alias type of string for context key +type ContextKey string + +// NewContextKeyBuilder returns an emtpy context key +func NewContextKeyBuilder() ContextKey { + return ContextKey("") +} + +// ParentDir returns the key of the parsent directory +func (c ContextKey) ParentDir() ContextKey { + return ContextKey("parentDir") +} + +// GetContextValueOrEmpty returns the value of the context key, if not exist, return empty string +func (c ContextKey) GetContextValueOrEmpty(ctx context.Context) string { + if ctx.Value(c) != nil { + return ctx.Value(c).(string) + } + return "" +} + // RunTestCase is the main entry point of a test case func (r *simpleTestCaseRunner) RunTestCase(testcase *testing.TestCase, dataContext interface{}, ctx context.Context) (output interface{}, err error) { r.log.Info("start to run: '%s'\n", testcase.Name) @@ -196,7 +217,8 @@ func (r *simpleTestCaseRunner) RunTestCase(testcase *testing.TestCase, dataConte }, } - if err = testcase.Request.Render(dataContext); err != nil { + contextDir := NewContextKeyBuilder().ParentDir().GetContextValueOrEmpty(ctx) + if err = testcase.Request.Render(dataContext, contextDir); err != nil { return } diff --git a/pkg/runner/simple_test.go b/pkg/runner/simple_test.go index 1e217297..4132de51 100644 --- a/pkg/runner/simple_test.go +++ b/pkg/runner/simple_test.go @@ -219,25 +219,25 @@ func TestTestCase(t *testing.T) { assert.Contains(t, err.Error(), "failed to get field") }, }, - // { - // name: "verify failed", - // testCase: &atest.TestCase{ - // Request: atest.Request{ - // API: urlFoo, - // }, - // Expect: atest.Response{ - // Verify: []string{ - // "len(data.items) > 0", - // }, - // }, - // }, - // prepare: defaultPrepare, - // verify: func(t *testing.T, output interface{}, err error) { - // if assert.NotNil(t, err) { - // assert.Contains(t, err.Error(), "failed to verify") - // } - // }, - // }, + { + name: "verify failed", + testCase: &atest.TestCase{ + Request: atest.Request{ + API: urlFoo, + }, + Expect: atest.Response{ + Verify: []string{ + "len(data.items) > 0", + }, + }, + }, + prepare: defaultPrepare, + verify: func(t *testing.T, output interface{}, err error) { + if assert.NotNil(t, err) { + assert.Contains(t, err.Error(), "failed to verify") + } + }, + }, { name: "failed to compile", testCase: &atest.TestCase{ @@ -437,6 +437,14 @@ func TestRunJob(t *testing.T) { } } +func TestContextKey(t *testing.T) { + assert.Equal(t, ContextKey("parentDir"), NewContextKeyBuilder().ParentDir()) + + ctx := context.WithValue(context.Background(), NewContextKeyBuilder().ParentDir(), "/tmp") + assert.Equal(t, "/tmp", NewContextKeyBuilder().ParentDir().GetContextValueOrEmpty(ctx)) + assert.Empty(t, ContextKey("fake").GetContextValueOrEmpty(ctx)) +} + const defaultSchemaForTest = `{"properties": { "name": {"type": "string"}, "age": {"type": "integer"} diff --git a/pkg/testing/parser.go b/pkg/testing/parser.go index 182d16e4..ffc9936f 100644 --- a/pkg/testing/parser.go +++ b/pkg/testing/parser.go @@ -8,6 +8,7 @@ import ( "net/http" "net/url" "os" + "path" "strings" "github.com/ghodss/yaml" @@ -70,7 +71,7 @@ func ParseTestCaseFromData(data []byte) (testCase *TestCase, err error) { } // Render injects the template based context -func (r *Request) Render(ctx interface{}) (err error) { +func (r *Request) Render(ctx interface{}, dataDir string) (err error) { // template the API var result string if result, err = render.Render("api", r.API, ctx); err == nil { @@ -83,7 +84,7 @@ func (r *Request) Render(ctx interface{}) (err error) { // read body from file if r.BodyFromFile != "" { var data []byte - if data, err = os.ReadFile(r.BodyFromFile); err != nil { + if data, err = os.ReadFile(path.Join(dataDir, r.BodyFromFile)); err != nil { return } r.Body = strings.TrimSpace(string(data)) diff --git a/pkg/testing/parser_test.go b/pkg/testing/parser_test.go index b506f4e7..b2d56635 100644 --- a/pkg/testing/parser_test.go +++ b/pkg/testing/parser_test.go @@ -151,7 +151,7 @@ func TestRequestRender(t *testing.T) { }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := tt.request.Render(tt.ctx) + err := tt.request.Render(tt.ctx, "") if assert.Equal(t, tt.hasErr, err != nil, err) && tt.verify != nil { tt.verify(t, tt.request) }