Skip to content

Commit

Permalink
feat: adding resource loader interface and default implement (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
LinuxSuRen authored Jun 18, 2023
1 parent 5a3b114 commit d564f69
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 89 deletions.
12 changes: 9 additions & 3 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,28 @@ import (

"github.com/stretchr/testify/assert"

exec "github.com/linuxsuren/go-fake-runtime"
fakeruntime "github.com/linuxsuren/go-fake-runtime"
)

func TestCreateRunCommand(t *testing.T) {
cmd := createRunCommand()
assert.Equal(t, "run", cmd.Use)

init := createInitCommand(exec.FakeExecer{})
init := createInitCommand(fakeruntime.FakeExecer{})
assert.Equal(t, "init", init.Use)

server := createServerCmd(&fakeGRPCServer{})
assert.NotNil(t, server)
assert.Equal(t, "server", server.Use)

root := NewRootCmd(exec.FakeExecer{}, NewFakeGRPCServer())
root := NewRootCmd(fakeruntime.FakeExecer{}, NewFakeGRPCServer())
root.SetArgs([]string{"init", "-k=demo.yaml", "--wait-namespace", "demo", "--wait-resource", "demo"})
err := root.Execute()
assert.Nil(t, err)
}

func TestRootCmd(t *testing.T) {
c := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"}, NewFakeGRPCServer())
assert.NotNil(t, c)
assert.Equal(t, "atest", c.Use)
}
38 changes: 19 additions & 19 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"fmt"
"io"
"os"
"path"
"path/filepath"
"strings"
"sync"
"time"
Expand All @@ -16,7 +14,6 @@ import (
"github.com/linuxsuren/api-testing/pkg/render"
"github.com/linuxsuren/api-testing/pkg/runner"
"github.com/linuxsuren/api-testing/pkg/testing"
"github.com/linuxsuren/api-testing/pkg/util"
"github.com/spf13/cobra"
"golang.org/x/sync/semaphore"
)
Expand All @@ -40,12 +37,16 @@ type runOption struct {
swaggerURL string
level string
caseItems []string

// for internal use
loader testing.Loader
}

func newDefaultRunOption() *runOption {
return &runOption{
reporter: runner.NewMemoryTestReporter(),
reportWriter: runner.NewResultWriter(os.Stdout),
loader: testing.NewFileLoader(),
}
}

Expand Down Expand Up @@ -134,19 +135,13 @@ func (o *runOption) runE(cmd *cobra.Command, args []string) (err error) {
o.limiter.Stop()
}()

var suites []string
for _, pattern := range util.Expand(o.pattern) {
var files []string
if files, err = filepath.Glob(pattern); err == nil {
suites = append(suites, files...)
}
if err = o.loader.Put(o.pattern); err != nil {
return
}

cmd.Println("found suites:", len(suites))
for i := range suites {
item := suites[i]
cmd.Println("run suite:", item)
if err = o.runSuiteWithDuration(item); err != nil {
cmd.Println("found suites:", o.loader.GetCount())
for o.loader.HasMore() {
if err = o.runSuiteWithDuration(o.loader); err != nil {
break
}
}
Expand All @@ -166,7 +161,7 @@ func (o *runOption) runE(cmd *cobra.Command, args []string) (err error) {
return
}

func (o *runOption) runSuiteWithDuration(suite string) (err error) {
func (o *runOption) runSuiteWithDuration(loader testing.Loader) (err error) {
sem := semaphore.NewWeighted(o.thread)
stop := false
var timeout *time.Ticker
Expand Down Expand Up @@ -204,7 +199,7 @@ func (o *runOption) runSuiteWithDuration(suite string) (err error) {
}()

dataContext := getDefaultContext()
ch <- o.runSuite(suite, dataContext, o.context, stopSingal)
ch <- o.runSuite(loader, dataContext, o.context, stopSingal)
}(errChannel, sem)
if o.duration <= 0 {
stop = true
Expand All @@ -221,9 +216,14 @@ func (o *runOption) runSuiteWithDuration(suite string) (err error) {
return
}

func (o *runOption) runSuite(suite string, dataContext map[string]interface{}, ctx context.Context, stopSingal chan struct{}) (err error) {
func (o *runOption) runSuite(loader testing.Loader, dataContext map[string]interface{}, ctx context.Context, stopSingal chan struct{}) (err error) {
var data []byte
if data, err = loader.Load(); err != nil {
return
}

var testSuite *testing.TestSuite
if testSuite, err = testing.Parse(suite); err != nil {
if testSuite, err = testing.Parse(data); err != nil {
return
}

Expand Down Expand Up @@ -253,7 +253,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))
ctxWithTimeout = context.WithValue(ctxWithTimeout, runner.ContextKey("").ParentDir(), loader.GetContext())

simpleRunner := runner.NewSimpleTestCaseRunner()
simpleRunner.WithTestReporter(o.reporter)
Expand Down
22 changes: 13 additions & 9 deletions cmd/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (

"github.com/h2non/gock"
"github.com/linuxsuren/api-testing/pkg/limit"
atest "github.com/linuxsuren/api-testing/pkg/testing"
"github.com/linuxsuren/api-testing/pkg/util"
fakeruntime "github.com/linuxsuren/go-fake-runtime"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -58,8 +58,13 @@ func TestRunSuite(t *testing.T) {
opt.limiter = limit.NewDefaultRateLimiter(0, 0)
stopSingal := make(chan struct{}, 1)

err := opt.runSuite(tt.suiteFile, ctx, context.TODO(), stopSingal)
assert.Equal(t, tt.hasError, err != nil, err)
loader := atest.NewFileLoader()
err := loader.Put(tt.suiteFile)
assert.NoError(t, err)
if loader.HasMore() {
err = opt.runSuite(loader, ctx, context.TODO(), stopSingal)
assert.Equal(t, tt.hasError, err != nil, err)
}
})
}
}
Expand Down Expand Up @@ -128,6 +133,11 @@ func TestRunCommand(t *testing.T) {
prepare: fooPrepare,
args: []string{"-p", simpleSuite, "--report", "md", "--report-file", path.Join(tmpFile.Name(), "fake")},
hasErr: true,
}, {
name: "malformed report file path",
prepare: fooPrepare,
args: []string{"-p", "[]]$#%*^&()"},
hasErr: true,
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -146,12 +156,6 @@ func TestRunCommand(t *testing.T) {
}
}

func TestRootCmd(t *testing.T) {
c := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"}, NewFakeGRPCServer())
assert.NotNil(t, c)
assert.Equal(t, "atest", c.Use)
}

func TestPreRunE(t *testing.T) {
tests := []struct {
name string
Expand Down
10 changes: 10 additions & 0 deletions pkg/testing/loader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package testing

// Loader is an interface for test cases loader
type Loader interface {
HasMore() bool
Load() ([]byte, error)
Put(string) (err error)
GetContext() string
GetCount() int
}
52 changes: 52 additions & 0 deletions pkg/testing/loader_file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package testing

import (
"os"
"path"
"path/filepath"

"github.com/linuxsuren/api-testing/pkg/util"
)

type fileLoader struct {
paths []string
index int
}

// NewFileLoader creates the instance of file loader
func NewFileLoader() Loader {
return &fileLoader{index: -1}
}

// HasMore returns if there are more test cases
func (l *fileLoader) HasMore() bool {
l.index++
return l.index < len(l.paths)
}

// Load returns the test case content
func (l *fileLoader) Load() (data []byte, err error) {
data, err = os.ReadFile(l.paths[l.index])
return
}

// Put adds the test case path
func (l *fileLoader) Put(item string) (err error) {
for _, pattern := range util.Expand(item) {
var files []string
if files, err = filepath.Glob(pattern); err == nil {
l.paths = append(l.paths, files...)
}
}
return
}

// GetContext returns the context of current test case
func (l *fileLoader) GetContext() string {
return path.Dir(l.paths[l.index])
}

// GetCount returns the count of test cases
func (l *fileLoader) GetCount() int {
return len(l.paths)
}
56 changes: 56 additions & 0 deletions pkg/testing/loader_file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package testing_test

import (
"testing"

atest "github.com/linuxsuren/api-testing/pkg/testing"
"github.com/stretchr/testify/assert"
)

func TestFileLoader(t *testing.T) {
tests := []struct {
name string
items []string
verify func(t *testing.T, loader atest.Loader)
}{{
name: "empty",
items: []string{},
verify: func(t *testing.T, loader atest.Loader) {
assert.False(t, loader.HasMore())
assert.Empty(t, loader.GetCount())
},
}, {
name: "brace expansion path",
items: []string{"testdata/{invalid-,}testcase.yaml"},
verify: defaultVerify,
}, {
name: "glob path",
items: []string{"testdata/*testcase.yaml"},
verify: defaultVerify,
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
loader := atest.NewFileLoader()
for _, item := range tt.items {
loader.Put(item)
}
tt.verify(t, loader)
})
}
}

func defaultVerify(t *testing.T, loader atest.Loader) {
assert.True(t, loader.HasMore())
data, err := loader.Load()
assert.Nil(t, err)
assert.Equal(t, invalidTestCaseContent, string(data))
assert.Equal(t, "testdata", loader.GetContext())

assert.True(t, loader.HasMore())
data, err = loader.Load()
assert.Nil(t, err)
assert.Equal(t, testCaseContent, string(data))
assert.Equal(t, "testdata", loader.GetContext())

assert.False(t, loader.HasMore())
}
17 changes: 8 additions & 9 deletions pkg/testing/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,8 @@ import (
)

// Parse parses a file and returns the test suite
func Parse(configFile string) (testSuite *TestSuite, err error) {
var data []byte
if data, err = os.ReadFile(configFile); err == nil {
testSuite, err = ParseFromData(data)
}
func Parse(data []byte) (testSuite *TestSuite, err error) {
testSuite, err = ParseFromData(data)

// schema validation
if err == nil {
Expand Down Expand Up @@ -116,7 +113,7 @@ func (r *Request) Render(ctx interface{}, dataDir string) (err error) {
}

// setting default values
r.Method = emptyThenDefault(r.Method, http.MethodGet)
r.Method = EmptyThenDefault(r.Method, http.MethodGet)
return
}

Expand Down Expand Up @@ -153,18 +150,20 @@ func (r *Request) GetBody() (reader io.Reader, err error) {

// Render renders the response
func (r *Response) Render(ctx interface{}) (err error) {
r.StatusCode = zeroThenDefault(r.StatusCode, http.StatusOK)
r.StatusCode = ZeroThenDefault(r.StatusCode, http.StatusOK)
return
}

func zeroThenDefault(val, defVal int) int {
// ZeroThenDefault return the default value if the val is zero
func ZeroThenDefault(val, defVal int) int {
if val == 0 {
val = defVal
}
return val
}

func emptyThenDefault(val, defVal string) string {
// EmptyThenDefault return the default value if the val is empty
func EmptyThenDefault(val, defVal string) string {
if strings.TrimSpace(val) == "" {
val = defVal
}
Expand Down
Loading

0 comments on commit d564f69

Please sign in to comment.