get next abailable port for e2e test
This commit is contained in:
parent
b91728afd7
commit
74f85992b6
3
go.mod
3
go.mod
@ -4,6 +4,7 @@ go 1.16
|
||||
|
||||
require (
|
||||
github.com/gin-gonic/gin v1.7.2
|
||||
github.com/gofrs/flock v0.8.1
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
@ -18,7 +19,7 @@ require (
|
||||
github.com/tongjingran/copy v1.4.2
|
||||
go.uber.org/zap v1.17.0
|
||||
golang.org/x/mod v0.4.2
|
||||
golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 // indirect
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d
|
||||
golang.org/x/tools v0.1.3
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
|
6
go.sum
6
go.sum
@ -503,6 +503,8 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@ -1524,8 +1526,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 h1:C+AwYEtBp/VQwoLntUmQ/yx3MS9vmZaKNdw5eOpoQe8=
|
||||
golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
||||
|
@ -3,12 +3,15 @@ package e2e
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/gofrs/flock"
|
||||
"github.com/tongjingran/copy"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@ -20,9 +23,10 @@ type Sample struct {
|
||||
|
||||
// SamplesMgr create and return sample for test case
|
||||
//
|
||||
// ginkgo 的运行模型是多进程模型,每一个 test case 是一个独立的进程
|
||||
// ginkgo 的并发执行时的运行模型是多进程模型,会有多个独立的 go test 进程。
|
||||
// Ginkgo has support for running specs in parallel. It does this by spawning separate go test processes and serving specs to each process off of a shared queue.
|
||||
// 所以这里会单独在一个临时目录中生成 sample,以便将来测试用例可以并发执行
|
||||
//
|
||||
// 所以这里设计成每个 test case 在各自的临时目录中生成 sample,以便将来测试用例可以并发执行。
|
||||
type SamplesMgr struct {
|
||||
Samples map[string]Sample `yaml:"samples"`
|
||||
path string `yaml:"-"`
|
||||
@ -76,3 +80,46 @@ func (m *SamplesMgr) GetSampleByKey(key string) (string, error) {
|
||||
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
// GetAvailablePort get next available host port among multiprocess ginkgo test cases
|
||||
//
|
||||
// 利用文件锁和端口探活,获取下一个可用的 port
|
||||
func (m *SamplesMgr) GetAvailablePort() (string, error) {
|
||||
fileLockPath := filepath.Join(m.path, "tmp", "port.lock")
|
||||
|
||||
// 文件锁,ginkgo parallel 模式是多进程,必须用跨平台跨进程的同步方式
|
||||
lock := flock.New(fileLockPath)
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
// 该文件记录 counter,代表下一个可用的 port
|
||||
portFilePath := filepath.Join(m.path, "tmp", "port.record")
|
||||
data, err := os.ReadFile(portFilePath)
|
||||
if err != nil {
|
||||
os.Create(portFilePath)
|
||||
}
|
||||
port, err := strconv.Atoi(string(data))
|
||||
if err != nil {
|
||||
port = 7777
|
||||
} else {
|
||||
port += 1
|
||||
}
|
||||
|
||||
// 循环检测直到找到可用 port
|
||||
for {
|
||||
if port == 65534 {
|
||||
port = 7777
|
||||
}
|
||||
conn, err := net.Dial("tcp", ":"+strconv.Itoa(port))
|
||||
if err == nil {
|
||||
port += 1
|
||||
conn.Close()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
err = os.WriteFile(portFilePath, []byte(strconv.Itoa(port)), os.ModePerm)
|
||||
|
||||
return "127.0.0.1:" + strconv.Itoa(port), err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user