1
1
package cmd
2
2
3
3
import (
4
+ "context"
4
5
"fmt"
5
6
"path"
6
7
"path/filepath"
7
8
"strings"
9
+ "sync"
10
+ "time"
8
11
12
+ "github.com/linuxsuren/api-testing/pkg/render"
9
13
"github.com/linuxsuren/api-testing/pkg/runner"
10
14
"github.com/linuxsuren/api-testing/pkg/testing"
11
15
"github.com/spf13/cobra"
16
+ "golang.org/x/sync/semaphore"
12
17
)
13
18
14
19
type runOption struct {
15
- pattern string
20
+ pattern string
21
+ duration time.Duration
22
+ thread int64
23
+ context context.Context
16
24
}
17
25
18
26
// CreateRunCommand returns the run command
@@ -31,31 +39,84 @@ See also https://github.com/LinuxSuRen/api-testing/tree/master/sample`,
31
39
flags := cmd .Flags ()
32
40
flags .StringVarP (& opt .pattern , "pattern" , "p" , "test-suite-*.yaml" ,
33
41
"The file pattern which try to execute the test cases" )
42
+ flags .DurationVarP (& opt .duration , "duration" , "" , 0 , "Running duration" )
43
+ flags .Int64VarP (& opt .thread , "thread" , "" , 1 , "Threads of the execution" )
34
44
return
35
45
}
36
46
37
47
func (o * runOption ) runE (cmd * cobra.Command , args []string ) (err error ) {
38
48
var files []string
39
- ctx := getDefaultContext ()
49
+ o . context = cmd . Context ()
40
50
41
51
if files , err = filepath .Glob (o .pattern ); err == nil {
42
52
for i := range files {
43
53
item := files [i ]
44
- if err = runSuite (item , ctx ); err != nil {
54
+ if err = o . runSuiteWithDuration (item ); err != nil {
45
55
return
46
56
}
47
57
}
48
58
}
49
59
return
50
60
}
51
61
62
+ func (o * runOption ) runSuiteWithDuration (suite string ) (err error ) {
63
+ sem := semaphore .NewWeighted (o .thread )
64
+ stop := false
65
+ var timeout * time.Ticker
66
+ if o .duration > 0 {
67
+ timeout = time .NewTicker (o .duration )
68
+ } else {
69
+ // make sure having a valid timer
70
+ timeout = time .NewTicker (time .Second )
71
+ }
72
+ errChannel := make (chan error , 10 )
73
+ var wait sync.WaitGroup
74
+
75
+ for ! stop {
76
+ select {
77
+ case <- timeout .C :
78
+ stop = true
79
+ case err = <- errChannel :
80
+ if err != nil {
81
+ stop = true
82
+ }
83
+ default :
84
+ if err := sem .Acquire (o .context , 1 ); err != nil {
85
+ continue
86
+ }
87
+ wait .Add (1 )
88
+ if o .duration <= 0 {
89
+ stop = true
90
+ }
91
+
92
+ go func (ch chan error ) {
93
+ defer sem .Release (1 )
94
+ defer wait .Done ()
95
+
96
+ ctx := getDefaultContext ()
97
+ ch <- runSuite (suite , ctx )
98
+ }(errChannel )
99
+ }
100
+ }
101
+ err = <- errChannel
102
+ wait .Wait ()
103
+ return
104
+ }
105
+
52
106
func runSuite (suite string , ctx map [string ]interface {}) (err error ) {
53
107
var testSuite * testing.TestSuite
54
108
if testSuite , err = testing .Parse (suite ); err != nil {
55
109
return
56
110
}
57
111
58
- testSuite .API = strings .TrimSuffix (testSuite .API , "/" )
112
+ var result string
113
+ if result , err = render .Render ("base api" , testSuite .API , ctx ); err == nil {
114
+ testSuite .API = result
115
+ testSuite .API = strings .TrimSuffix (testSuite .API , "/" )
116
+ } else {
117
+ return
118
+ }
119
+
59
120
for _ , testCase := range testSuite .Items {
60
121
// reuse the API prefix
61
122
if strings .HasPrefix (testCase .Request .API , "/" ) {
0 commit comments