Fixed an intermittent issue in the libnetwork test

The libnetwork test does not need to run inside a namespace
when inside a container. This results in unpredictable behavior
when the sandbox code unlocks the go routine from the OS thread
while the test code still wants it locked in the OS thread. This
will result in unreachable interfaces when the go routine
migrates to a different OS thread.

Fixed by passing a special test flag which is only set to true
when the test is run inside a container.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
Jana Radhakrishnan 2015-05-12 23:39:30 +00:00
parent 79556b1ccc
commit 10fafb06eb
9 changed files with 112 additions and 27 deletions

View File

@ -2,8 +2,9 @@
SHELL=/bin/bash SHELL=/bin/bash
build_image=libnetwork-build build_image=libnetwork-build
dockerargs = --privileged -v $(shell pwd):/go/src/github.com/docker/libnetwork -w /go/src/github.com/docker/libnetwork dockerargs = --privileged -v $(shell pwd):/go/src/github.com/docker/libnetwork -w /go/src/github.com/docker/libnetwork
docker = docker run --rm ${dockerargs} ${build_image} container_env = -e "INSIDECONTAINER=-incontainer=true"
ciargs = -e "COVERALLS_TOKEN=$$COVERALLS_TOKEN" docker = docker run --rm ${dockerargs} ${container_env} ${build_image}
ciargs = -e "COVERALLS_TOKEN=$$COVERALLS_TOKEN" -e "INSIDECONTAINER=-incontainer=true"
cidocker = docker run ${ciargs} ${dockerargs} golang:1.4 cidocker = docker run ${ciargs} ${dockerargs} golang:1.4
all: ${build_image}.created all: ${build_image}.created
@ -42,8 +43,11 @@ run-tests:
@echo "mode: count" > coverage.coverprofile @echo "mode: count" > coverage.coverprofile
@for dir in $$(find . -maxdepth 10 -not -path './.git*' -not -path '*/_*' -type d); do \ @for dir in $$(find . -maxdepth 10 -not -path './.git*' -not -path '*/_*' -type d); do \
if ls $$dir/*.go &> /dev/null; then \ if ls $$dir/*.go &> /dev/null; then \
$(shell which godep) go test -test.parallel 3 -test.v -covermode=count -coverprofile=$$dir/profile.tmp $$dir ; \ pushd . &> /dev/null ; \
cd $$dir ; \
$(shell which godep) go test ${INSIDECONTAINER} -test.parallel 3 -test.v -covermode=count -coverprofile=./profile.tmp ; \
if [ $$? -ne 0 ]; then exit $$?; fi ;\ if [ $$? -ne 0 ]; then exit $$?; fi ;\
popd &> /dev/null; \
if [ -f $$dir/profile.tmp ]; then \ if [ -f $$dir/profile.tmp ]; then \
cat $$dir/profile.tmp | tail -n +2 >> coverage.coverprofile ; \ cat $$dir/profile.tmp | tail -n +2 >> coverage.coverprofile ; \
rm $$dir/profile.tmp ; \ rm $$dir/profile.tmp ; \

View File

@ -4,6 +4,8 @@ import (
"bytes" "bytes"
"io" "io"
"testing" "testing"
_ "github.com/docker/libnetwork/netutils"
) )
// nopCloser is used to provide a dummy CallFunc for Cmd() // nopCloser is used to provide a dummy CallFunc for Cmd()

View File

@ -138,7 +138,10 @@ func TestHost(t *testing.T) {
} }
func TestBridge(t *testing.T) { func TestBridge(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
ip, subnet, err := net.ParseCIDR("192.168.100.1/24") ip, subnet, err := net.ParseCIDR("192.168.100.1/24")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -209,7 +212,9 @@ func TestBridge(t *testing.T) {
} }
func TestUnknownDriver(t *testing.T) { func TestUnknownDriver(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
_, err := createTestNetwork("unknowndriver", "testnetwork", options.Generic{}, options.Generic{}) _, err := createTestNetwork("unknowndriver", "testnetwork", options.Generic{}, options.Generic{})
if err == nil { if err == nil {
@ -256,7 +261,10 @@ func TestNoInitDriver(t *testing.T) {
} }
func TestDuplicateNetwork(t *testing.T) { func TestDuplicateNetwork(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
controller, err := libnetwork.New() controller, err := libnetwork.New()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -287,7 +295,9 @@ func TestDuplicateNetwork(t *testing.T) {
} }
func TestNetworkName(t *testing.T) { func TestNetworkName(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
_, err := createTestNetwork(bridgeNetType, "", options.Generic{}, options.Generic{}) _, err := createTestNetwork(bridgeNetType, "", options.Generic{}, options.Generic{})
if err == nil { if err == nil {
@ -309,7 +319,10 @@ func TestNetworkName(t *testing.T) {
} }
func TestNetworkType(t *testing.T) { func TestNetworkType(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{}) n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -321,7 +334,9 @@ func TestNetworkType(t *testing.T) {
} }
func TestNetworkID(t *testing.T) { func TestNetworkID(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{}) n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{})
if err != nil { if err != nil {
@ -334,7 +349,10 @@ func TestNetworkID(t *testing.T) {
} }
func TestDeleteNetworkWithActiveEndpoints(t *testing.T) { func TestDeleteNetworkWithActiveEndpoints(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
option := options.Generic{ option := options.Generic{
"BridgeName": bridgeName, "BridgeName": bridgeName,
"AllowNonDefaultBridge": true} "AllowNonDefaultBridge": true}
@ -369,7 +387,10 @@ func TestDeleteNetworkWithActiveEndpoints(t *testing.T) {
} }
func TestUnknownNetwork(t *testing.T) { func TestUnknownNetwork(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
option := options.Generic{ option := options.Generic{
"BridgeName": bridgeName, "BridgeName": bridgeName,
"AllowNonDefaultBridge": true} "AllowNonDefaultBridge": true}
@ -395,7 +416,10 @@ func TestUnknownNetwork(t *testing.T) {
} }
func TestUnknownEndpoint(t *testing.T) { func TestUnknownEndpoint(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
ip, subnet, err := net.ParseCIDR("192.168.100.1/24") ip, subnet, err := net.ParseCIDR("192.168.100.1/24")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -446,7 +470,10 @@ func TestUnknownEndpoint(t *testing.T) {
} }
func TestNetworkEndpointsWalkers(t *testing.T) { func TestNetworkEndpointsWalkers(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
controller, err := libnetwork.New() controller, err := libnetwork.New()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -527,7 +554,10 @@ func TestNetworkEndpointsWalkers(t *testing.T) {
} }
func TestControllerQuery(t *testing.T) { func TestControllerQuery(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
controller, err := libnetwork.New() controller, err := libnetwork.New()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -590,7 +620,10 @@ func TestControllerQuery(t *testing.T) {
} }
func TestNetworkQuery(t *testing.T) { func TestNetworkQuery(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
controller, err := libnetwork.New() controller, err := libnetwork.New()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -656,7 +689,9 @@ func TestNetworkQuery(t *testing.T) {
const containerID = "valid_container" const containerID = "valid_container"
func TestEndpointJoin(t *testing.T) { func TestEndpointJoin(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{}) n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{})
if err != nil { if err != nil {
@ -685,7 +720,9 @@ func TestEndpointJoin(t *testing.T) {
} }
func TestEndpointJoinInvalidContainerId(t *testing.T) { func TestEndpointJoinInvalidContainerId(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{}) n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{})
if err != nil { if err != nil {
@ -708,7 +745,9 @@ func TestEndpointJoinInvalidContainerId(t *testing.T) {
} }
func TestEndpointDeleteWithActiveContainer(t *testing.T) { func TestEndpointDeleteWithActiveContainer(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{}) n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{})
if err != nil { if err != nil {
@ -750,7 +789,9 @@ func TestEndpointDeleteWithActiveContainer(t *testing.T) {
} }
func TestEndpointMultipleJoins(t *testing.T) { func TestEndpointMultipleJoins(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{}) n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{})
if err != nil { if err != nil {
@ -788,7 +829,9 @@ func TestEndpointMultipleJoins(t *testing.T) {
} }
func TestEndpointInvalidLeave(t *testing.T) { func TestEndpointInvalidLeave(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{}) n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{}, options.Generic{})
if err != nil { if err != nil {
@ -847,7 +890,9 @@ func TestEndpointInvalidLeave(t *testing.T) {
} }
func TestEndpointUpdateParent(t *testing.T) { func TestEndpointUpdateParent(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
n, err := createTestNetwork("bridge", "testnetwork", options.Generic{}, options.Generic{}) n, err := createTestNetwork("bridge", "testnetwork", options.Generic{}, options.Generic{})
if err != nil { if err != nil {
@ -899,7 +944,9 @@ func TestEndpointUpdateParent(t *testing.T) {
} }
func TestEnableIPv6(t *testing.T) { func TestEnableIPv6(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888") tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888")
//take a copy of resolv.conf for restoring after test completes //take a copy of resolv.conf for restoring after test completes
@ -914,8 +961,17 @@ func TestEnableIPv6(t *testing.T) {
} }
}() }()
ip, cidrv6, err := net.ParseCIDR("fe80::1/64")
if err != nil {
t.Fatal(err)
}
cidrv6.IP = ip
netOption := options.Generic{ netOption := options.Generic{
netlabel.EnableIPv6: true, netlabel.EnableIPv6: true,
netlabel.GenericData: options.Generic{
"FixedCIDRv6": cidrv6,
},
} }
n, err := createTestNetwork("bridge", "testnetwork", options.Generic{}, netOption) n, err := createTestNetwork("bridge", "testnetwork", options.Generic{}, netOption)
@ -962,7 +1018,9 @@ func TestEnableIPv6(t *testing.T) {
} }
func TestNoEnableIPv6(t *testing.T) { func TestNoEnableIPv6(t *testing.T) {
defer netutils.SetupTestNetNS(t)() if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
}
tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888") tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888")
expectedResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\n") expectedResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\n")
@ -1046,10 +1104,13 @@ func createGlobalInstance(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
//testns = origns if netutils.IsRunningInContainer() {
testns, err = netns.New() testns = origns
if err != nil { } else {
t.Fatal(err) testns, err = netns.New()
if err != nil {
t.Fatal(err)
}
} }
ctrlr, err = libnetwork.New() ctrlr, err = libnetwork.New()

View File

@ -1,11 +1,19 @@
package netutils package netutils
import ( import (
"flag"
"runtime" "runtime"
"syscall" "syscall"
"testing" "testing"
) )
var runningInContainer = flag.Bool("incontainer", false, "Indicates if the test is running in a container")
// IsRunningInContainer returns whether the test is running inside a container.
func IsRunningInContainer() bool {
return (*runningInContainer)
}
// SetupTestNetNS joins a new network namespace, and returns its associated // SetupTestNetNS joins a new network namespace, and returns its associated
// teardown function. // teardown function.
// //

View File

@ -5,6 +5,8 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"testing" "testing"
_ "github.com/docker/libnetwork/netutils"
) )
func TestBuildDefault(t *testing.T) { func TestBuildDefault(t *testing.T) {

View File

@ -6,6 +6,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"testing" "testing"
_ "github.com/docker/libnetwork/netutils"
) )
const chainName = "DOCKERTEST" const chainName = "DOCKERTEST"

View File

@ -4,6 +4,8 @@ import (
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
_ "github.com/docker/libnetwork/netutils"
) )
func TestGenerate(t *testing.T) { func TestGenerate(t *testing.T) {

View File

@ -3,6 +3,8 @@ package portallocator
import ( import (
"net" "net"
"testing" "testing"
_ "github.com/docker/libnetwork/netutils"
) )
func resetPortAllocator() { func resetPortAllocator() {

View File

@ -5,6 +5,8 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"testing" "testing"
_ "github.com/docker/libnetwork/netutils"
) )
func TestGet(t *testing.T) { func TestGet(t *testing.T) {