- Added more testcases for libnetwork API testing

- Added new error types for all of libnetwork errors

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
Jana Radhakrishnan 2015-04-16 05:01:29 +00:00
parent ec7d417a37
commit 56c3adda07
3 changed files with 310 additions and 22 deletions

63
libnetwork/error.go Normal file
View File

@ -0,0 +1,63 @@
package libnetwork
import (
"errors"
"fmt"
)
var (
// ErrNilNetworkDriver is returned if a nil network driver
// is passed to NewNetwork api.
ErrNilNetworkDriver = errors.New("nil NetworkDriver instance")
// ErrInvalidNetworkDriver is returned if an invalid driver
// instance is passed.
ErrInvalidNetworkDriver = errors.New("invalid driver bound to network")
)
// NetworkTypeError type is returned when the network type string is not
// known to libnetwork.
type NetworkTypeError string
func (nt NetworkTypeError) Error() string {
return fmt.Sprintf("unknown driver %q", string(nt))
}
// NetworkNameError is returned when a network with the same name already exists.
type NetworkNameError string
func (name NetworkNameError) Error() string {
return fmt.Sprintf("network with name %s already exists", string(name))
}
// UnknownNetworkError is returned when libnetwork could not find in it's database
// a network with the same name and id.
type UnknownNetworkError struct {
name string
id string
}
func (une *UnknownNetworkError) Error() string {
return fmt.Sprintf("unknown network %s id %s", une.name, une.id)
}
// ActiveEndpointsError is returned when a network is deleted which has active
// endpoints in it.
type ActiveEndpointsError struct {
name string
id string
}
func (aee *ActiveEndpointsError) Error() string {
return fmt.Sprintf("network with name %s id %s has active endpoints", aee.name, aee.id)
}
// UnknownEndpointError is returned when libnetwork could not find in it's database
// an endpoint with the same name and id.
type UnknownEndpointError struct {
name string
id string
}
func (uee *UnknownEndpointError) Error() string {
return fmt.Sprintf("unknown endpoint %s id %s", uee.name, uee.id)
}

View File

