func TestVIC(t *testing.T) { log.SetLevel(log.PanicLevel) options.IP = "127.0.0.1" options.Port = 5354 // BEGIN - Context initialization var bridgeNetwork object.NetworkReference n := object.NewNetwork(nil, types.ManagedObjectReference{}) n.InventoryPath = "testBridge" bridgeNetwork = n network.Config = network.Configuration{ BridgeNetwork: "bridge", ContainerNetworks: map[string]*network.ContainerNetwork{ "bridge": &network.ContainerNetwork{ Common: metadata.Common{ Name: "testBridge", }, PortGroup: bridgeNetwork, }, }, } // initialize the context err := network.Init() if err != nil { t.Fatalf("%s", err) } // create the container con := exec.NewContainer("foo") ip := net.IPv4(172, 16, 0, 2) // add it err = network.DefaultContext.AddContainer(con, "bridge", &ip) if err != nil { t.Fatalf("%s", err) } // bind it _, err = network.DefaultContext.BindContainer(con) if err != nil { t.Fatalf("%s", err) } server := NewServer(options) if server != nil { server.Start() } // END - Context initialization m := new(mdns.Msg) m.SetQuestion("foo.", mdns.TypeA) c := new(mdns.Client) r, _, err := c.Exchange(m, server.Addr()) if err != nil || len(r.Answer) == 0 { t.Fatalf("Exchange failed: %s", err) } m = new(mdns.Msg) m.SetQuestion("foo.bridge.", mdns.TypeA) r, _, err = c.Exchange(m, server.Addr()) if err != nil || len(r.Answer) == 0 { t.Fatalf("Exchange failed: %s", err) } server.Stop() server.Wait() }
func TestDeleteScope(t *testing.T) { ctx, err := NewContext(net.IPNet{IP: net.IPv4(172, 16, 0, 0), Mask: net.CIDRMask(12, 32)}, net.CIDRMask(16, 32)) if err != nil { t.Fatalf("NewContext() => (nil, %s), want (ctx, nil)", err) } foo, err := ctx.NewScope(BridgeScopeType, "foo", nil, nil, nil, nil) if err != nil { t.Fatalf("ctx.NewScope(%s, \"foo\", nil, nil, nil, nil) => (nil, %#v), want (foo, nil)", BridgeScopeType, err) } h := exec.NewContainer("container") options := &AddContainerOptions{ Scope: foo.Name(), } ctx.AddContainer(h, options) // bar is a scope with bound endpoints bar, err := ctx.NewScope(BridgeScopeType, "bar", nil, nil, nil, nil) if err != nil { t.Fatalf("ctx.NewScope(%s, \"bar\", nil, nil, nil, nil) => (nil, %#v), want (bar, nil)", BridgeScopeType, err) } h = exec.NewContainer("container2") options.Scope = bar.Name() ctx.AddContainer(h, options) ctx.BindContainer(h) baz, err := ctx.NewScope(BridgeScopeType, "bazScope", nil, nil, nil, nil) if err != nil { t.Fatalf("ctx.NewScope(%s, \"bazScope\", nil, nil, nil, nil) => (nil, %#v), want (baz, nil)", BridgeScopeType, err) } qux, err := ctx.NewScope(BridgeScopeType, "quxScope", nil, nil, nil, nil) if err != nil { t.Fatalf("ctx.NewScope(%s, \"quxScope\", nil, nil, nil, nil) => (nil, %#v), want (qux, nil)", BridgeScopeType, err) } var tests = []struct { name string err error }{ {"", ResourceNotFoundError{}}, {ctx.DefaultScope().Name(), fmt.Errorf("cannot delete builtin scopes")}, {bar.Name(), fmt.Errorf("cannot delete scope with bound endpoints")}, // full name {foo.Name(), nil}, // full id {baz.ID().String(), nil}, // partial id {qux.ID().String()[:6], nil}, } for _, te := range tests { err := ctx.DeleteScope(te.name) if te.err != nil { if err == nil { t.Fatalf("DeleteScope(%s) => nil, expected err", te.name) } if reflect.TypeOf(te.err) != reflect.TypeOf(err) { t.Fatalf("DeleteScope(%s) => %#v, want %#v", te.name, err, te.err) } continue } scopes, err := ctx.Scopes(&te.name) if _, ok := err.(ResourceNotFoundError); !ok || len(scopes) != 0 { t.Fatalf("scope %s not deleted", te.name) } } }
func TestContextRemoveContainer(t *testing.T) { hFoo := exec.NewContainer(uid.New()) ctx, err := NewContext(net.IPNet{IP: net.IPv4(172, 16, 0, 0), Mask: net.CIDRMask(12, 32)}, net.CIDRMask(16, 32)) if err != nil { t.Fatalf("NewContext() => (nil, %s), want (ctx, nil)", err) } scope, err := ctx.NewScope(BridgeScopeType, "scope", nil, nil, nil, nil) if err != nil { t.Fatalf("ctx.NewScope() => (nil, %s), want (scope, nil)", err) } options := &AddContainerOptions{ Scope: scope.Name(), } ctx.AddContainer(hFoo, options) ctx.BindContainer(hFoo) // container that is added to multiple bridge scopes hBar := exec.NewContainer(uid.New()) options.Scope = "default" ctx.AddContainer(hBar, options) options.Scope = scope.Name() ctx.AddContainer(hBar, options) var tests = []struct { h *exec.Handle scope string err error }{ {nil, "", fmt.Errorf("")}, // nil handle {hBar, "bar", fmt.Errorf("")}, // scope not found {hFoo, scope.Name(), fmt.Errorf("")}, // bound container {exec.NewContainer(uid.New()), "default", fmt.Errorf("")}, // container not part of scope {hBar, "default", nil}, {hBar, scope.Name(), nil}, } for i, te := range tests { var ne *executor.NetworkEndpoint if te.h != nil && te.h.ExecConfig.Networks != nil { ne = te.h.ExecConfig.Networks[te.scope] } err = ctx.RemoveContainer(te.h, te.scope) if te.err != nil { // expect error if err == nil { t.Fatalf("%d: ctx.RemoveContainer(%#v, %s) => nil want err", i, te.h, te.scope) } continue } s, err := ctx.resolveScope(te.scope) if err != nil { t.Fatalf(err.Error()) } if s.Container(uid.Parse(te.h.Container.ExecConfig.ID)) != nil { t.Fatalf("container %s is part of scope %s", te.h, s.Name()) } // should have a remove spec for NIC, if container was only part of one bridge scope dcs, err := te.h.Spec.FindNICs(context.TODO(), s.Network()) if err != nil { t.Fatalf(err.Error()) } found := false var d types.BaseVirtualDevice for _, dc := range dcs { if dc.GetVirtualDeviceConfigSpec().Operation != types.VirtualDeviceConfigSpecOperationRemove { continue } d = dc.GetVirtualDeviceConfigSpec().Device found = true break } // if a remove spec for the NIC was found, check if any other // network endpoints are still using it if found { for _, ne := range te.h.ExecConfig.Networks { if atoiOrZero(ne.ID) == spec.VirtualDeviceSlotNumber(d) { t.Fatalf("%d: NIC with pci slot %d is still in use by a network endpoint %#v", i, spec.VirtualDeviceSlotNumber(d), ne) } } } else if ne != nil { // check if remove spec for NIC should have been there for _, ne2 := range te.h.ExecConfig.Networks { if ne.ID == ne2.ID { t.Fatalf("%d: NIC with pci slot %s should have been removed", i, ne.ID) } } } // metadata should be gone if _, ok := te.h.ExecConfig.Networks[te.scope]; ok { t.Fatalf("%d: endpoint metadata for container still present in handle %#v", i, te.h.ExecConfig) } } }
func TestContextBindUnbindContainer(t *testing.T) { ctx, err := NewContext(net.IPNet{IP: net.IPv4(172, 16, 0, 0), Mask: net.CIDRMask(12, 32)}, net.CIDRMask(16, 32)) if err != nil { t.Fatalf("NewContext() => (nil, %s), want (ctx, nil)", err) } scope, err := ctx.NewScope(BridgeScopeType, "scope", nil, nil, nil, nil) if err != nil { t.Fatalf("ctx.NewScope(%s, %s, nil, nil, nil) => (nil, %s)", BridgeScopeType, "scope", err) } foo := exec.NewContainer(uid.New()) added := exec.NewContainer(uid.New()) staticIP := exec.NewContainer(uid.New()) ipErr := exec.NewContainer(uid.New()) alias := exec.NewContainer(uid.New()) aliasErr := exec.NewContainer(uid.New()) options := &AddContainerOptions{ Scope: ctx.DefaultScope().Name(), } // add a container to the default scope if err = ctx.AddContainer(added, options); err != nil { t.Fatalf("ctx.AddContainer(%s, %s, nil) => %s", added, ctx.DefaultScope().Name(), err) } // add a container with a static IP ip := net.IPv4(172, 16, 0, 10) options = &AddContainerOptions{ Scope: ctx.DefaultScope().Name(), IP: &ip, } if err = ctx.AddContainer(staticIP, options); err != nil { t.Fatalf("ctx.AddContainer(%s, %s, nil) => %s", staticIP, ctx.DefaultScope().Name(), err) } options = &AddContainerOptions{ Scope: scope.Name(), } if err = ctx.AddContainer(added, options); err != nil { t.Fatalf("ctx.AddContainer(%s, %s, nil) => %s", added, scope.Name(), err) } // add a container with an ip that is already taken, // causing Scope.BindContainer call to fail gw := ctx.DefaultScope().Gateway() options = &AddContainerOptions{ Scope: scope.Name(), } ctx.AddContainer(ipErr, options) options = &AddContainerOptions{ Scope: ctx.DefaultScope().Name(), IP: &gw, } ctx.AddContainer(ipErr, options) // add a container with correct aliases options = &AddContainerOptions{ Scope: ctx.DefaultScope().Name(), Aliases: []string{"added:foo", ":bar"}, } if err = ctx.AddContainer(alias, options); err != nil { t.Fatalf("ctx.AddContainer(%s, %s, nil) => %s", alias, ctx.DefaultScope().Name(), err) } // add a container with incorrect aliases options = &AddContainerOptions{ Scope: ctx.DefaultScope().Name(), Aliases: []string{"cloud:foo", "bar"}, } if err = ctx.AddContainer(aliasErr, options); err != nil { t.Fatalf("ctx.AddContainer(%s, %s, nil) => %s", aliasErr, ctx.DefaultScope().Name(), err) } var tests = []struct { i int h *exec.Handle scopes []string ips []net.IP static bool err error }{ // container not added to scope {0, foo, []string{}, []net.IP{}, false, fmt.Errorf("")}, // container has bad ip address {1, ipErr, []string{}, nil, false, fmt.Errorf("")}, // successful container bind {2, added, []string{ctx.DefaultScope().Name(), scope.Name()}, []net.IP{net.IPv4(172, 16, 0, 2), net.IPv4(172, 17, 0, 2)}, false, nil}, {3, staticIP, []string{ctx.DefaultScope().Name()}, []net.IP{net.IPv4(172, 16, 0, 10)}, true, nil}, {4, alias, []string{ctx.DefaultScope().Name()}, []net.IP{net.IPv4(172, 16, 0, 3)}, false, nil}, {5, aliasErr, []string{ctx.DefaultScope().Name()}, []net.IP{}, false, fmt.Errorf("")}, } for _, te := range tests { eps, err := ctx.BindContainer(te.h) if te.err != nil { // expect an error if err == nil || eps != nil { t.Fatalf("%d: ctx.BindContainer(%s) => (%#v, %#v), want (%#v, %#v)", te.i, te.h, eps, err, nil, te.err) } con := ctx.Container(uid.Parse(te.h.Container.ExecConfig.ID)) if con != nil { t.Fatalf("%d: ctx.BindContainer(%s) added container %#v", te.i, te.h, con) } continue } // check if the correct endpoints were added con := ctx.Container(uid.Parse(te.h.Container.ExecConfig.ID)) if con == nil { t.Fatalf("%d: ctx.Container(%s) => nil, want %s", te.i, te.h.Container.ExecConfig.ID, te.h.Container.ExecConfig.ID) } if len(con.Scopes()) != len(te.scopes) { t.Fatalf("%d: len(con.Scopes()) %#v != len(te.scopes) %#v", te.i, con.Scopes(), te.scopes) } // check endpoints for i, s := range te.scopes { found := false for _, e := range eps { if e.Scope().Name() != s { continue } found = true if !e.Gateway().Equal(e.Scope().Gateway()) { t.Fatalf("%d: ctx.BindContainer(%s) => endpoint gateway %s, want %s", te.i, te.h, e.Gateway(), e.Scope().Gateway()) } if !e.IP().Equal(te.ips[i]) { t.Fatalf("%d: ctx.BindContainer(%s) => endpoint IP %s, want %s", te.i, te.h, e.IP(), te.ips[i]) } if e.Subnet().String() != e.Scope().Subnet().String() { t.Fatalf("%d: ctx.BindContainer(%s) => endpoint subnet %s, want %s", te.i, te.h, e.Subnet(), e.Scope().Subnet()) } ne := te.h.ExecConfig.Networks[s] if !ne.Static.IP.Equal(te.ips[i]) { t.Fatalf("%d: ctx.BindContainer(%s) => metadata endpoint IP %s, want %s", te.i, te.h, ne.Static.IP, te.ips[i]) } if ne.Static.Mask.String() != e.Scope().Subnet().Mask.String() { t.Fatalf("%d: ctx.BindContainer(%s) => metadata endpoint IP mask %s, want %s", te.i, te.h, ne.Static.Mask.String(), e.Scope().Subnet().Mask.String()) } if !ne.Network.Gateway.IP.Equal(e.Scope().Gateway()) { t.Fatalf("%d: ctx.BindContainer(%s) => metadata endpoint gateway %s, want %s", te.i, te.h, ne.Network.Gateway.IP, e.Scope().Gateway()) } if ne.Network.Gateway.Mask.String() != e.Scope().Subnet().Mask.String() { t.Fatalf("%d: ctx.BindContainer(%s) => metadata endpoint gateway mask %s, want %s", te.i, te.h, ne.Network.Gateway.Mask.String(), e.Scope().Subnet().Mask.String()) } break } if !found { t.Fatalf("%d: ctx.BindContainer(%s) => endpoint for scope %s not added", te.i, te.h, s) } } } tests = []struct { i int h *exec.Handle scopes []string ips []net.IP static bool err error }{ // container not found {0, foo, []string{}, nil, false, fmt.Errorf("")}, // container has bad ip address {1, ipErr, []string{ctx.DefaultScope().Name(), scope.Name()}, nil, false, fmt.Errorf("")}, // successful container unbind {2, added, []string{ctx.DefaultScope().Name(), scope.Name()}, nil, false, nil}, {3, staticIP, []string{ctx.DefaultScope().Name()}, nil, true, nil}, {4, alias, []string{ctx.DefaultScope().Name()}, nil, false, nil}, {5, aliasErr, []string{ctx.DefaultScope().Name()}, nil, false, fmt.Errorf("")}, } // test UnbindContainer for _, te := range tests { eps, err := ctx.UnbindContainer(te.h) if te.err != nil { if err == nil { t.Fatalf("%d: ctx.UnbindContainer(%s) => nil, want err", te.i, te.h) } continue } // container should not be there con := ctx.Container(uid.Parse(te.h.Container.ExecConfig.ID)) if con != nil { t.Fatalf("%d: ctx.Container(%s) => %#v, want nil", te.i, te.h, con) } for _, s := range te.scopes { found := false for _, e := range eps { if e.Scope().Name() == s { found = true } } if !found { t.Fatalf("%d: ctx.UnbindContainer(%s) did not return endpoint for scope %s. Endpoints: %+v", te.i, te.h, s, eps) } // container should not be part of scope scopes, err := ctx.Scopes(&s) if err != nil || len(scopes) != 1 { t.Fatalf("%d: ctx.Scopes(%s) => (%#v, %#v)", te.i, s, scopes, err) } if scopes[0].Container(uid.Parse(te.h.Container.ExecConfig.ID)) != nil { t.Fatalf("%d: container %s is still part of scope %s", te.i, te.h.Container.ExecConfig.ID, s) } // check if endpoint is still there, but without the ip ne, ok := te.h.ExecConfig.Networks[s] if !ok { t.Fatalf("%d: container endpoint not present in %v", te.i, te.h.ExecConfig) } if !te.static && ne.Static != nil { t.Fatalf("%d: endpoint IP should be nil in %v", te.i, ne) } if te.static && (ne.Static == nil || ne.Static.IP.Equal(net.IPv4zero)) { t.Fatalf("%d: endpoint IP should not be zero in %v", te.i, ne) } } } }
func TestContextAddContainer(t *testing.T) { ctx, err := NewContext(net.IPNet{IP: net.IPv4(172, 16, 0, 0), Mask: net.CIDRMask(12, 32)}, net.CIDRMask(16, 32)) if err != nil { t.Fatalf("NewContext() => (nil, %s), want (ctx, nil)", err) return } h := exec.NewContainer("foo") var devices object.VirtualDeviceList backing, _ := ctx.DefaultScope().Network().EthernetCardBackingInfo(context.TODO()) specWithEthCard := &spec.VirtualMachineConfigSpec{ VirtualMachineConfigSpec: &types.VirtualMachineConfigSpec{}, } var d types.BaseVirtualDevice if d, err = devices.CreateEthernetCard("vmxnet3", backing); err == nil { d.GetVirtualDevice().SlotInfo = &types.VirtualDevicePciBusSlotInfo{ PciSlotNumber: 1111, } devices = append(devices, d) var cs []types.BaseVirtualDeviceConfigSpec if cs, err = devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd); err == nil { specWithEthCard.DeviceChange = cs } } if err != nil { t.Fatalf(err.Error()) } aecErr := func(_ *exec.Handle, _ *Scope) (types.BaseVirtualDevice, error) { return nil, fmt.Errorf("error") } otherScope, err := ctx.NewScope(BridgeScopeType, "other", nil, net.IPv4(0, 0, 0, 0), nil, nil) if err != nil { t.Fatalf("failed to add scope") } hBar := exec.NewContainer(uid.New()) var tests = []struct { aec func(h *exec.Handle, s *Scope) (types.BaseVirtualDevice, error) h *exec.Handle s *spec.VirtualMachineConfigSpec scope string ip *net.IP err error }{ // nil handle {nil, nil, nil, "", nil, fmt.Errorf("")}, // scope not found {nil, h, nil, "foo", nil, ResourceNotFoundError{}}, // addEthernetCard returns error {aecErr, h, nil, "default", nil, fmt.Errorf("")}, // add a container {nil, h, nil, "default", nil, nil}, // container already added {nil, h, nil, "default", nil, nil}, {nil, hBar, specWithEthCard, "default", nil, nil}, {nil, hBar, nil, otherScope.Name(), nil, nil}, } origAEC := addEthernetCard defer func() { addEthernetCard = origAEC }() for i, te := range tests { // setup addEthernetCard = origAEC scopy := &spec.VirtualMachineConfigSpec{} if te.h != nil { te.h.SetSpec(te.s) if te.h.Spec != nil { *scopy = *te.h.Spec } } if te.aec != nil { addEthernetCard = te.aec } options := &AddContainerOptions{ Scope: te.scope, IP: te.ip, } err := ctx.AddContainer(te.h, options) if te.err != nil { // expect an error if err == nil { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) => nil want err", i, te.h, te.scope, te.ip) } if reflect.TypeOf(err) != reflect.TypeOf(te.err) { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) => (%v, %v) want (%v, %v)", i, te.h, te.scope, te.ip, err, te.err, err, te.err) } if _, ok := te.err.(DuplicateResourceError); ok { continue } // verify no device changes in the spec if te.s != nil { if len(scopy.DeviceChange) != len(h.Spec.DeviceChange) { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) added device", i, te.h, te.scope, te.ip) } } continue } if err != nil { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) => %s want nil", i, te.h, te.scope, te.ip, err) } // verify the container was not added to the scope s, _ := ctx.resolveScope(te.scope) if s != nil && te.h != nil { c := s.Container(uid.Parse(te.h.Container.ExecConfig.ID)) if c != nil { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) added container", i, te.h, te.scope, te.ip) } } // spec should have a nic attached to the scope's network var dev types.BaseVirtualDevice dcs, err := te.h.Spec.FindNICs(context.TODO(), s.Network()) if len(dcs) != 1 { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) more than one NIC added for scope %s", i, te.h, te.scope, te.ip, s.Network()) } dev = dcs[0].GetVirtualDeviceConfigSpec().Device if spec.VirtualDeviceSlotNumber(dev) == spec.NilSlot { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) NIC added has nil pci slot", i, te.h, te.scope, te.ip) } // spec metadata should be updated with endpoint info ne, ok := te.h.ExecConfig.Networks[s.Name()] if !ok { t.Fatalf("case %d: ctx.AddContainer(%v, %s, %s) no network endpoint info added", i, te.h, te.scope, te.ip) } if spec.VirtualDeviceSlotNumber(dev) != atoiOrZero(ne.ID) { t.Fatalf("case %d; ctx.AddContainer(%v, %s, %s) => ne.ID == %d, want %d", i, te.h, te.scope, te.ip, atoiOrZero(ne.ID), spec.VirtualDeviceSlotNumber(dev)) } if ne.Network.Name != s.Name() { t.Fatalf("case %d; ctx.AddContainer(%v, %s, %s) => ne.NetworkName == %s, want %s", i, te.h, te.scope, te.ip, ne.Network.Name, s.Name()) } if te.ip != nil && !te.ip.Equal(ne.Static.IP) { t.Fatalf("case %d; ctx.AddContainer(%v, %s, %s) => ne.Static.IP == %s, want %s", i, te.h, te.scope, te.ip, ne.Static.IP, te.ip) } if te.ip == nil && ne.Static != nil { t.Fatalf("case %d; ctx.AddContainer(%v, %s, %s) => ne.Static.IP == %s, want %s", i, te.h, te.scope, te.ip, ne.Static.IP, net.IPv4zero) } } }
func TestScopeAddRemoveContainer(t *testing.T) { var err error ctx, err := NewContext(net.IPNet{IP: net.IPv4(172, 16, 0, 0), Mask: net.CIDRMask(12, 32)}, net.CIDRMask(16, 32)) if err != nil { t.Errorf("NewContext() => (nil, %s), want (ctx, nil)", err) return } s := ctx.defaultScope idFoo := uid.New() idBar := uid.New() var tests1 = []struct { c *Container ip *net.IP out *Endpoint err error }{ // no container {nil, nil, nil, fmt.Errorf("")}, // add a new container to scope {&Container{id: idFoo}, nil, &Endpoint{ip: net.IPv4(172, 16, 0, 2), subnet: s.subnet, gateway: s.gateway}, nil}, // container already part of scope {&Container{id: idFoo}, nil, nil, DuplicateResourceError{}}, // container with ip {&Container{id: idBar}, makeIP(172, 16, 0, 3), &Endpoint{ip: net.IPv4(172, 16, 0, 3), subnet: s.subnet, gateway: s.gateway, static: true}, nil}, } for _, te := range tests1 { var e *Endpoint e, err = s.addContainer(te.c, te.ip) if te.err != nil { if err == nil { t.Errorf("s.AddContainer() => (_, nil), want (_, err)") continue } if reflect.TypeOf(err) != reflect.TypeOf(te.err) { t.Errorf("s.AddContainer() => (_, %v), want (_, %v)", reflect.TypeOf(err), reflect.TypeOf(te.err)) continue } if te.c == nil { continue } // for any other error other than DuplicateResourcError // verify that the container was not added if _, ok := err.(DuplicateResourceError); !ok { c := s.Container(te.c.ID()) if c != nil { t.Errorf("s.Container(%s) => (%v, %v), want (nil, err)", te.c.ID(), c, err) } } continue } if !e.IP().Equal(te.out.IP()) { t.Errorf("s.AddContainer() => e.IP() == %v, want e.IP() == %v", e.IP(), te.out.IP()) continue } if !e.Gateway().Equal(te.out.Gateway()) { t.Errorf("s.AddContainer() => e.Gateway() == %v, want e.Gateway() == %v", e.Gateway(), te.out.Gateway()) continue } if e.subnet.String() != s.subnet.String() { t.Errorf("s.AddContainer() => e.subnet == %s, want e.subnet == %s", e.subnet, s.subnet) continue } if e.static != te.out.static { t.Errorf("s.AddContainer() => e.static == %#v, want e.static == %#v", e.static, te.out.static) } if e.container.ID() != te.c.ID() { t.Errorf("s.AddContainer() => e.container == %s, want e.container == %s", e.container.ID(), te.c.ID()) continue } found := false for _, e1 := range s.Endpoints() { if e1 == e { found = true break } } if !found { t.Errorf("s.endpoints does not contain %v", e) } c := s.Container(te.c.id) if c == nil { t.Errorf("s.Container(%s) => nil, want %v", te.c.ID(), te.c) continue } if c.Endpoint(s) != e { t.Errorf("container %s does not contain %v", te.c.ID(), e) } } options := &AddContainerOptions{ Scope: ctx.defaultScope.Name(), } bound := exec.NewContainer("bound") ctx.AddContainer(bound, options) ctx.BindContainer(bound) // test RemoveContainer var tests2 = []struct { c *Container err error }{ // container not found {&Container{id: "c1"}, ResourceNotFoundError{}}, // remove a container {s.Container(idFoo), nil}, } for _, te := range tests2 { err = s.removeContainer(te.c) if te.err != nil { if err == nil { t.Errorf("s.RemoveContainer() => nil, want %v", te.err) } continue } // container was removed, verify if err != nil { t.Errorf("s.RemoveContainer() => %s, want nil", err) continue } c := s.Container(te.c.ID()) if c != nil { t.Errorf("s.RemoveContainer() did not remove container %s", te.c.ID()) continue } for _, e := range s.endpoints { if e.container.ID() == te.c.ID() { t.Errorf("s.RemoveContainer() did not remove endpoint for container %s", te.c.ID()) break } } } }