Test coverage on bridge

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
This commit is contained in:
Arnaud Porterie 2015-02-24 18:41:17 -08:00
parent 8ca185e2ee
commit 3845ec20c4
10 changed files with 340 additions and 15 deletions

View File

@ -0,0 +1,53 @@
package bridge
import (
"net"
"testing"
"github.com/docker/libnetwork"
)
func TestCreate(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
config := &Configuration{BridgeName: DefaultBridgeName}
netw, err := Create(config)
if err != nil {
t.Fatalf("Failed to create bridge: %v", err)
}
if expected := NetworkType; netw.Type() != NetworkType {
t.Fatalf("Expected networkType %q, got %q", expected, netw.Type())
}
}
func TestCreateFail(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
config := &Configuration{BridgeName: "dummy0"}
if _, err := Create(config); err == nil {
t.Fatal("Bridge creation was expected to fail")
}
}
func TestCreateFullOptions(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
config := &Configuration{
BridgeName: DefaultBridgeName,
EnableIPv6: true,
FixedCIDR: bridgeNetworks[0],
EnableIPTables: true,
EnableIPForwarding: true,
}
_, config.FixedCIDRv6, _ = net.ParseCIDR("2001:db8::/48")
netw, err := Create(config)
if err != nil {
t.Fatalf("Failed to create bridge: %v", err)
}
if expected := NetworkType; netw.Type() != NetworkType {
t.Fatalf("Expected networkType %q, got %q", expected, netw.Type())
}
}

View File

@ -44,5 +44,8 @@ func (i *Interface) Addresses() (netlink.Addr, []netlink.Addr, error) {
return netlink.Addr{}, nil, err
}
if len(v4addr) == 0 {
return netlink.Addr{}, v6addr, nil
}
return v4addr[0], v6addr, nil
}

View File

@ -0,0 +1,32 @@
package bridge
import (
"testing"
"github.com/docker/libnetwork"
"github.com/vishvananda/netlink"
)
func TestInterfaceDefaultName(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
if inf := NewInterface(&Configuration{}); inf.Config.BridgeName != DefaultBridgeName {
t.Fatalf("Expected default interface name %q, got %q", DefaultBridgeName, inf.Config.BridgeName)
}
}
func TestAddressesEmptyInterface(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
inf := NewInterface(&Configuration{})
addrv4, addrsv6, err := inf.Addresses()
if err != nil {
t.Fatalf("Failed to get addresses of default interface: %v", err)
}
if expected := (netlink.Addr{}); addrv4 != expected {
t.Fatalf("Default interface has unexpected IPv4: %s", addrv4)
}
if len(addrsv6) != 0 {
t.Fatalf("Default interface has unexpected IPv6: %v", addrsv6)
}
}

View File

@ -0,0 +1,53 @@
package bridge
import (
"bytes"
"testing"
)
func TestResolveConfRead(t *testing.T) {
b, err := readResolvConf()
if err != nil {
t.Fatalf("Failed to read resolv.conf: %v", err)
}
if b == nil {
t.Fatal("Reading resolv.conf returned no content")
}
}
func TestResolveConfReadLines(t *testing.T) {
commentChar := []byte("#")
b, _ := readResolvConf()
lines := getLines(b, commentChar)
if lines == nil {
t.Fatal("Failed to read resolv.conf lines")
}
for _, line := range lines {
if bytes.Index(line, commentChar) != -1 {
t.Fatal("Returned comment content from resolv.conf")
}
}
}
func TestResolvConfNameserversAsCIDR(t *testing.T) {
resolvConf := `# Commented line
nameserver 1.2.3.4
nameserver 5.6.7.8 # Test
`
cidrs := getNameserversAsCIDR([]byte(resolvConf))
if expected := 2; len(cidrs) != expected {
t.Fatalf("Expected %d nameservers, got %d", expected, len(cidrs))
}
expected := []string{"1.2.3.4/32", "5.6.7.8/32"}
for i, exp := range expected {
if cidrs[i] != exp {
t.Fatalf("Expected nameservers %s, got %s", exp, cidrs[i])
}
}
}

View File

