From 74f85992b6f1f9d6ba5f59cb487570b176540bde Mon Sep 17 00:00:00 2001 From: lyyyuna Date: Fri, 23 Jul 2021 15:25:03 +0800 Subject: [PATCH] get next abailable port for e2e test --- go.mod | 3 ++- go.sum | 6 +++-- tests/e2e/samples_mgr.go | 51 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 0a8c27f..2fd4e80 100644 --- a/go.mod +++ b/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 diff --git a/go.sum b/go.sum index 2a0c689..92cc3a2 100644 --- a/go.sum +++ b/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= diff --git a/tests/e2e/samples_mgr.go b/tests/e2e/samples_mgr.go index 4350a4d..e898b29 100644 --- a/tests/e2e/samples_mgr.go +++ b/tests/e2e/samples_mgr.go @@ -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 +}