diff --git a/.claude/settings.local.json b/.claude/settings.local.json
new file mode 100644
index 00000000..1eccc226
--- /dev/null
+++ b/.claude/settings.local.json
@@ -0,0 +1,11 @@
+{
+ "permissions": {
+ "allow": [
+ "Bash(go test:*)",
+ "Bash(go doc:*)",
+ "WebSearch",
+ "Bash(go env:*)",
+ "Bash(docker pull:*)"
+ ]
+ }
+}
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 0b3e95f8..6189343c 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -129,7 +129,7 @@ jobs:
BuildDesktop:
strategy:
matrix:
- os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
+ os: [ubuntu-latest, windows-latest, macos-latest, macos-14]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index c0eb9e15..b42689e7 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -133,7 +133,7 @@ jobs:
fail-fast: false
matrix:
# see https://github.com/actions/runner-images
- os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
+ os: [ubuntu-latest, windows-latest, macos-latest, macos-14]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
diff --git a/cmd/run.go b/cmd/run.go
index 3a2edf26..3690d76e 100644
--- a/cmd/run.go
+++ b/cmd/run.go
@@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
+ "golang.org/x/time/rate"
"io"
"net/http"
"os"
@@ -32,7 +33,6 @@ import (
"github.com/linuxsuren/api-testing/pkg/util/home"
"github.com/linuxsuren/api-testing/pkg/apispec"
- "github.com/linuxsuren/api-testing/pkg/limit"
"github.com/linuxsuren/api-testing/pkg/logging"
"github.com/linuxsuren/api-testing/pkg/runner"
"github.com/linuxsuren/api-testing/pkg/runner/monitor"
@@ -55,8 +55,8 @@ type runOption struct {
thread int64
context context.Context
qps int32
- burst int32
- limiter limit.RateLimiter
+ burst int
+ limiter *rate.Limiter
startTime time.Time
reporter runner.TestReporter
reportFile string
@@ -137,7 +137,7 @@ func (o *runOption) addFlags(flags *pflag.FlagSet) {
flags.StringVarP(&o.swaggerURL, "swagger-url", "", "", "The URL of swagger")
flags.Int64VarP(&o.thread, "thread", "", 1, "Threads of the execution")
flags.Int32VarP(&o.qps, "qps", "", 5, "QPS")
- flags.Int32VarP(&o.burst, "burst", "", 5, "burst")
+ flags.IntVarP(&o.burst, "burst", "", 5, "burst")
flags.StringVarP(&o.monitorDocker, "monitor-docker", "", "", "The docker container name to monitor")
}
@@ -256,10 +256,9 @@ func (o *runOption) startMonitor() (err error) {
func (o *runOption) runE(cmd *cobra.Command, args []string) (err error) {
o.startTime = time.Now()
- o.limiter = limit.NewDefaultRateLimiter(o.qps, o.burst)
+ o.limiter = rate.NewLimiter(rate.Limit(o.qps), o.burst)
defer func() {
cmd.Printf("Consumed: %s\n", time.Since(o.startTime).String())
- o.limiter.Stop()
}()
if err = o.loader.Put(o.pattern); err != nil {
@@ -400,7 +399,7 @@ func (o *runOption) runSuite(loader testing.Loader, dataContext map[string]inter
case <-stopSingal:
return
default:
- o.limiter.Accept()
+ o.limiter.Allow()
ctxWithTimeout, cancel := context.WithTimeout(ctx, o.requestTimeout)
defer cancel() // Ensure context is always cancelled when leaving this scope
diff --git a/cmd/run_test.go b/cmd/run_test.go
index 1ac3f1c5..55d553e6 100644
--- a/cmd/run_test.go
+++ b/cmd/run_test.go
@@ -27,11 +27,11 @@ import (
"time"
"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"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
+ "golang.org/x/time/rate"
)
func TestRunSuite(t *testing.T) {
@@ -71,7 +71,7 @@ func TestRunSuite(t *testing.T) {
ctx := getDefaultContext()
opt := newDiscardRunOption()
opt.requestTimeout = 30 * time.Second
- opt.limiter = limit.NewDefaultRateLimiter(0, 0)
+ opt.limiter = rate.NewLimiter(rate.Limit(0), 0)
stopSingal := make(chan struct{}, 1)
loader := atest.NewFileLoader()
diff --git a/e2e/code-generator/Dockerfile b/e2e/code-generator/Dockerfile
index 7ec2ea37..ed3d5ee7 100644
--- a/e2e/code-generator/Dockerfile
+++ b/e2e/code-generator/Dockerfile
@@ -1,7 +1,7 @@
ARG LAN_ENV=docker.io/library/golang:1.21
FROM ghcr.io/linuxsuren/api-testing:master AS atest
-FROM ghcr.io/linuxsuren/hd:v0.0.42 as downloader
+FROM ghcr.io/linuxsuren/hd:v0.0.42 AS downloader
RUN hd install jq
FROM $LAN_ENV
diff --git a/e2e/code-generator/compose.yaml b/e2e/code-generator/compose.yaml
index bdc4114b..0289df91 100644
--- a/e2e/code-generator/compose.yaml
+++ b/e2e/code-generator/compose.yaml
@@ -13,7 +13,7 @@ services:
context: .
dockerfile: Dockerfile
args:
- - LAN_ENV=docker.io/library/openjdk:23
+ - LAN_ENV=docker.io/library/openjdk:26-rc-jdk
command:
- /workspace/entrypoint.sh
- java
@@ -49,7 +49,7 @@ services:
context: .
dockerfile: Dockerfile
args:
- - LAN_ENV=docker.io/library/openjdk:23
+ - LAN_ENV=docker.io/library/openjdk:26-rc-jdk
command:
- /workspace/entrypoint.sh
- curl
diff --git a/go.mod b/go.mod
index 79566609..df3b85a3 100644
--- a/go.mod
+++ b/go.mod
@@ -22,7 +22,7 @@ require (
github.com/invopop/jsonschema v0.7.0
github.com/jhump/protoreflect v1.15.3
github.com/linuxsuren/go-fake-runtime v0.0.5
- github.com/linuxsuren/go-service v0.0.2-0.20251117091849-c58edc8748d9
+ github.com/linuxsuren/go-service v0.0.2
github.com/linuxsuren/unstructured v0.0.1
github.com/prometheus/client_golang v1.22.0
github.com/prometheus/common v0.67.2
@@ -48,6 +48,7 @@ require (
github.com/gorilla/websocket v1.5.3
github.com/linuxsuren/http-downloader v0.0.99
golang.org/x/mod v0.28.0
+ golang.org/x/time v0.14.0
)
require (
diff --git a/go.sum b/go.sum
index 5676602f..2bd65812 100644
--- a/go.sum
+++ b/go.sum
@@ -131,28 +131,10 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/linuxsuren/go-fake-runtime v0.0.5 h1:x1qvuGMfly3L4BTwx6Hq5oUcuf/1u0kSVPzQylHHpwI=
github.com/linuxsuren/go-fake-runtime v0.0.5/go.mod h1:hlE6bZp76N3YPDsKi5YKOf1XmcJy4rvf8EtkTLYRYLw=
-github.com/linuxsuren/go-service v0.0.1 h1:GoeK2HLDlRh+QQvFlxOferGtDUwzO3YduumMJ0XYPJ8=
-github.com/linuxsuren/go-service v0.0.1/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
-github.com/linuxsuren/go-service v0.0.2-0.20251117075600-96234f59e3f2 h1:vy8Y8NA7vjZmHE+28v2Un4mtc4DG1XtXo66hbeQ4pXE=
-github.com/linuxsuren/go-service v0.0.2-0.20251117075600-96234f59e3f2/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
-github.com/linuxsuren/go-service v0.0.2-0.20251117081324-130f4c6054f7 h1:/xN+kJ5Vo+FCCjasmapVw5lRMwb6sgdJZqTu02kfNag=
-github.com/linuxsuren/go-service v0.0.2-0.20251117081324-130f4c6054f7/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
-github.com/linuxsuren/go-service v0.0.2-0.20251117081529-39b6694d1e30 h1:C9aOFP9tVFcDKlQAd3X4rU43s+VmS/R/BNzHKWD6uhU=
-github.com/linuxsuren/go-service v0.0.2-0.20251117081529-39b6694d1e30/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
-github.com/linuxsuren/go-service v0.0.2-0.20251117082747-764ea1ba3825 h1:6CwFWPq2DjFrW1gbH2FtKPlNPCm1j0vgYBl5/LWeT6Y=
-github.com/linuxsuren/go-service v0.0.2-0.20251117082747-764ea1ba3825/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
-github.com/linuxsuren/go-service v0.0.2-0.20251117083110-fbec39b2f85d h1:+kMcMI8rB9VbpcfWH8h3lOH7sYjT0+uq0EWsDf1byf4=
-github.com/linuxsuren/go-service v0.0.2-0.20251117083110-fbec39b2f85d/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
-github.com/linuxsuren/go-service v0.0.2-0.20251117083330-afb28a74b935 h1:bAFGUhlWuRla9Di1Fq7alY9Q9lXeLDgHMQdyLPVbVOg=
-github.com/linuxsuren/go-service v0.0.2-0.20251117083330-afb28a74b935/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
-github.com/linuxsuren/go-service v0.0.2-0.20251117083554-81682ffea100 h1:7uMuI3tJB53C4+dlBrfF4FaQ9YxY3KvatUSZL9Kgo8A=
-github.com/linuxsuren/go-service v0.0.2-0.20251117083554-81682ffea100/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
-github.com/linuxsuren/go-service v0.0.2-0.20251117084203-71bf4d3ebe0f h1:XYw35A2a2XafK57MSSoyDICrTw+TOcUWWT0cqHE/Khw=
-github.com/linuxsuren/go-service v0.0.2-0.20251117084203-71bf4d3ebe0f/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
-github.com/linuxsuren/go-service v0.0.2-0.20251117091757-3ae9fc74c5b9 h1:5jCZ8Xh4Bxpq9pwrs+T4CBVCfG4gVTpx45t3s/0gnxI=
-github.com/linuxsuren/go-service v0.0.2-0.20251117091757-3ae9fc74c5b9/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
github.com/linuxsuren/go-service v0.0.2-0.20251117091849-c58edc8748d9 h1:w5prP6ROOxInPV38KL+0laf7ZDIHlidBerhrphHqWHU=
github.com/linuxsuren/go-service v0.0.2-0.20251117091849-c58edc8748d9/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
+github.com/linuxsuren/go-service v0.0.2 h1:4pq+LEXs1/V6qBCVW749PZbaXSQb3dyz/VR+xsdf95o=
+github.com/linuxsuren/go-service v0.0.2/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw=
github.com/linuxsuren/http-downloader v0.0.99 h1:fEu+HkHdYeLM932c7IfmuaDJqWxVU5sIEnS/Aln8h9o=
github.com/linuxsuren/http-downloader v0.0.99/go.mod h1:OngIAkbOJTMbd+IMRbt3TiWSizVJZvPfjdbTpl6uHLo=
github.com/linuxsuren/oauth-hub v0.0.1 h1:5LAdX9ZlWhaM7P10rdxiXPk26eceYHRyfkFXsym6AxY=
@@ -334,6 +316,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
+golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
+golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
diff --git a/pkg/limit/limiter.go b/pkg/limit/limiter.go
deleted file mode 100644
index 23ae56c6..00000000
--- a/pkg/limit/limiter.go
+++ /dev/null
@@ -1,91 +0,0 @@
-package limit
-
-import (
- "sync"
- "time"
-)
-
-type RateLimiter interface {
- Accept() bool
- Stop()
- Burst() int32
-}
-
-type defaultRateLimiter struct {
- qps int32
- burst int32
- lastToken time.Time
- singal chan struct{}
- mu sync.Mutex
-}
-
-func NewDefaultRateLimiter(qps, burst int32) RateLimiter {
- if qps <= 0 {
- qps = 5
- }
- if burst <= 0 {
- burst = 5
- }
- limiter := &defaultRateLimiter{
- qps: qps,
- burst: burst,
- singal: make(chan struct{}, 1),
- lastToken: time.Now(),
- }
- go limiter.updateBurst()
- return limiter
-}
-
-func (r *defaultRateLimiter) resver() (delay time.Duration, ok bool) {
- delay = time.Now().Sub(r.lastToken) / time.Millisecond
- delayRequire := time.Second / time.Duration(r.qps)
- r.lastToken = time.Now()
- if delay >= delayRequire {
- ok = true
- } else if r.Burst() > 0 {
- r.Setburst(r.Burst() - 1)
- ok = true
- } else {
- delay = delayRequire - delay
- }
- return
-}
-
-func (r *defaultRateLimiter) Accept() bool {
- delay, ok := r.resver()
- if ok {
- return ok
- }
-
- if delay > 0 {
- time.Sleep(delay)
- }
- return ok
-}
-
-func (r *defaultRateLimiter) Setburst(burst int32) {
- r.mu.Lock()
- defer r.mu.Unlock()
- r.burst = burst
-}
-
-func (r *defaultRateLimiter) Burst() int32 {
- r.mu.Lock()
- defer r.mu.Unlock()
- return r.burst
-}
-
-func (r *defaultRateLimiter) Stop() {
- r.singal <- struct{}{}
-}
-
-func (r *defaultRateLimiter) updateBurst() {
- for {
- select {
- case <-time.After(time.Second):
- r.Setburst(r.Burst() + r.qps)
- case <-r.singal:
- return
- }
- }
-}
diff --git a/pkg/limit/limiter_long_test.go b/pkg/limit/limiter_long_test.go
deleted file mode 100644
index 6a849f16..00000000
--- a/pkg/limit/limiter_long_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-//go:build longtest
-// +build longtest
-
-/*
-Copyright 2023 API Testing Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package limit_test
-
-import (
- "testing"
- "time"
-
- "github.com/linuxsuren/api-testing/pkg/limit"
- "github.com/stretchr/testify/assert"
-)
-
-func TestLimiterWithLongTime(t *testing.T) {
- for i := 0; i < 10; i++ {
- testLimiter(t, int32(8+i*2))
- }
-}
-
-func testLimiter(t *testing.T, count int32) {
- t.Log("test limit with count", count)
- limiter := limit.NewDefaultRateLimiter(count, 1)
- num := int32(0)
-
- loop := true
- go func(l limit.RateLimiter) {
- for loop {
- l.Accept()
- num += 1
- }
- }(limiter)
-
- select {
- case <-time.After(time.Second):
- loop = false
- }
- assert.True(t, num <= count+1, num)
-}
diff --git a/pkg/limit/limiter_test.go b/pkg/limit/limiter_test.go
deleted file mode 100644
index a7e779de..00000000
--- a/pkg/limit/limiter_test.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package limit
-
-import (
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestLimiter(t *testing.T) {
- t.Log("run rate limit test")
- limiter := NewDefaultRateLimiter(0, 0)
- num := 0
-
- loop := true
- go func(l RateLimiter) {
- for loop {
- l.Accept()
- num += 1
- }
- }(limiter)
-
- select {
- case <-time.After(time.Second):
- loop = false
- limiter.Stop()
- }
- assert.True(t, num <= 10, num)
-}
diff --git a/pkg/runner/expr_function.go b/pkg/runner/expr_function.go
index b624dcb9..32ce26b4 100644
--- a/pkg/runner/expr_function.go
+++ b/pkg/runner/expr_function.go
@@ -24,6 +24,7 @@ import (
"net/http"
"os"
"os/exec"
+ "runtime"
"time"
"github.com/expr-lang/expr"
@@ -140,8 +141,18 @@ func init() {
{
Name: "command",
Func: func(params ...interface{}) (res any, err error) {
+ if len(params) < 1 {
+ err = fmt.Errorf("the command param is required")
+ return
+ }
+
+ shParams := []string{"sh", "-c"}
+ if runtime.GOOS == "windows" {
+ shParams = []string{"cmd", "/c"}
+ }
+
var output []byte
- output, err = exec.Command("sh", "-c", params[0].(string)).CombinedOutput()
+ output, err = exec.Command(shParams[0], shParams[1], params[0].(string)).CombinedOutput()
if output != nil {
res = string(output)
}
diff --git a/pkg/runner/expr_function_test.go b/pkg/runner/expr_function_test.go
index 7a13d69f..7cf063a8 100644
--- a/pkg/runner/expr_function_test.go
+++ b/pkg/runner/expr_function_test.go
@@ -21,6 +21,8 @@ import (
"io"
"net/http"
"os"
+ "path/filepath"
+ "strings"
"testing"
"github.com/expr-lang/expr"
@@ -144,16 +146,16 @@ func TestFunctions(t *testing.T) {
expr: `command("echo 1")`,
verify: func(t *testing.T, result any, resultErr error) {
assert.NoError(t, resultErr)
- assert.Equal(t, "1\n", result)
+ assert.Equal(t, "1", strings.TrimSpace(result.(string)))
},
}, {
name: "writeFile",
- expr: fmt.Sprintf(`writeFile("%s", "hello")`, tmpFile.Name()),
+ expr: fmt.Sprintf(`writeFile("%s", "hello")`, filepath.ToSlash(tmpFile.Name())),
verify: func(t *testing.T, result any, resultErr error) {
assert.NoError(t, resultErr)
data, err := io.ReadAll(tmpFile)
- assert.NoError(t, err)
+ assert.NoError(t, err, "failed to read file: %v", err)
assert.Equal(t, "hello", string(data))
},
}}
@@ -166,7 +168,7 @@ func TestFunctions(t *testing.T) {
assert.Error(t, err, "%q %d", tt.name, i)
return
}
- if !assert.NotNil(t, program, "%q %d", tt.name, i) {
+ if !assert.NotNil(t, program, "%q, index: %d, expr: %s: error: %v", tt.name, i, tt.expr, err) {
return
}
diff --git a/pkg/runner/writer_markdown_test.go b/pkg/runner/writer_markdown_test.go
index 345eb18c..4622c301 100644
--- a/pkg/runner/writer_markdown_test.go
+++ b/pkg/runner/writer_markdown_test.go
@@ -18,6 +18,7 @@ package runner_test
import (
"bytes"
+ "strings"
"testing"
"github.com/linuxsuren/api-testing/pkg/apispec"
@@ -25,6 +26,11 @@ import (
"github.com/stretchr/testify/assert"
)
+const (
+ winLineEnd = "\r\n"
+ unixLineEnd = "\n"
+)
+
func TestMarkdownWriter(t *testing.T) {
sample := runner.ReportResult{
Name: "api",
@@ -51,12 +57,15 @@ func TestMarkdownWriter(t *testing.T) {
writer.WithAPICoverage(nil)
err := writer.Output(createSlice(sample, 2))
assert.Nil(t, err)
+ // Normalize line endings for Windows compatibility
+ actual := buf.String()
+ actual = normalizeLineEndings(actual)
assert.Equal(t, `There are 2 test cases, failed count 0:
| Name | Average | Max | Min | Count | Error |
|---|---|---|---|---|---|
| api | 3ns | 4ns | 2ns | 3 | 0 |
-| api | 3ns | 4ns | 2ns | 3 | 0 |`, buf.String())
+| api | 3ns | 4ns | 2ns | 3 | 0 |`, actual)
})
t.Run("long", func(t *testing.T) {
@@ -65,6 +74,7 @@ func TestMarkdownWriter(t *testing.T) {
writer.WithAPICoverage(nil)
err := writer.Output(createSlice(sample, 8))
assert.Nil(t, err)
+ actual := normalizeLineEndings(buf.String())
assert.Equal(t, `There are 8 test cases, failed count 0:
@@ -80,7 +90,7 @@ func TestMarkdownWriter(t *testing.T) {
| api | 3ns | 4ns | 2ns | 3 | 0 |
| api | 3ns | 4ns | 2ns | 3 | 0 |
| api | 3ns | 4ns | 2ns | 3 | 0 |
- `, buf.String())
+`, actual)
})
t.Run("long, there are error cases", func(t *testing.T) {
@@ -89,6 +99,7 @@ func TestMarkdownWriter(t *testing.T) {
writer.WithAPICoverage(nil)
err := writer.Output(append(createSlice(sample, 8), errSample))
assert.Nil(t, err)
+ actual := normalizeLineEndings(buf.String())
assert.Equal(t, `There are 9 test cases, failed count 1:
| Name | Average | Max | Min | Count | Error |
@@ -109,7 +120,7 @@ func TestMarkdownWriter(t *testing.T) {
| api | 3ns | 4ns | 2ns | 3 | 0 |
| api | 3ns | 4ns | 2ns | 3 | 0 |
| foo | 3ns | 4ns | 2ns | 3 | 1 |
-`, buf.String())
+`, actual)
})
t.Run("with resource usage", func(t *testing.T) {
@@ -122,6 +133,7 @@ func TestMarkdownWriter(t *testing.T) {
}})
err := writer.Output(createSlice(sample, 2))
assert.Nil(t, err)
+ actual := normalizeLineEndings(buf.String())
assert.Equal(t, `There are 2 test cases, failed count 0:
| Name | Average | Max | Min | Count | Error |
@@ -131,7 +143,7 @@ func TestMarkdownWriter(t *testing.T) {
Resource usage:
* CPU: 1
-* Memory: 1`, buf.String())
+* Memory: 1`, actual)
})
t.Run("have error message", func(t *testing.T) {
@@ -142,6 +154,7 @@ Resource usage:
result.LastErrorMessage = "error happend"
err := writer.Output(createSlice(result, 2))
assert.Nil(t, err)
+ actual := normalizeLineEndings(buf.String())
assert.Equal(t, `There are 2 test cases, failed count 0:
| Name | Average | Max | Min | Count | Error |
@@ -153,7 +166,7 @@ Resource usage:
See the error message
* error happend
* error happend
-`, buf.String())
+`, actual)
})
t.Run("with api converage", func(t *testing.T) {
@@ -164,6 +177,7 @@ Resource usage:
}}))
err := writer.Output(createSlice(sample, 2))
assert.Nil(t, err)
+ actual := normalizeLineEndings(buf.String())
assert.Equal(t, `There are 2 test cases, failed count 0:
| Name | Average | Max | Min | Count | Error |
@@ -171,10 +185,14 @@ Resource usage:
| api | 3ns | 4ns | 2ns | 3 | 0 |
| api | 3ns | 4ns | 2ns | 3 | 0 |
-API Coverage: 1/1`, buf.String())
+API Coverage: 1/1`, actual)
})
}
+func normalizeLineEndings(s string) string {
+ return strings.ReplaceAll(s, winLineEnd, unixLineEnd)
+}
+
func createSlice(sample runner.ReportResult, count int) (result []runner.ReportResult) {
for i := 0; i < count; i++ {
result = append(result, sample)
diff --git a/pkg/server/remote_server_test.go b/pkg/server/remote_server_test.go
index 2dbde95d..065f25ae 100644
--- a/pkg/server/remote_server_test.go
+++ b/pkg/server/remote_server_test.go
@@ -507,6 +507,9 @@ func TestDuplicate(t *testing.T) {
SourceSuiteName: "simple",
TargetSuiteName: "simple2",
})
+ defer func() {
+ _ = os.RemoveAll("simple2.yaml")
+ }()
assert.NoError(t, err)
// find the new test suite