@ -1,6 +1,8 @@
package bridge
import (
"fmt"
log "github.com/Sirupsen/logrus"
"github.com/docker/docker/daemon/networkdriver/ipallocator"
)
@ -12,5 +14,9 @@ func SetupFixedCIDRv4(i *Interface) error {
}
log.Debugf("Using IPv4 subnet: %v", i.Config.FixedCIDR)
return ipallocator.RegisterSubnet(addrv4.IPNet, i.Config.FixedCIDR)
if err := ipallocator.RegisterSubnet(addrv4.IPNet, i.Config.FixedCIDR); err != nil {
return fmt.Errorf("Setup FixedCIDRv4 failed for subnet %s in %s: %v", i.Config.FixedCIDR, addrv4.IPNet, err)
}
return nil
}

View File

@ -0,0 +1,59 @@
package bridge
import (
"net"
"testing"
"github.com/docker/docker/daemon/networkdriver/ipallocator"
"github.com/docker/libnetwork"
)
func TestSetupFixedCIDRv4(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
br := &Interface{
Config: &Configuration{
BridgeName: DefaultBridgeName,
AddressIPv4: &net.IPNet{IP: net.ParseIP("192.168.1.1"), Mask: net.CIDRMask(16, 32)},
FixedCIDR: &net.IPNet{IP: net.ParseIP("192.168.2.0"), Mask: net.CIDRMask(24, 32)},
},
}
if err := SetupDevice(br); err != nil {
t.Fatalf("Bridge creation failed: %v", err)
}
if err := SetupBridgeIPv4(br); err != nil {
t.Fatalf("Assign IPv4 to bridge failed: %v", err)
}
if err := SetupFixedCIDRv4(br); err != nil {
t.Fatalf("Failed to setup bridge FixedCIDRv4: %v", err)
}
if ip, err := ipallocator.RequestIP(br.Config.FixedCIDR, nil); err != nil {
t.Fatalf("Failed to request IP to allocator: %v", err)
} else if expected := "192.168.2.1"; ip.String() != expected {
t.Fatalf("Expected allocated IP %s, got %s", expected, ip)
}
}
func TestSetupBadFixedCIDRv4(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
br := &Interface{
Config: &Configuration{
BridgeName: DefaultBridgeName,
AddressIPv4: &net.IPNet{IP: net.ParseIP("192.168.1.1"), Mask: net.CIDRMask(24, 32)},
FixedCIDR: &net.IPNet{IP: net.ParseIP("192.168.2.0"), Mask: net.CIDRMask(24, 32)},
},
}
if err := SetupDevice(br); err != nil {
t.Fatalf("Bridge creation failed: %v", err)
}
if err := SetupBridgeIPv4(br); err != nil {
t.Fatalf("Assign IPv4 to bridge failed: %v", err)
}
if err := SetupFixedCIDRv4(br); err == nil {
t.Fatal("Setup bridge FixedCIDRv4 should have failed")
}
}

View File

@ -105,13 +105,11 @@ func checkRouteOverlaps(toCheck *net.IPNet) error {
}
func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
if len(netX.IP) == len(netY.IP) {
if firstIP, _ := networkRange(netX); netY.Contains(firstIP) {
return true
}
if firstIP, _ := networkRange(netY); netX.Contains(firstIP) {
return true
}
if firstIP, _ := networkRange(netX); netY.Contains(firstIP) {
return true
}
if firstIP, _ := networkRange(netY); netX.Contains(firstIP) {
return true
}
return false
}

View File

