Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
45eaef24
G
go-ethereum
项目概览
whqwjb
/
go-ethereum
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
go-ethereum
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
45eaef24
编写于
8月 09, 2018
作者:
J
Janoš Guljaš
提交者:
Balint Gabor
8月 09, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
cmd/swarm: solve rare cases of using the same random port in tests (#17352)
上级
3bcb501c
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
131 addition
and
19 deletion
+131
-19
cmd/swarm/config_test.go
cmd/swarm/config_test.go
+14
-0
cmd/swarm/run_test.go
cmd/swarm/run_test.go
+117
-19
未找到文件。
cmd/swarm/config_test.go
浏览文件 @
45eaef24
...
...
@@ -20,6 +20,7 @@ import (
"fmt"
"io"
"io/ioutil"
"net"
"os"
"os/exec"
"testing"
...
...
@@ -559,3 +560,16 @@ func TestValidateConfig(t *testing.T) {
}
}
}
func
assignTCPPort
()
(
string
,
error
)
{
l
,
err
:=
net
.
Listen
(
"tcp"
,
"127.0.0.1:0"
)
if
err
!=
nil
{
return
""
,
err
}
l
.
Close
()
_
,
port
,
err
:=
net
.
SplitHostPort
(
l
.
Addr
()
.
String
())
if
err
!=
nil
{
return
""
,
err
}
return
port
,
nil
}
cmd/swarm/run_test.go
浏览文件 @
45eaef24
...
...
@@ -17,12 +17,15 @@
package
main
import
(
"context"
"fmt"
"io/ioutil"
"net"
"os"
"path/filepath"
"runtime"
"sync"
"syscall"
"testing"
"time"
...
...
@@ -218,14 +221,12 @@ func existingTestNode(t *testing.T, dir string, bzzaccount string) *testNode {
}
// assign ports
httpPort
,
err
:=
assignTCPPort
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
p2pPort
,
err
:=
assignTCPPort
()
ports
,
err
:=
getAvailableTCPPorts
(
2
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
p2pPort
:=
ports
[
0
]
httpPort
:=
ports
[
1
]
// start the node
node
.
Cmd
=
runSwarm
(
t
,
...
...
@@ -246,6 +247,17 @@ func existingTestNode(t *testing.T, dir string, bzzaccount string) *testNode {
}
}()
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
30
*
time
.
Second
)
defer
cancel
()
// ensure that all ports have active listeners
// so that the next node will not get the same
// when calling getAvailableTCPPorts
err
=
waitTCPPorts
(
ctx
,
ports
...
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// wait for the node to start
for
start
:=
time
.
Now
();
time
.
Since
(
start
)
<
10
*
time
.
Second
;
time
.
Sleep
(
50
*
time
.
Millisecond
)
{
node
.
Client
,
err
=
rpc
.
Dial
(
conf
.
IPCEndpoint
())
...
...
@@ -280,14 +292,12 @@ func newTestNode(t *testing.T, dir string) *testNode {
node
:=
&
testNode
{
Dir
:
dir
}
// assign ports
httpPort
,
err
:=
assignTCPPort
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
p2pPort
,
err
:=
assignTCPPort
()
ports
,
err
:=
getAvailableTCPPorts
(
2
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
p2pPort
:=
ports
[
0
]
httpPort
:=
ports
[
1
]
// start the node
node
.
Cmd
=
runSwarm
(
t
,
...
...
@@ -308,6 +318,17 @@ func newTestNode(t *testing.T, dir string) *testNode {
}
}()
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
30
*
time
.
Second
)
defer
cancel
()
// ensure that all ports have active listeners
// so that the next node will not get the same
// when calling getAvailableTCPPorts
err
=
waitTCPPorts
(
ctx
,
ports
...
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// wait for the node to start
for
start
:=
time
.
Now
();
time
.
Since
(
start
)
<
10
*
time
.
Second
;
time
.
Sleep
(
50
*
time
.
Millisecond
)
{
node
.
Client
,
err
=
rpc
.
Dial
(
conf
.
IPCEndpoint
())
...
...
@@ -343,15 +364,92 @@ func (n *testNode) Shutdown() {
}
}
func
assignTCPPort
()
(
string
,
error
)
{
l
,
err
:=
net
.
Listen
(
"tcp"
,
"127.0.0.1:0"
)
if
err
!=
nil
{
return
""
,
err
// getAvailableTCPPorts returns a set of ports that
// nothing is listening on at the time.
//
// Function assignTCPPort cannot be called in sequence
// and guardantee that the same port will be returned in
// different calls as the listener is closed within the function,
// not after all listeners are started and selected unique
// available ports.
func
getAvailableTCPPorts
(
count
int
)
(
ports
[]
string
,
err
error
)
{
for
i
:=
0
;
i
<
count
;
i
++
{
l
,
err
:=
net
.
Listen
(
"tcp"
,
"127.0.0.1:0"
)
if
err
!=
nil
{
return
nil
,
err
}
// defer close in the loop to be sure the same port will not
// be selected in the next iteration
defer
l
.
Close
()
_
,
port
,
err
:=
net
.
SplitHostPort
(
l
.
Addr
()
.
String
())
if
err
!=
nil
{
return
nil
,
err
}
ports
=
append
(
ports
,
port
)
}
l
.
Close
()
_
,
port
,
err
:=
net
.
SplitHostPort
(
l
.
Addr
()
.
String
())
if
err
!=
nil
{
return
""
,
err
return
ports
,
nil
}
// waitTCPPorts blocks until tcp connections can be
// established on all provided ports. It runs all
// ports dialers in parallel, and returns the first
// encountered error.
// See waitTCPPort also.
func
waitTCPPorts
(
ctx
context
.
Context
,
ports
...
string
)
error
{
var
err
error
// mu locks err variable that is assigned in
// other goroutines
var
mu
sync
.
Mutex
// cancel is canceling all goroutines
// when the firs error is returned
// to prevent unnecessary waiting
ctx
,
cancel
:=
context
.
WithCancel
(
ctx
)
defer
cancel
()
var
wg
sync
.
WaitGroup
for
_
,
port
:=
range
ports
{
wg
.
Add
(
1
)
go
func
(
port
string
)
{
defer
wg
.
Done
()
e
:=
waitTCPPort
(
ctx
,
port
)
mu
.
Lock
()
defer
mu
.
Unlock
()
if
e
!=
nil
&&
err
==
nil
{
err
=
e
cancel
()
}
}(
port
)
}
wg
.
Wait
()
return
err
}
// waitTCPPort blocks until tcp connection can be established
// ona provided port. It has a 3 minute timeout as maximum,
// to prevent long waiting, but it can be shortened with
// a provided context instance. Dialer has a 10 second timeout
// in every iteration, and connection refused error will be
// retried in 100 milliseconds periods.
func
waitTCPPort
(
ctx
context
.
Context
,
port
string
)
error
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
3
*
time
.
Minute
)
defer
cancel
()
for
{
c
,
err
:=
(
&
net
.
Dialer
{
Timeout
:
10
*
time
.
Second
})
.
DialContext
(
ctx
,
"tcp"
,
"127.0.0.1:"
+
port
)
if
err
!=
nil
{
if
operr
,
ok
:=
err
.
(
*
net
.
OpError
);
ok
{
if
syserr
,
ok
:=
operr
.
Err
.
(
*
os
.
SyscallError
);
ok
&&
syserr
.
Err
==
syscall
.
ECONNREFUSED
{
time
.
Sleep
(
100
*
time
.
Millisecond
)
continue
}
}
return
err
}
return
c
.
Close
()
}
return
port
,
nil
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录