@ -8,15 +8,27 @@ import (
"github.com/docker/libnetwork"
_ "github.com/docker/libnetwork/drivers/bridge"
"github.com/docker/libnetwork/pkg/options"
"github.com/vishvananda/netlink"
)
var bridgeName = "dockertest0"
func TestSimplebridge(t *testing.T) {
bridge := &netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: bridgeName}}
netlink.LinkDel(bridge)
func createTestNetwork(networkType, networkName string, option options.Generic) (libnetwork.Network, error) {
controller := libnetwork.New()
driver, err := controller.NewNetworkDriver(networkType, option)
if err != nil {
return nil, err
}
network, err := controller.NewNetwork(driver, networkName, "")
if err != nil {
return nil, err
}
return network, nil
}
func TestSimplebridge(t *testing.T) {
ip, subnet, err := net.ParseCIDR("192.168.100.1/24")
if err != nil {
t.Fatal(err)
@ -36,7 +48,7 @@ func TestSimplebridge(t *testing.T) {
cidrv6.IP = ip
log.Debug("Adding a simple bridge")
options := options.Generic{
option := options.Generic{
"BridgeName": bridgeName,
"AddressIPv4": subnet,
"FixedCIDR": cidr,
@ -48,14 +60,7 @@ func TestSimplebridge(t *testing.T) {
"EnableIPForwarding": true,
"AllowNonDefaultBridge": true}
controller := libnetwork.New()
driver, err := controller.NewNetworkDriver("simplebridge", options)
if err != nil {
t.Fatal(err)
}
network, err := controller.NewNetwork(driver, "testnetwork", "")
network, err := createTestNetwork("simplebridge", "testnetwork", option)
if err != nil {
t.Fatal(err)
}
@ -73,3 +78,206 @@ func TestSimplebridge(t *testing.T) {
t.Fatal(err)
}
}
func TestUnknownDriver(t *testing.T) {
_, err := createTestNetwork("unknowndriver", "testnetwork", options.Generic{})
if err == nil {
t.Fatal("Expected to fail. But instead succeeded")
}
if _, ok := err.(libnetwork.NetworkTypeError); !ok {
t.Fatalf("Did not fail with expected error. Actual error: %v", err)
}
}
func TestNilDriver(t *testing.T) {
controller := libnetwork.New()
option := options.Generic{}
_, err := controller.NewNetwork(nil, "dummy", option)
if err == nil {
t.Fatal("Expected to fail. But instead succeeded")
}
if err != libnetwork.ErrNilNetworkDriver {
t.Fatalf("Did not fail with expected error. Actual error: %v", err)
}
}
func TestNoInitDriver(t *testing.T) {
controller := libnetwork.New()
option := options.Generic{}
_, err := controller.NewNetwork(&libnetwork.NetworkDriver{}, "dummy", option)
if err == nil {
t.Fatal("Expected to fail. But instead succeeded")
}
if err != libnetwork.ErrInvalidNetworkDriver {
t.Fatalf("Did not fail with expected error. Actual error: %v", err)
}
}
func TestDuplicateNetwork(t *testing.T) {
controller := libnetwork.New()
option := options.Generic{}
driver, err := controller.NewNetworkDriver("simplebridge", option)
if err != nil {
t.Fatal(err)
}
_, err = controller.NewNetwork(driver, "testnetwork", "")
if err != nil {
t.Fatal(err)
}
_, err = controller.NewNetwork(driver, "testnetwork", "")
if err == nil {
t.Fatal("Expected to fail. But instead succeeded")
}
if _, ok := err.(libnetwork.NetworkNameError); !ok {
t.Fatalf("Did not fail with expected error. Actual error: %v", err)
}
}
func TestNetworkName(t *testing.T) {
networkName := "testnetwork"
n, err := createTestNetwork("simplebridge", networkName, options.Generic{})
if err != nil {
t.Fatal(err)
}
if n.Name() != networkName {
t.Fatalf("Expected network name %s, got %s", networkName, n.Name())
}
}
func TestNetworkType(t *testing.T) {
networkType := "simplebridge"
n, err := createTestNetwork(networkType, "testnetwork", options.Generic{})
if err != nil {
t.Fatal(err)
}
if n.Type() != networkType {
t.Fatalf("Expected network type %s, got %s", networkType, n.Type())
}
}
func TestNetworkID(t *testing.T) {
networkType := "simplebridge"
n, err := createTestNetwork(networkType, "testnetwork", options.Generic{})
if err != nil {
t.Fatal(err)
}
if n.ID() == "" {
t.Fatal("Expected non-empty network id")
}
}
func TestDeleteNetworkWithActiveEndpoints(t *testing.T) {
option := options.Generic{
"BridgeName": bridgeName,
"AllowNonDefaultBridge": true}
network, err := createTestNetwork("simplebridge", "testnetwork", option)
if err != nil {
t.Fatal(err)
}
ep, _, err := network.CreateEndpoint("testep", "", "")
if err != nil {
t.Fatal(err)
}
err = network.Delete()
if err == nil {
t.Fatal("Expected to fail. But instead succeeded")
}
if _, ok := err.(*libnetwork.ActiveEndpointsError); !ok {
t.Fatalf("Did not fail with expected error. Actual error: %v", err)
}
// Done testing. Now cleanup.
if err := ep.Delete(); err != nil {
t.Fatal(err)
}
if err := network.Delete(); err != nil {
t.Fatal(err)
}
}
func TestUnknownNetwork(t *testing.T) {
option := options.Generic{
"BridgeName": bridgeName,
"AllowNonDefaultBridge": true}
network, err := createTestNetwork("simplebridge", "testnetwork", option)
if err != nil {
t.Fatal(err)
}
err = network.Delete()
if err != nil {
t.Fatal(err)
}
err = network.Delete()
if err == nil {
t.Fatal("Expected to fail. But instead succeeded")
}
if _, ok := err.(*libnetwork.UnknownNetworkError); !ok {
t.Fatalf("Did not fail with expected error. Actual error: %v", err)
}
}
func TestUnknownEndpoint(t *testing.T) {
ip, subnet, err := net.ParseCIDR("192.168.100.1/24")
if err != nil {
t.Fatal(err)
}
subnet.IP = ip
option := options.Generic{
"BridgeName": bridgeName,
"AddressIPv4": subnet,
"AllowNonDefaultBridge": true}
network, err := createTestNetwork("simplebridge", "testnetwork", option)
if err != nil {
t.Fatal(err)
}
ep, _, err := network.CreateEndpoint("testep", "", "")
if err != nil {
t.Fatal(err)
}
err = ep.Delete()
if err != nil {
t.Fatal(err)
}
err = ep.Delete()
if err == nil {
t.Fatal("Expected to fail. But instead succeeded")
}
if _, ok := err.(*libnetwork.UnknownEndpointError); !ok {
t.Fatalf("Did not fail with expected error. Actual error: %v", err)
}
// Done testing. Now cleanup
if err := network.Delete(); err != nil {
t.Fatal(err)
}
}

View File

@ -39,7 +39,6 @@ create network namespaces and allocate interfaces for containers to use.
package libnetwork
import (
"fmt"
"sync"
"github.com/docker/docker/pkg/common"
@ -84,6 +83,7 @@ type Endpoint interface {
// NetworkDriver provides a reference to driver and way to push driver specific config
type NetworkDriver struct {
networkType string
internalDriver driverapi.Driver
}
@ -121,19 +121,32 @@ func New() NetworkController {
func (c *controller) NewNetworkDriver(networkType string, options interface{}) (*NetworkDriver, error) {
d, ok := c.drivers[networkType]
if !ok {
return nil, fmt.Errorf("unknown driver %q", networkType)
return nil, NetworkTypeError(networkType)
}
if err := d.Config(options); err != nil {
return nil, err
}
return &NetworkDriver{internalDriver: d}, nil
return &NetworkDriver{networkType: networkType, internalDriver: d}, nil
}
// NewNetwork creates a new network of the specified networkType. The options
// NewNetwork creates a new network of the specified NetworkDriver. The options
// are driver specific and modeled in a generic way.
func (c *controller) NewNetwork(nd *NetworkDriver, name string, options interface{}) (Network, error) {
if nd == nil {
return nil, ErrNilNetworkDriver
}
c.Lock()
for _, n := range c.networks {
if n.name == name {
c.Unlock()
return nil, NetworkNameError(name)
}
}
c.Unlock()
network := &network{
name: name,
id: driverapi.UUID(common.GenerateRandomID()),
@ -143,7 +156,7 @@ func (c *controller) NewNetwork(nd *NetworkDriver, name string, options interfac
d := network.driver.internalDriver
if d == nil {
return nil, fmt.Errorf("invalid driver bound to network")
return nil, ErrInvalidNetworkDriver
}
if err := d.CreateNetwork(network.id, options); err != nil {
@ -166,7 +179,11 @@ func (n *network) ID() string {
}
func (n *network) Type() string {
return n.networkType
if n.driver == nil {
return ""
}
return n.driver.networkType
}
func (n *network) Delete() error {
@ -176,7 +193,7 @@ func (n *network) Delete() error {
_, ok := n.ctrlr.networks[n.id]
if !ok {
n.ctrlr.Unlock()
return fmt.Errorf("unknown network %s id %s", n.name, n.id)
return &UnknownNetworkError{name: n.name, id: string(n.id)}
}
n.Lock()
@ -184,7 +201,7 @@ func (n *network) Delete() error {
n.Unlock()
if numEps != 0 {
n.ctrlr.Unlock()
return fmt.Errorf("network %s has active endpoints", n.id)
return &ActiveEndpointsError{name: n.name, id: string(n.id)}
}
delete(n.ctrlr.networks, n.id)
@ -228,7 +245,7 @@ func (ep *endpoint) Delete() error {
_, ok := n.endpoints[ep.id]
if !ok {
n.Unlock()
return fmt.Errorf("unknown endpoint %s id %s", ep.name, ep.id)
return &UnknownEndpointError{name: ep.name, id: string(ep.id)}
}
delete(n.endpoints, ep.id)