@ -1,6 +1,10 @@
package bridge
import "fmt"
import (
"fmt"
"github.com/vishvananda/netlink"
)
func SetupVerifyConfiguredAddresses(i *Interface) error {
// Fetch a single IPv4 and a slice of IPv6 addresses from the bridge.
@ -9,6 +13,11 @@ func SetupVerifyConfiguredAddresses(i *Interface) error {
return err
}
// Verify that the bridge does have an IPv4 address.
if addrv4.IPNet == nil {
return fmt.Errorf("Bridge has no IPv4 address configured")
}
// Verify that the bridge IPv4 address matches the requested configuration.
if i.Config.AddressIPv4 != nil && !addrv4.IP.Equal(i.Config.AddressIPv4.IP) {
return fmt.Errorf("Bridge IPv4 (%s) does not match requested configuration %s", addrv4.IP, i.Config.AddressIPv4.IP)
@ -16,11 +25,18 @@ func SetupVerifyConfiguredAddresses(i *Interface) error {
// Verify that one of the bridge IPv6 addresses matches the requested
// configuration.
for _, addrv6 := range addrsv6 {
if addrv6.String() == BridgeIPv6.String() {
return nil
}
if i.Config.EnableIPv6 && !findIPv6Address(netlink.Addr{IPNet: BridgeIPv6}, addrsv6) {
return fmt.Errorf("Bridge IPv6 addresses do not match the expected bridge configuration %s", BridgeIPv6)
}
return fmt.Errorf("Bridge IPv6 addresses do not match the expected bridge configuration %s", BridgeIPv6)
return nil
}
func findIPv6Address(addr netlink.Addr, addresses []netlink.Addr) bool {
for _, addrv6 := range addresses {
if addrv6.String() == addr.String() {
return true
}
}
return false
}

View File

@ -0,0 +1,105 @@
package bridge
import (
"net"
"testing"
"github.com/docker/libnetwork"
"github.com/vishvananda/netlink"
)
func setupVerifyTest(t *testing.T) *Interface {
inf := &Interface{Config: &Configuration{}}
br := netlink.Bridge{}
br.LinkAttrs.Name = "default0"
if err := netlink.LinkAdd(&br); err == nil {
inf.Link = &br
} else {
t.Fatalf("Failed to create bridge interface: %v", err)
}
return inf
}
func TestSetupVerify(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
addrv4 := net.IPv4(192, 168, 1, 1)
inf := setupVerifyTest(t)
inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: inf.Config.AddressIPv4}); err != nil {
t.Fatalf("Failed to assign IPv4 %s to interface: %v", inf.Config.AddressIPv4, err)
}
if err := SetupVerifyConfiguredAddresses(inf); err != nil {
t.Fatalf("Address verification failed: %v", err)
}
}
func TestSetupVerifyBad(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
addrv4 := net.IPv4(192, 168, 1, 1)
inf := setupVerifyTest(t)
inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
ipnet := &net.IPNet{IP: net.IPv4(192, 168, 1, 2), Mask: addrv4.DefaultMask()}
if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: ipnet}); err != nil {
t.Fatalf("Failed to assign IPv4 %s to interface: %v", ipnet, err)
}
if err := SetupVerifyConfiguredAddresses(inf); err == nil {
t.Fatal("Address verification was expected to fail")
}
}
func TestSetupVerifyMissing(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
addrv4 := net.IPv4(192, 168, 1, 1)
inf := setupVerifyTest(t)
inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
if err := SetupVerifyConfiguredAddresses(inf); err == nil {
t.Fatal("Address verification was expected to fail")
}
}
func TestSetupVerifyIPv6(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
addrv4 := net.IPv4(192, 168, 1, 1)
inf := setupVerifyTest(t)
inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
inf.Config.EnableIPv6 = true
if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: BridgeIPv6}); err != nil {
t.Fatalf("Failed to assign IPv6 %s to interface: %v", BridgeIPv6, err)
}
if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: inf.Config.AddressIPv4}); err != nil {
t.Fatalf("Failed to assign IPv4 %s to interface: %v", inf.Config.AddressIPv4, err)
}
if err := SetupVerifyConfiguredAddresses(inf); err != nil {
t.Fatalf("Address verification failed: %v", err)
}
}
func TestSetupVerifyIPv6Missing(t *testing.T) {
defer libnetwork.SetupTestNetNS(t)()
addrv4 := net.IPv4(192, 168, 1, 1)
inf := setupVerifyTest(t)
inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
inf.Config.EnableIPv6 = true
if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: inf.Config.AddressIPv4}); err != nil {
t.Fatalf("Failed to assign IPv4 %s to interface: %v", inf.Config.AddressIPv4, err)
}
if err := SetupVerifyConfiguredAddresses(inf); err == nil {
t.Fatal("Address verification was expected to fail")
}
}

View File

@ -17,7 +17,7 @@
// // For each new container: allocate IP and interfaces. The returned network
// // settings will be used for container infos (inspect and such), as well as
// // iptables rules for port publishing.
// interfaces, err := network.CreateInterfaces(containerID)
// interfaces, err := network.Link(containerID)
// if err != nil {
// return err
// }