github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/libnetwork/api/api_test.go (about)

     1  package api
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"net/http"
    10  	"os"
    11  	"regexp"
    12  	"runtime"
    13  	"testing"
    14  
    15  	"github.com/docker/docker/pkg/reexec"
    16  	"github.com/docker/libnetwork"
    17  	"github.com/docker/libnetwork/datastore"
    18  	"github.com/docker/libnetwork/netlabel"
    19  	"github.com/docker/libnetwork/options"
    20  	"github.com/docker/libnetwork/testutils"
    21  	"github.com/docker/libnetwork/types"
    22  )
    23  
    24  const (
    25  	bridgeNetType = "bridge"
    26  	bridgeName    = "docker0"
    27  )
    28  
    29  func i2s(i interface{}) string {
    30  	s, ok := i.(string)
    31  	if !ok {
    32  		panic(fmt.Sprintf("Failed i2s for %v", i))
    33  	}
    34  	return s
    35  }
    36  
    37  func i2e(i interface{}) *endpointResource {
    38  	s, ok := i.(*endpointResource)
    39  	if !ok {
    40  		panic(fmt.Sprintf("Failed i2e for %v", i))
    41  	}
    42  	return s
    43  }
    44  
    45  func i2eL(i interface{}) []*endpointResource {
    46  	s, ok := i.([]*endpointResource)
    47  	if !ok {
    48  		panic(fmt.Sprintf("Failed i2eL for %v", i))
    49  	}
    50  	return s
    51  }
    52  
    53  func i2n(i interface{}) *networkResource {
    54  	s, ok := i.(*networkResource)
    55  	if !ok {
    56  		panic(fmt.Sprintf("Failed i2n for %v", i))
    57  	}
    58  	return s
    59  }
    60  
    61  func i2nL(i interface{}) []*networkResource {
    62  	s, ok := i.([]*networkResource)
    63  	if !ok {
    64  		panic(fmt.Sprintf("Failed i2nL for %v", i))
    65  	}
    66  	return s
    67  }
    68  
    69  func i2sb(i interface{}) *sandboxResource {
    70  	s, ok := i.(*sandboxResource)
    71  	if !ok {
    72  		panic(fmt.Sprintf("Failed i2sb for %v", i))
    73  	}
    74  	return s
    75  }
    76  
    77  func i2sbL(i interface{}) []*sandboxResource {
    78  	s, ok := i.([]*sandboxResource)
    79  	if !ok {
    80  		panic(fmt.Sprintf("Failed i2sbL for %v", i))
    81  	}
    82  	return s
    83  }
    84  
    85  func createTestNetwork(t *testing.T, network string) (libnetwork.NetworkController, libnetwork.Network) {
    86  	// Cleanup local datastore file
    87  	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
    88  
    89  	c, err := libnetwork.New()
    90  	if err != nil {
    91  		t.Fatal(err)
    92  	}
    93  
    94  	netOption := options.Generic{
    95  		netlabel.GenericData: options.Generic{
    96  			"BridgeName": network,
    97  		},
    98  	}
    99  	netGeneric := libnetwork.NetworkOptionGeneric(netOption)
   100  	nw, err := c.NewNetwork(bridgeNetType, network, "", netGeneric)
   101  	if err != nil {
   102  		t.Fatal(err)
   103  	}
   104  
   105  	return c, nw
   106  }
   107  
   108  func getExposedPorts() []types.TransportPort {
   109  	return []types.TransportPort{
   110  		{Proto: types.TCP, Port: uint16(5000)},
   111  		{Proto: types.UDP, Port: uint16(400)},
   112  		{Proto: types.TCP, Port: uint16(600)},
   113  	}
   114  }
   115  
   116  func getPortMapping() []types.PortBinding {
   117  	return []types.PortBinding{
   118  		{Proto: types.TCP, Port: uint16(230), HostPort: uint16(23000)},
   119  		{Proto: types.UDP, Port: uint16(200), HostPort: uint16(22000)},
   120  		{Proto: types.TCP, Port: uint16(120), HostPort: uint16(12000)},
   121  	}
   122  }
   123  
   124  func TestMain(m *testing.M) {
   125  	if reexec.Init() {
   126  		return
   127  	}
   128  	os.Exit(m.Run())
   129  }
   130  
   131  func TestSandboxOptionParser(t *testing.T) {
   132  	hn := "host1"
   133  	dn := "docker.com"
   134  	hp := "/etc/hosts"
   135  	rc := "/etc/resolv.conf"
   136  	dnss := []string{"8.8.8.8", "172.28.34.5"}
   137  	ehs := []extraHost{{Name: "extra1", Address: "172.28.9.1"}, {Name: "extra2", Address: "172.28.9.2"}}
   138  
   139  	sb := sandboxCreate{
   140  		HostName:          hn,
   141  		DomainName:        dn,
   142  		HostsPath:         hp,
   143  		ResolvConfPath:    rc,
   144  		DNS:               dnss,
   145  		ExtraHosts:        ehs,
   146  		UseDefaultSandbox: true,
   147  	}
   148  
   149  	if len(sb.parseOptions()) != 9 {
   150  		t.Fatal("Failed to generate all libnetwork.SandboxOption methods")
   151  	}
   152  }
   153  
   154  func TestJson(t *testing.T) {
   155  	nc := networkCreate{NetworkType: bridgeNetType}
   156  	b, err := json.Marshal(nc)
   157  	if err != nil {
   158  		t.Fatal(err)
   159  	}
   160  
   161  	var ncp networkCreate
   162  	err = json.Unmarshal(b, &ncp)
   163  	if err != nil {
   164  		t.Fatal(err)
   165  	}
   166  
   167  	if nc.NetworkType != ncp.NetworkType {
   168  		t.Fatalf("Incorrect networkCreate after json encoding/deconding: %v", ncp)
   169  	}
   170  
   171  	jl := endpointJoin{SandboxID: "abcdef456789"}
   172  	b, err = json.Marshal(jl)
   173  	if err != nil {
   174  		t.Fatal(err)
   175  	}
   176  
   177  	var jld endpointJoin
   178  	err = json.Unmarshal(b, &jld)
   179  	if err != nil {
   180  		t.Fatal(err)
   181  	}
   182  
   183  	if jl.SandboxID != jld.SandboxID {
   184  		t.Fatalf("Incorrect endpointJoin after json encoding/deconding: %v", jld)
   185  	}
   186  }
   187  
   188  func TestCreateDeleteNetwork(t *testing.T) {
   189  	defer testutils.SetupTestOSContext(t)()
   190  
   191  	// Cleanup local datastore file
   192  	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
   193  
   194  	c, err := libnetwork.New()
   195  	if err != nil {
   196  		t.Fatal(err)
   197  	}
   198  	defer c.Stop()
   199  
   200  	badBody, err := json.Marshal("bad body")
   201  	if err != nil {
   202  		t.Fatal(err)
   203  	}
   204  
   205  	vars := make(map[string]string)
   206  	_, errRsp := procCreateNetwork(c, nil, badBody)
   207  	if errRsp == &createdResponse {
   208  		t.Fatal("Expected to fail but succeeded")
   209  	}
   210  	if errRsp.StatusCode != http.StatusBadRequest {
   211  		t.Fatalf("Expected StatusBadRequest status code, got: %v", errRsp)
   212  	}
   213  
   214  	incompleteBody, err := json.Marshal(networkCreate{})
   215  	if err != nil {
   216  		t.Fatal(err)
   217  	}
   218  
   219  	_, errRsp = procCreateNetwork(c, vars, incompleteBody)
   220  	if errRsp == &createdResponse {
   221  		t.Fatal("Expected to fail but succeeded")
   222  	}
   223  	if errRsp.StatusCode != http.StatusBadRequest {
   224  		t.Fatalf("Expected StatusBadRequest status code, got: %v", errRsp)
   225  	}
   226  
   227  	dops := GetOpsMap("abc", "")
   228  	nops := map[string]string{}
   229  	nc := networkCreate{Name: "network_1", NetworkType: bridgeNetType, DriverOpts: dops, NetworkOpts: nops}
   230  	goodBody, err := json.Marshal(nc)
   231  	if err != nil {
   232  		t.Fatal(err)
   233  	}
   234  
   235  	_, errRsp = procCreateNetwork(c, vars, goodBody)
   236  	if errRsp != &createdResponse {
   237  		t.Fatalf("Unexpected failure: %v", errRsp)
   238  	}
   239  
   240  	vars[urlNwName] = ""
   241  	_, errRsp = procDeleteNetwork(c, vars, nil)
   242  	if errRsp == &successResponse {
   243  		t.Fatal("Expected to fail but succeeded")
   244  	}
   245  
   246  	vars[urlNwName] = "abc"
   247  	_, errRsp = procDeleteNetwork(c, vars, nil)
   248  	if errRsp == &successResponse {
   249  		t.Fatal("Expected to fail but succeeded")
   250  	}
   251  
   252  	vars[urlNwName] = "network_1"
   253  	_, errRsp = procDeleteNetwork(c, vars, nil)
   254  	if errRsp != &successResponse {
   255  		t.Fatalf("Unexpected failure: %v", errRsp)
   256  	}
   257  }
   258  
   259  func TestGetNetworksAndEndpoints(t *testing.T) {
   260  	defer testutils.SetupTestOSContext(t)()
   261  
   262  	// Cleanup local datastore file
   263  	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
   264  
   265  	c, err := libnetwork.New()
   266  	if err != nil {
   267  		t.Fatal(err)
   268  	}
   269  	defer c.Stop()
   270  
   271  	ops := GetOpsMap("api_test_nw", "")
   272  	nc := networkCreate{Name: "sh", NetworkType: bridgeNetType, DriverOpts: ops}
   273  	body, err := json.Marshal(nc)
   274  	if err != nil {
   275  		t.Fatal(err)
   276  	}
   277  
   278  	vars := make(map[string]string)
   279  	inid, errRsp := procCreateNetwork(c, vars, body)
   280  	if errRsp != &createdResponse {
   281  		t.Fatalf("Unexpected failure: %v", errRsp)
   282  	}
   283  	nid, ok := inid.(string)
   284  	if !ok {
   285  		t.FailNow()
   286  	}
   287  
   288  	ec1 := endpointCreate{
   289  		Name: "ep1",
   290  	}
   291  	b1, err := json.Marshal(ec1)
   292  	if err != nil {
   293  		t.Fatal(err)
   294  	}
   295  	ec2 := endpointCreate{Name: "ep2"}
   296  	b2, err := json.Marshal(ec2)
   297  	if err != nil {
   298  		t.Fatal(err)
   299  	}
   300  
   301  	vars[urlNwName] = "sh"
   302  	vars[urlEpName] = "ep1"
   303  	ieid1, errRsp := procCreateEndpoint(c, vars, b1)
   304  	if errRsp != &createdResponse {
   305  		t.Fatalf("Unexpected failure: %v", errRsp)
   306  	}
   307  	eid1 := i2s(ieid1)
   308  	vars[urlEpName] = "ep2"
   309  	ieid2, errRsp := procCreateEndpoint(c, vars, b2)
   310  	if errRsp != &createdResponse {
   311  		t.Fatalf("Unexpected failure: %v", errRsp)
   312  	}
   313  	eid2 := i2s(ieid2)
   314  
   315  	vars[urlNwName] = ""
   316  	vars[urlEpName] = "ep1"
   317  	_, errRsp = procGetEndpoint(c, vars, nil)
   318  	if errRsp == &successResponse {
   319  		t.Fatalf("Expected failure but succeeded: %v", errRsp)
   320  	}
   321  	if errRsp.StatusCode != http.StatusBadRequest {
   322  		t.Fatalf("Expected to fail with http.StatusBadRequest, but got: %d", errRsp.StatusCode)
   323  	}
   324  
   325  	vars = make(map[string]string)
   326  	vars[urlNwName] = "sh"
   327  	vars[urlEpID] = ""
   328  	_, errRsp = procGetEndpoint(c, vars, nil)
   329  	if errRsp == &successResponse {
   330  		t.Fatalf("Expected failure but succeeded: %v", errRsp)
   331  	}
   332  	if errRsp.StatusCode != http.StatusBadRequest {
   333  		t.Fatalf("Expected to fail with http.StatusBadRequest, but got: %d", errRsp.StatusCode)
   334  	}
   335  
   336  	vars = make(map[string]string)
   337  	vars[urlNwID] = ""
   338  	vars[urlEpID] = eid1
   339  	_, errRsp = procGetEndpoint(c, vars, nil)
   340  	if errRsp == &successResponse {
   341  		t.Fatalf("Expected failure but succeeded: %v", errRsp)
   342  	}
   343  	if errRsp.StatusCode != http.StatusBadRequest {
   344  		t.Fatalf("Expected to fail with http.StatusBadRequest, but got: %d", errRsp.StatusCode)
   345  	}
   346  
   347  	// nw by name and ep by id
   348  	vars[urlNwName] = "sh"
   349  	i1, errRsp := procGetEndpoint(c, vars, nil)
   350  	if errRsp != &successResponse {
   351  		t.Fatalf("Unexpected failure: %v", errRsp)
   352  	}
   353  	// nw by name and ep by name
   354  	delete(vars, urlEpID)
   355  	vars[urlEpName] = "ep1"
   356  	i2, errRsp := procGetEndpoint(c, vars, nil)
   357  	if errRsp != &successResponse {
   358  		t.Fatalf("Unexpected failure: %v", errRsp)
   359  	}
   360  	// nw by id and ep by name
   361  	delete(vars, urlNwName)
   362  	vars[urlNwID] = nid
   363  	i3, errRsp := procGetEndpoint(c, vars, nil)
   364  	if errRsp != &successResponse {
   365  		t.Fatalf("Unexpected failure: %v", errRsp)
   366  	}
   367  	// nw by id and ep by id
   368  	delete(vars, urlEpName)
   369  	vars[urlEpID] = eid1
   370  	i4, errRsp := procGetEndpoint(c, vars, nil)
   371  	if errRsp != &successResponse {
   372  		t.Fatalf("Unexpected failure: %v", errRsp)
   373  	}
   374  
   375  	id1 := i2e(i1).ID
   376  	if id1 != i2e(i2).ID || id1 != i2e(i3).ID || id1 != i2e(i4).ID {
   377  		t.Fatalf("Endpoints retrieved via different query parameters differ: %v, %v, %v, %v", i1, i2, i3, i4)
   378  	}
   379  
   380  	vars[urlNwName] = ""
   381  	_, errRsp = procGetEndpoints(c, vars, nil)
   382  	if errRsp == &successResponse {
   383  		t.Fatalf("Expected failure, got: %v", errRsp)
   384  	}
   385  
   386  	delete(vars, urlNwName)
   387  	vars[urlNwID] = "fakeID"
   388  	_, errRsp = procGetEndpoints(c, vars, nil)
   389  	if errRsp == &successResponse {
   390  		t.Fatalf("Expected failure, got: %v", errRsp)
   391  	}
   392  
   393  	vars[urlNwID] = nid
   394  	_, errRsp = procGetEndpoints(c, vars, nil)
   395  	if errRsp != &successResponse {
   396  		t.Fatalf("Unexpected failure: %v", errRsp)
   397  	}
   398  
   399  	vars[urlNwName] = "sh"
   400  	iepList, errRsp := procGetEndpoints(c, vars, nil)
   401  	if errRsp != &successResponse {
   402  		t.Fatalf("Unexpected failure: %v", errRsp)
   403  	}
   404  	epList := i2eL(iepList)
   405  	if len(epList) != 2 {
   406  		t.Fatalf("Did not return the expected number (2) of endpoint resources: %d", len(epList))
   407  	}
   408  	if "sh" != epList[0].Network || "sh" != epList[1].Network {
   409  		t.Fatal("Did not find expected network name in endpoint resources")
   410  	}
   411  
   412  	vars = make(map[string]string)
   413  	vars[urlNwName] = ""
   414  	_, errRsp = procGetNetwork(c, vars, nil)
   415  	if errRsp == &successResponse {
   416  		t.Fatalf("Expected failure, got: %v", errRsp)
   417  	}
   418  	vars[urlNwName] = "shhhhh"
   419  	_, errRsp = procGetNetwork(c, vars, nil)
   420  	if errRsp == &successResponse {
   421  		t.Fatalf("Expected failure, got: %v", errRsp)
   422  	}
   423  	vars[urlNwName] = "sh"
   424  	inr1, errRsp := procGetNetwork(c, vars, nil)
   425  	if errRsp != &successResponse {
   426  		t.Fatalf("Unexpected failure: %v", errRsp)
   427  	}
   428  	nr1 := i2n(inr1)
   429  
   430  	delete(vars, urlNwName)
   431  	vars[urlNwID] = "acacac"
   432  	_, errRsp = procGetNetwork(c, vars, nil)
   433  	if errRsp == &successResponse {
   434  		t.Fatalf("Expected failure. Got: %v", errRsp)
   435  	}
   436  	vars[urlNwID] = nid
   437  	inr2, errRsp := procGetNetwork(c, vars, nil)
   438  	if errRsp != &successResponse {
   439  		t.Fatalf("procgetNetworkByName() != procgetNetworkById(), %v vs %v", inr1, inr2)
   440  	}
   441  	nr2 := i2n(inr2)
   442  	if nr1.Name != nr2.Name || nr1.Type != nr2.Type || nr1.ID != nr2.ID || len(nr1.Endpoints) != len(nr2.Endpoints) {
   443  		t.Fatalf("Get by name and Get failure: %v", errRsp)
   444  	}
   445  
   446  	if len(nr1.Endpoints) != 2 {
   447  		t.Fatalf("Did not find the expected number (2) of endpoint resources in the network resource: %d", len(nr1.Endpoints))
   448  	}
   449  	for _, er := range nr1.Endpoints {
   450  		if er.ID != eid1 && er.ID != eid2 {
   451  			t.Fatalf("Did not find the expected endpoint resources in the network resource: %v", nr1.Endpoints)
   452  		}
   453  	}
   454  
   455  	iList, errRsp := procGetNetworks(c, nil, nil)
   456  	if errRsp != &successResponse {
   457  		t.Fatalf("Unexpected failure: %v", errRsp)
   458  	}
   459  	netList := i2nL(iList)
   460  	if len(netList) != 1 {
   461  		t.Fatal("Did not return the expected number of network resources")
   462  	}
   463  	if nid != netList[0].ID {
   464  		t.Fatalf("Did not find expected network %s: %v", nid, netList)
   465  	}
   466  
   467  	_, errRsp = procDeleteNetwork(c, vars, nil)
   468  	if errRsp == &successResponse {
   469  		t.Fatalf("Expected failure, got: %v", errRsp)
   470  	}
   471  
   472  	vars[urlEpName] = "ep1"
   473  	_, errRsp = procDeleteEndpoint(c, vars, nil)
   474  	if errRsp != &successResponse {
   475  		t.Fatalf("Unexpected failure: %v", errRsp)
   476  	}
   477  	delete(vars, urlEpName)
   478  	iepList, errRsp = procGetEndpoints(c, vars, nil)
   479  	if errRsp != &successResponse {
   480  		t.Fatalf("Unexpected failure: %v", errRsp)
   481  	}
   482  	epList = i2eL(iepList)
   483  	if len(epList) != 1 {
   484  		t.Fatalf("Did not return the expected number (1) of endpoint resources: %d", len(epList))
   485  	}
   486  
   487  	vars[urlEpName] = "ep2"
   488  	_, errRsp = procDeleteEndpoint(c, vars, nil)
   489  	if errRsp != &successResponse {
   490  		t.Fatalf("Unexpected failure: %v", errRsp)
   491  	}
   492  	iepList, errRsp = procGetEndpoints(c, vars, nil)
   493  	if errRsp != &successResponse {
   494  		t.Fatalf("Unexpected failure: %v", errRsp)
   495  	}
   496  	epList = i2eL(iepList)
   497  	if len(epList) != 0 {
   498  		t.Fatalf("Did not return the expected number (0) of endpoint resources: %d", len(epList))
   499  	}
   500  
   501  	_, errRsp = procDeleteNetwork(c, vars, nil)
   502  	if errRsp != &successResponse {
   503  		t.Fatalf("Unexpected failure: %v", errRsp)
   504  	}
   505  
   506  	iList, errRsp = procGetNetworks(c, nil, nil)
   507  	if errRsp != &successResponse {
   508  		t.Fatalf("Unexpected failure: %v", errRsp)
   509  	}
   510  	netList = i2nL(iList)
   511  	if len(netList) != 0 {
   512  		t.Fatal("Did not return the expected number of network resources")
   513  	}
   514  }
   515  
   516  func TestProcGetServices(t *testing.T) {
   517  	defer testutils.SetupTestOSContext(t)()
   518  
   519  	// Cleanup local datastore file
   520  	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
   521  
   522  	c, err := libnetwork.New()
   523  	if err != nil {
   524  		t.Fatal(err)
   525  	}
   526  	defer c.Stop()
   527  
   528  	// Create 2 networks
   529  	netName1 := "production"
   530  	netOption := options.Generic{
   531  		netlabel.GenericData: options.Generic{
   532  			"BridgeName": netName1,
   533  		},
   534  	}
   535  	nw1, err := c.NewNetwork(bridgeNetType, netName1, "", libnetwork.NetworkOptionGeneric(netOption))
   536  	if err != nil {
   537  		t.Fatal(err)
   538  	}
   539  
   540  	netName2 := "workdev"
   541  	netOption = options.Generic{
   542  		netlabel.GenericData: options.Generic{
   543  			"BridgeName": netName2,
   544  		},
   545  	}
   546  	nw2, err := c.NewNetwork(bridgeNetType, netName2, "", libnetwork.NetworkOptionGeneric(netOption))
   547  	if err != nil {
   548  		t.Fatal(err)
   549  	}
   550  
   551  	vars := make(map[string]string)
   552  	li, errRsp := procGetServices(c, vars, nil)
   553  	if !errRsp.isOK() {
   554  		t.Fatalf("Unexpected failure: %v", errRsp)
   555  	}
   556  	list := i2eL(li)
   557  	if len(list) != 0 {
   558  		t.Fatalf("Unexpected services in response: %v", list)
   559  	}
   560  
   561  	// Add a couple of services on one network and one on the other network
   562  	ep11, err := nw1.CreateEndpoint("db-prod")
   563  	if err != nil {
   564  		t.Fatal(err)
   565  	}
   566  	ep12, err := nw1.CreateEndpoint("web-prod")
   567  	if err != nil {
   568  		t.Fatal(err)
   569  	}
   570  	ep21, err := nw2.CreateEndpoint("db-dev")
   571  	if err != nil {
   572  		t.Fatal(err)
   573  	}
   574  
   575  	li, errRsp = procGetServices(c, vars, nil)
   576  	if !errRsp.isOK() {
   577  		t.Fatalf("Unexpected failure: %v", errRsp)
   578  	}
   579  	list = i2eL(li)
   580  	if len(list) != 3 {
   581  		t.Fatalf("Unexpected services in response: %v", list)
   582  	}
   583  
   584  	// Filter by network
   585  	vars[urlNwName] = netName1
   586  	li, errRsp = procGetServices(c, vars, nil)
   587  	if !errRsp.isOK() {
   588  		t.Fatalf("Unexpected failure: %v", errRsp)
   589  	}
   590  	list = i2eL(li)
   591  	if len(list) != 2 {
   592  		t.Fatalf("Unexpected services in response: %v", list)
   593  	}
   594  
   595  	vars[urlNwName] = netName2
   596  	li, errRsp = procGetServices(c, vars, nil)
   597  	if !errRsp.isOK() {
   598  		t.Fatalf("Unexpected failure: %v", errRsp)
   599  	}
   600  	list = i2eL(li)
   601  	if len(list) != 1 {
   602  		t.Fatalf("Unexpected services in response: %v", list)
   603  	}
   604  
   605  	vars[urlNwName] = "unknown-network"
   606  	li, errRsp = procGetServices(c, vars, nil)
   607  	if !errRsp.isOK() {
   608  		t.Fatalf("Unexpected failure: %v", errRsp)
   609  	}
   610  	list = i2eL(li)
   611  	if len(list) != 0 {
   612  		t.Fatalf("Unexpected services in response: %v", list)
   613  	}
   614  
   615  	// Query by name
   616  	delete(vars, urlNwName)
   617  	vars[urlEpName] = "db-prod"
   618  	li, errRsp = procGetServices(c, vars, nil)
   619  	if !errRsp.isOK() {
   620  		t.Fatalf("Unexpected failure: %v", errRsp)
   621  	}
   622  	list = i2eL(li)
   623  	if len(list) != 1 {
   624  		t.Fatalf("Unexpected services in response: %v", list)
   625  	}
   626  
   627  	vars[urlEpName] = "no-service"
   628  	li, errRsp = procGetServices(c, vars, nil)
   629  	if !errRsp.isOK() {
   630  		t.Fatalf("Unexpected failure: %v", errRsp)
   631  	}
   632  	list = i2eL(li)
   633  	if len(list) != 0 {
   634  		t.Fatalf("Unexpected services in response: %v", list)
   635  	}
   636  
   637  	// Query by id or partial id
   638  	delete(vars, urlEpName)
   639  	vars[urlEpPID] = ep12.ID()
   640  	li, errRsp = procGetServices(c, vars, nil)
   641  	if !errRsp.isOK() {
   642  		t.Fatalf("Unexpected failure: %v", errRsp)
   643  	}
   644  	list = i2eL(li)
   645  	if len(list) != 1 {
   646  		t.Fatalf("Unexpected services in response: %v", list)
   647  	}
   648  	if list[0].ID != ep12.ID() {
   649  		t.Fatalf("Unexpected element in response: %v", list)
   650  	}
   651  
   652  	vars[urlEpPID] = "non-id"
   653  	li, errRsp = procGetServices(c, vars, nil)
   654  	if !errRsp.isOK() {
   655  		t.Fatalf("Unexpected failure: %v", errRsp)
   656  	}
   657  	list = i2eL(li)
   658  	if len(list) != 0 {
   659  		t.Fatalf("Unexpected services in response: %v", list)
   660  	}
   661  
   662  	delete(vars, urlEpPID)
   663  	err = ep11.Delete(false)
   664  	if err != nil {
   665  		t.Fatal(err)
   666  	}
   667  	err = ep12.Delete(false)
   668  	if err != nil {
   669  		t.Fatal(err)
   670  	}
   671  	err = ep21.Delete(false)
   672  	if err != nil {
   673  		t.Fatal(err)
   674  	}
   675  
   676  	li, errRsp = procGetServices(c, vars, nil)
   677  	if !errRsp.isOK() {
   678  		t.Fatalf("Unexpected failure: %v", errRsp)
   679  	}
   680  	list = i2eL(li)
   681  	if len(list) != 0 {
   682  		t.Fatalf("Unexpected services in response: %v", list)
   683  	}
   684  }
   685  
   686  func TestProcGetService(t *testing.T) {
   687  	defer testutils.SetupTestOSContext(t)()
   688  
   689  	c, nw := createTestNetwork(t, "network")
   690  	defer c.Stop()
   691  	ep1, err := nw.CreateEndpoint("db")
   692  	if err != nil {
   693  		t.Fatal(err)
   694  	}
   695  	ep2, err := nw.CreateEndpoint("web")
   696  	if err != nil {
   697  		t.Fatal(err)
   698  	}
   699  
   700  	vars := map[string]string{urlEpID: ""}
   701  	_, errRsp := procGetService(c, vars, nil)
   702  	if errRsp.isOK() {
   703  		t.Fatal("Expected failure, but succeeded")
   704  	}
   705  	if errRsp.StatusCode != http.StatusBadRequest {
   706  		t.Fatalf("Expected %d, but got: %d", http.StatusBadRequest, errRsp.StatusCode)
   707  	}
   708  
   709  	vars[urlEpID] = "unknown-service-id"
   710  	_, errRsp = procGetService(c, vars, nil)
   711  	if errRsp.isOK() {
   712  		t.Fatal("Expected failure, but succeeded")
   713  	}
   714  	if errRsp.StatusCode != http.StatusNotFound {
   715  		t.Fatalf("Expected %d, but got: %d. (%v)", http.StatusNotFound, errRsp.StatusCode, errRsp)
   716  	}
   717  
   718  	vars[urlEpID] = ep1.ID()
   719  	si, errRsp := procGetService(c, vars, nil)
   720  	if !errRsp.isOK() {
   721  		t.Fatalf("Unexpected failure: %v", errRsp)
   722  	}
   723  	sv := i2e(si)
   724  	if sv.ID != ep1.ID() {
   725  		t.Fatalf("Unexpected service resource returned: %v", sv)
   726  	}
   727  
   728  	vars[urlEpID] = ep2.ID()
   729  	si, errRsp = procGetService(c, vars, nil)
   730  	if !errRsp.isOK() {
   731  		t.Fatalf("Unexpected failure: %v", errRsp)
   732  	}
   733  	sv = i2e(si)
   734  	if sv.ID != ep2.ID() {
   735  		t.Fatalf("Unexpected service resource returned: %v", sv)
   736  	}
   737  }
   738  
   739  func TestProcPublishUnpublishService(t *testing.T) {
   740  	defer testutils.SetupTestOSContext(t)()
   741  
   742  	c, _ := createTestNetwork(t, "network")
   743  	defer c.Stop()
   744  
   745  	vars := make(map[string]string)
   746  
   747  	vbad, err := json.Marshal("bad service create data")
   748  	if err != nil {
   749  		t.Fatal(err)
   750  	}
   751  	_, errRsp := procPublishService(c, vars, vbad)
   752  	if errRsp == &createdResponse {
   753  		t.Fatal("Expected to fail but succeeded")
   754  	}
   755  	if errRsp.StatusCode != http.StatusBadRequest {
   756  		t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
   757  	}
   758  
   759  	b, err := json.Marshal(servicePublish{Name: ""})
   760  	if err != nil {
   761  		t.Fatal(err)
   762  	}
   763  	_, errRsp = procPublishService(c, vars, b)
   764  	if errRsp == &createdResponse {
   765  		t.Fatal("Expected to fail but succeeded")
   766  	}
   767  	if errRsp.StatusCode != http.StatusBadRequest {
   768  		t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
   769  	}
   770  
   771  	b, err = json.Marshal(servicePublish{Name: "db"})
   772  	if err != nil {
   773  		t.Fatal(err)
   774  	}
   775  	_, errRsp = procPublishService(c, vars, b)
   776  	if errRsp == &createdResponse {
   777  		t.Fatal("Expected to fail but succeeded")
   778  	}
   779  	if errRsp.StatusCode != http.StatusBadRequest {
   780  		t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
   781  	}
   782  
   783  	b, err = json.Marshal(servicePublish{Name: "db", Network: "unknown-network"})
   784  	if err != nil {
   785  		t.Fatal(err)
   786  	}
   787  	_, errRsp = procPublishService(c, vars, b)
   788  	if errRsp == &createdResponse {
   789  		t.Fatal("Expected to fail but succeeded")
   790  	}
   791  	if errRsp.StatusCode != http.StatusNotFound {
   792  		t.Fatalf("Expected %d. Got: %v", http.StatusNotFound, errRsp)
   793  	}
   794  
   795  	b, err = json.Marshal(servicePublish{Name: "", Network: "network"})
   796  	if err != nil {
   797  		t.Fatal(err)
   798  	}
   799  	_, errRsp = procPublishService(c, vars, b)
   800  	if errRsp == &createdResponse {
   801  		t.Fatal("Expected to fail but succeeded")
   802  	}
   803  	if errRsp.StatusCode != http.StatusBadRequest {
   804  		t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
   805  	}
   806  
   807  	b, err = json.Marshal(servicePublish{Name: "db", Network: "network"})
   808  	if err != nil {
   809  		t.Fatal(err)
   810  	}
   811  	_, errRsp = procPublishService(c, vars, b)
   812  	if errRsp != &createdResponse {
   813  		t.Fatalf("Unexpected failure: %v", errRsp)
   814  	}
   815  
   816  	sp := servicePublish{
   817  		Name:    "web",
   818  		Network: "network",
   819  	}
   820  	b, err = json.Marshal(sp)
   821  	if err != nil {
   822  		t.Fatal(err)
   823  	}
   824  	si, errRsp := procPublishService(c, vars, b)
   825  	if errRsp != &createdResponse {
   826  		t.Fatalf("Unexpected failure: %v", errRsp)
   827  	}
   828  	sid := i2s(si)
   829  
   830  	vars[urlEpID] = ""
   831  	_, errRsp = procUnpublishService(c, vars, nil)
   832  	if errRsp.isOK() {
   833  		t.Fatal("Expected failure but succeeded")
   834  	}
   835  	if errRsp.StatusCode != http.StatusBadRequest {
   836  		t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
   837  	}
   838  
   839  	vars[urlEpID] = "unknown-service-id"
   840  	_, errRsp = procUnpublishService(c, vars, nil)
   841  	if errRsp.isOK() {
   842  		t.Fatal("Expected failure but succeeded")
   843  	}
   844  	if errRsp.StatusCode != http.StatusNotFound {
   845  		t.Fatalf("Expected %d. Got: %v", http.StatusNotFound, errRsp)
   846  	}
   847  
   848  	vars[urlEpID] = sid
   849  	_, errRsp = procUnpublishService(c, vars, nil)
   850  	if !errRsp.isOK() {
   851  		t.Fatalf("Unexpected failure: %v", errRsp)
   852  	}
   853  
   854  	_, errRsp = procGetService(c, vars, nil)
   855  	if errRsp.isOK() {
   856  		t.Fatal("Expected failure, but succeeded")
   857  	}
   858  	if errRsp.StatusCode != http.StatusNotFound {
   859  		t.Fatalf("Expected %d, but got: %d. (%v)", http.StatusNotFound, errRsp.StatusCode, errRsp)
   860  	}
   861  }
   862  
   863  func TestAttachDetachBackend(t *testing.T) {
   864  	defer testutils.SetupTestOSContext(t)()
   865  
   866  	c, nw := createTestNetwork(t, "network")
   867  	defer c.Stop()
   868  	ep1, err := nw.CreateEndpoint("db")
   869  	if err != nil {
   870  		t.Fatal(err)
   871  	}
   872  
   873  	vars := make(map[string]string)
   874  
   875  	vbad, err := json.Marshal("bad data")
   876  	if err != nil {
   877  		t.Fatal(err)
   878  	}
   879  	_, errRsp := procAttachBackend(c, vars, vbad)
   880  	if errRsp == &successResponse {
   881  		t.Fatalf("Expected failure, got: %v", errRsp)
   882  	}
   883  
   884  	vars[urlEpName] = "endpoint"
   885  	bad, err := json.Marshal(endpointJoin{})
   886  	if err != nil {
   887  		t.Fatal(err)
   888  	}
   889  	_, errRsp = procAttachBackend(c, vars, bad)
   890  	if errRsp == &successResponse {
   891  		t.Fatalf("Expected failure, got: %v", errRsp)
   892  	}
   893  	if errRsp.StatusCode != http.StatusNotFound {
   894  		t.Fatalf("Expected %d. Got: %v", http.StatusNotFound, errRsp)
   895  	}
   896  
   897  	vars[urlEpID] = "db"
   898  	_, errRsp = procGetSandbox(c, vars, nil)
   899  	if errRsp.isOK() {
   900  		t.Fatalf("Expected failure. Got %v", errRsp)
   901  	}
   902  	if errRsp.StatusCode != http.StatusNotFound {
   903  		t.Fatalf("Expected %d. Got: %v", http.StatusNotFound, errRsp)
   904  	}
   905  
   906  	vars[urlEpName] = "db"
   907  	_, errRsp = procAttachBackend(c, vars, bad)
   908  	if errRsp == &successResponse {
   909  		t.Fatalf("Expected failure, got: %v", errRsp)
   910  	}
   911  	if errRsp.StatusCode != http.StatusBadRequest {
   912  		t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
   913  	}
   914  
   915  	cid := "abcdefghi"
   916  	sbox, err := c.NewSandbox(cid)
   917  	if err != nil {
   918  		t.Fatal(err)
   919  	}
   920  	sid := sbox.ID()
   921  	defer sbox.Delete()
   922  
   923  	jl := endpointJoin{SandboxID: sid}
   924  	jlb, err := json.Marshal(jl)
   925  	if err != nil {
   926  		t.Fatal(err)
   927  	}
   928  
   929  	_, errRsp = procAttachBackend(c, vars, jlb)
   930  	if errRsp != &successResponse {
   931  		t.Fatalf("Unexpected failure, got: %v", errRsp)
   932  	}
   933  
   934  	sli, errRsp := procGetSandboxes(c, vars, nil)
   935  	if errRsp != &successResponse {
   936  		t.Fatalf("Unexpected failure, got: %v", errRsp)
   937  	}
   938  	sl := i2sbL(sli)
   939  	if len(sl) != 1 {
   940  		t.Fatalf("Did not find expected number of sandboxes attached to the service: %d", len(sl))
   941  	}
   942  	if sl[0].ContainerID != cid {
   943  		t.Fatalf("Did not find expected sandbox attached to the service: %v", sl[0])
   944  	}
   945  
   946  	_, errRsp = procUnpublishService(c, vars, nil)
   947  	if errRsp.isOK() {
   948  		t.Fatal("Expected failure but succeeded")
   949  	}
   950  	if errRsp.StatusCode != http.StatusForbidden {
   951  		t.Fatalf("Expected %d. Got: %v", http.StatusForbidden, errRsp)
   952  	}
   953  
   954  	vars[urlEpName] = "endpoint"
   955  	_, errRsp = procDetachBackend(c, vars, nil)
   956  	if errRsp == &successResponse {
   957  		t.Fatalf("Expected failure, got: %v", errRsp)
   958  	}
   959  	if errRsp.StatusCode != http.StatusNotFound {
   960  		t.Fatalf("Expected %d. Got: %v", http.StatusNotFound, errRsp)
   961  	}
   962  
   963  	vars[urlEpName] = "db"
   964  	_, errRsp = procDetachBackend(c, vars, nil)
   965  	if errRsp == &successResponse {
   966  		t.Fatalf("Expected failure, got: %v", errRsp)
   967  	}
   968  	if errRsp.StatusCode != http.StatusBadRequest {
   969  		t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
   970  	}
   971  
   972  	vars[urlSbID] = sid
   973  	_, errRsp = procDetachBackend(c, vars, nil)
   974  	if errRsp != &successResponse {
   975  		t.Fatalf("Unexpected failure, got: %v", errRsp)
   976  	}
   977  
   978  	delete(vars, urlEpID)
   979  	si, errRsp := procGetSandbox(c, vars, nil)
   980  	if errRsp != &successResponse {
   981  		t.Fatalf("Unexpected failure, got: %v", errRsp)
   982  	}
   983  	sb := i2sb(si)
   984  	if sb.ContainerID != cid {
   985  		t.Fatalf("Did not find expected sandbox. Got %v", sb)
   986  	}
   987  
   988  	err = ep1.Delete(false)
   989  	if err != nil {
   990  		t.Fatal(err)
   991  	}
   992  }
   993  
   994  func TestDetectGetNetworksInvalidQueryComposition(t *testing.T) {
   995  	// Cleanup local datastore file
   996  	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
   997  
   998  	c, err := libnetwork.New()
   999  	if err != nil {
  1000  		t.Fatal(err)
  1001  	}
  1002  	defer c.Stop()
  1003  
  1004  	vars := map[string]string{urlNwName: "x", urlNwPID: "y"}
  1005  	_, errRsp := procGetNetworks(c, vars, nil)
  1006  	if errRsp.StatusCode != http.StatusBadRequest {
  1007  		t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
  1008  	}
  1009  }
  1010  
  1011  func TestDetectGetEndpointsInvalidQueryComposition(t *testing.T) {
  1012  	defer testutils.SetupTestOSContext(t)()
  1013  
  1014  	c, _ := createTestNetwork(t, "network")
  1015  	defer c.Stop()
  1016  
  1017  	vars := map[string]string{urlNwName: "network", urlEpName: "x", urlEpPID: "y"}
  1018  	_, errRsp := procGetEndpoints(c, vars, nil)
  1019  	if errRsp.StatusCode != http.StatusBadRequest {
  1020  		t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
  1021  	}
  1022  }
  1023  
  1024  func TestDetectGetServicesInvalidQueryComposition(t *testing.T) {
  1025  	defer testutils.SetupTestOSContext(t)()
  1026  
  1027  	c, _ := createTestNetwork(t, "network")
  1028  	defer c.Stop()
  1029  
  1030  	vars := map[string]string{urlNwName: "network", urlEpName: "x", urlEpPID: "y"}
  1031  	_, errRsp := procGetServices(c, vars, nil)
  1032  	if errRsp.StatusCode != http.StatusBadRequest {
  1033  		t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
  1034  	}
  1035  }
  1036  
  1037  func TestFindNetworkUtilPanic(t *testing.T) {
  1038  	defer checkPanic(t)
  1039  	findNetwork(nil, "", -1)
  1040  }
  1041  
  1042  func TestFindNetworkUtil(t *testing.T) {
  1043  	defer testutils.SetupTestOSContext(t)()
  1044  
  1045  	c, nw := createTestNetwork(t, "network")
  1046  	defer c.Stop()
  1047  
  1048  	nid := nw.ID()
  1049  
  1050  	_, errRsp := findNetwork(c, "", byName)
  1051  	if errRsp == &successResponse {
  1052  		t.Fatal("Expected to fail but succeeded")
  1053  	}
  1054  	if errRsp.StatusCode != http.StatusBadRequest {
  1055  		t.Fatalf("Expected %d, but got: %d", http.StatusBadRequest, errRsp.StatusCode)
  1056  	}
  1057  
  1058  	n, errRsp := findNetwork(c, nid, byID)
  1059  	if errRsp != &successResponse {
  1060  		t.Fatalf("Unexpected failure: %v", errRsp)
  1061  	}
  1062  	if n == nil {
  1063  		t.Fatal("Unexpected nil libnetwork.Network")
  1064  	}
  1065  	if nid != n.ID() {
  1066  		t.Fatalf("Incorrect libnetwork.Network resource. It has different id: %v", n)
  1067  	}
  1068  	if "network" != n.Name() {
  1069  		t.Fatalf("Incorrect libnetwork.Network resource. It has different name: %v", n)
  1070  	}
  1071  
  1072  	n, errRsp = findNetwork(c, "network", byName)
  1073  	if errRsp != &successResponse {
  1074  		t.Fatalf("Unexpected failure: %v", errRsp)
  1075  	}
  1076  	if n == nil {
  1077  		t.Fatal("Unexpected nil libnetwork.Network")
  1078  	}
  1079  	if nid != n.ID() {
  1080  		t.Fatalf("Incorrect libnetwork.Network resource. It has different id: %v", n)
  1081  	}
  1082  	if "network" != n.Name() {
  1083  		t.Fatalf("Incorrect libnetwork.Network resource. It has different name: %v", n)
  1084  	}
  1085  
  1086  	if err := n.Delete(); err != nil {
  1087  		t.Fatalf("Failed to delete the network: %s", err.Error())
  1088  	}
  1089  
  1090  	_, errRsp = findNetwork(c, nid, byID)
  1091  	if errRsp == &successResponse {
  1092  		t.Fatal("Expected to fail but succeeded")
  1093  	}
  1094  	if errRsp.StatusCode != http.StatusNotFound {
  1095  		t.Fatalf("Expected %d, but got: %d", http.StatusNotFound, errRsp.StatusCode)
  1096  	}
  1097  
  1098  	_, errRsp = findNetwork(c, "network", byName)
  1099  	if errRsp == &successResponse {
  1100  		t.Fatal("Expected to fail but succeeded")
  1101  	}
  1102  	if errRsp.StatusCode != http.StatusNotFound {
  1103  		t.Fatalf("Expected %d, but got: %d", http.StatusNotFound, errRsp.StatusCode)
  1104  	}
  1105  }
  1106  
  1107  func TestCreateDeleteEndpoints(t *testing.T) {
  1108  	defer testutils.SetupTestOSContext(t)()
  1109  
  1110  	// Cleanup local datastore file
  1111  	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
  1112  
  1113  	c, err := libnetwork.New()
  1114  	if err != nil {
  1115  		t.Fatal(err)
  1116  	}
  1117  	defer c.Stop()
  1118  
  1119  	nc := networkCreate{Name: "firstNet", NetworkType: bridgeNetType}
  1120  	body, err := json.Marshal(nc)
  1121  	if err != nil {
  1122  		t.Fatal(err)
  1123  	}
  1124  
  1125  	vars := make(map[string]string)
  1126  	i, errRsp := procCreateNetwork(c, vars, body)
  1127  	if errRsp != &createdResponse {
  1128  		t.Fatalf("Unexpected failure: %v", errRsp)
  1129  	}
  1130  	nid := i2s(i)
  1131  
  1132  	vbad, err := json.Marshal("bad endpoint create data")
  1133  	if err != nil {
  1134  		t.Fatal(err)
  1135  	}
  1136  
  1137  	vars[urlNwName] = "firstNet"
  1138  	_, errRsp = procCreateEndpoint(c, vars, vbad)
  1139  	if errRsp == &createdResponse {
  1140  		t.Fatal("Expected to fail but succeeded")
  1141  	}
  1142  
  1143  	b, err := json.Marshal(endpointCreate{Name: ""})
  1144  	if err != nil {
  1145  		t.Fatal(err)
  1146  	}
  1147  
  1148  	vars[urlNwName] = "secondNet"
  1149  	_, errRsp = procCreateEndpoint(c, vars, b)
  1150  	if errRsp == &createdResponse {
  1151  		t.Fatal("Expected to fail but succeeded")
  1152  	}
  1153  
  1154  	vars[urlNwName] = "firstNet"
  1155  	_, errRsp = procCreateEndpoint(c, vars, b)
  1156  	if errRsp == &successResponse {
  1157  		t.Fatalf("Expected failure but succeeded: %v", errRsp)
  1158  	}
  1159  
  1160  	b, err = json.Marshal(endpointCreate{Name: "firstEp"})
  1161  	if err != nil {
  1162  		t.Fatal(err)
  1163  	}
  1164  
  1165  	i, errRsp = procCreateEndpoint(c, vars, b)
  1166  	if errRsp != &createdResponse {
  1167  		t.Fatalf("Unexpected failure: %v", errRsp)
  1168  	}
  1169  	eid := i2s(i)
  1170  
  1171  	_, errRsp = findEndpoint(c, "myNet", "firstEp", byName, byName)
  1172  	if errRsp == &successResponse {
  1173  		t.Fatalf("Expected failure but succeeded: %v", errRsp)
  1174  	}
  1175  
  1176  	ep0, errRsp := findEndpoint(c, nid, "firstEp", byID, byName)
  1177  	if errRsp != &successResponse {
  1178  		t.Fatalf("Unexpected failure: %v", errRsp)
  1179  	}
  1180  
  1181  	ep1, errRsp := findEndpoint(c, "firstNet", "firstEp", byName, byName)
  1182  	if errRsp != &successResponse {
  1183  		t.Fatalf("Unexpected failure: %v", errRsp)
  1184  	}
  1185  
  1186  	ep2, errRsp := findEndpoint(c, nid, eid, byID, byID)
  1187  	if errRsp != &successResponse {
  1188  		t.Fatalf("Unexpected failure: %v", errRsp)
  1189  	}
  1190  
  1191  	ep3, errRsp := findEndpoint(c, "firstNet", eid, byName, byID)
  1192  	if errRsp != &successResponse {
  1193  		t.Fatalf("Unexpected failure: %v", errRsp)
  1194  	}
  1195  
  1196  	if ep0.ID() != ep1.ID() || ep0.ID() != ep2.ID() || ep0.ID() != ep3.ID() {
  1197  		t.Fatalf("Different queries returned different endpoints: \nep0: %v\nep1: %v\nep2: %v\nep3: %v", ep0, ep1, ep2, ep3)
  1198  	}
  1199  
  1200  	vars = make(map[string]string)
  1201  	vars[urlNwName] = ""
  1202  	vars[urlEpName] = "ep1"
  1203  	_, errRsp = procDeleteEndpoint(c, vars, nil)
  1204  	if errRsp == &successResponse {
  1205  		t.Fatalf("Expected failure, got: %v", errRsp)
  1206  	}
  1207  
  1208  	vars[urlNwName] = "firstNet"
  1209  	vars[urlEpName] = ""
  1210  	_, errRsp = procDeleteEndpoint(c, vars, nil)
  1211  	if errRsp == &successResponse {
  1212  		t.Fatalf("Expected failure, got: %v", errRsp)
  1213  	}
  1214  
  1215  	vars[urlEpName] = "ep2"
  1216  	_, errRsp = procDeleteEndpoint(c, vars, nil)
  1217  	if errRsp == &successResponse {
  1218  		t.Fatalf("Expected failure, got: %v", errRsp)
  1219  	}
  1220  
  1221  	vars[urlEpName] = "firstEp"
  1222  	_, errRsp = procDeleteEndpoint(c, vars, nil)
  1223  	if errRsp != &successResponse {
  1224  		t.Fatalf("Unexpected failure: %v", errRsp)
  1225  	}
  1226  
  1227  	_, errRsp = findEndpoint(c, "firstNet", "firstEp", byName, byName)
  1228  	if errRsp == &successResponse {
  1229  		t.Fatalf("Expected failure, got: %v", errRsp)
  1230  	}
  1231  }
  1232  
  1233  func TestJoinLeave(t *testing.T) {
  1234  	defer testutils.SetupTestOSContext(t)()
  1235  
  1236  	// Cleanup local datastore file
  1237  	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
  1238  
  1239  	c, err := libnetwork.New()
  1240  	if err != nil {
  1241  		t.Fatal(err)
  1242  	}
  1243  	defer c.Stop()
  1244  
  1245  	nb, err := json.Marshal(networkCreate{Name: "network", NetworkType: bridgeNetType})
  1246  	if err != nil {
  1247  		t.Fatal(err)
  1248  	}
  1249  	vars := make(map[string]string)
  1250  	_, errRsp := procCreateNetwork(c, vars, nb)
  1251  	if errRsp != &createdResponse {
  1252  		t.Fatalf("Unexpected failure: %v", errRsp)
  1253  	}
  1254  
  1255  	eb, err := json.Marshal(endpointCreate{Name: "endpoint"})
  1256  	if err != nil {
  1257  		t.Fatal(err)
  1258  	}
  1259  	vars[urlNwName] = "network"
  1260  	_, errRsp = procCreateEndpoint(c, vars, eb)
  1261  	if errRsp != &createdResponse {
  1262  		t.Fatalf("Unexpected failure: %v", errRsp)
  1263  	}
  1264  
  1265  	vbad, err := json.Marshal("bad data")
  1266  	if err != nil {
  1267  		t.Fatal(err)
  1268  	}
  1269  	_, errRsp = procJoinEndpoint(c, vars, vbad)
  1270  	if errRsp == &successResponse {
  1271  		t.Fatalf("Expected failure, got: %v", errRsp)
  1272  	}
  1273  
  1274  	vars[urlEpName] = "endpoint"
  1275  	bad, err := json.Marshal(endpointJoin{})
  1276  	if err != nil {
  1277  		t.Fatal(err)
  1278  	}
  1279  	_, errRsp = procJoinEndpoint(c, vars, bad)
  1280  	if errRsp == &successResponse {
  1281  		t.Fatalf("Expected failure, got: %v", errRsp)
  1282  	}
  1283  
  1284  	cid := "abcdefghi"
  1285  	sb, err := c.NewSandbox(cid)
  1286  	if err != nil {
  1287  		t.Fatal(err)
  1288  	}
  1289  	defer sb.Delete()
  1290  
  1291  	jl := endpointJoin{SandboxID: sb.ID()}
  1292  	jlb, err := json.Marshal(jl)
  1293  	if err != nil {
  1294  		t.Fatal(err)
  1295  	}
  1296  
  1297  	vars = make(map[string]string)
  1298  	vars[urlNwName] = ""
  1299  	vars[urlEpName] = ""
  1300  	_, errRsp = procJoinEndpoint(c, vars, jlb)
  1301  	if errRsp == &successResponse {
  1302  		t.Fatalf("Expected failure, got: %v", errRsp)
  1303  	}
  1304  
  1305  	vars[urlNwName] = "network"
  1306  	vars[urlEpName] = ""
  1307  	_, errRsp = procJoinEndpoint(c, vars, jlb)
  1308  	if errRsp == &successResponse {
  1309  		t.Fatalf("Expected failure, got: %v", errRsp)
  1310  	}
  1311  
  1312  	vars[urlEpName] = "epoint"
  1313  	_, errRsp = procJoinEndpoint(c, vars, jlb)
  1314  	if errRsp == &successResponse {
  1315  		t.Fatalf("Expected failure, got: %v", errRsp)
  1316  	}
  1317  
  1318  	// bad labels
  1319  	vars[urlEpName] = "endpoint"
  1320  	key, errRsp := procJoinEndpoint(c, vars, jlb)
  1321  	if errRsp != &successResponse {
  1322  		t.Fatalf("Unexpected failure, got: %v", errRsp)
  1323  	}
  1324  
  1325  	keyStr := i2s(key)
  1326  	if keyStr == "" {
  1327  		t.Fatal("Empty sandbox key")
  1328  	}
  1329  	_, errRsp = procDeleteEndpoint(c, vars, nil)
  1330  	if errRsp == &successResponse {
  1331  		t.Fatalf("Expected failure, got: %v", errRsp)
  1332  	}
  1333  
  1334  	vars[urlNwName] = "network2"
  1335  	_, errRsp = procLeaveEndpoint(c, vars, vbad)
  1336  	if errRsp == &successResponse {
  1337  		t.Fatalf("Expected failure, got: %v", errRsp)
  1338  	}
  1339  	_, errRsp = procLeaveEndpoint(c, vars, bad)
  1340  	if errRsp == &successResponse {
  1341  		t.Fatalf("Expected failure, got: %v", errRsp)
  1342  	}
  1343  	_, errRsp = procLeaveEndpoint(c, vars, jlb)
  1344  	if errRsp == &successResponse {
  1345  		t.Fatalf("Expected failure, got: %v", errRsp)
  1346  	}
  1347  	vars = make(map[string]string)
  1348  	vars[urlNwName] = ""
  1349  	vars[urlEpName] = ""
  1350  	_, errRsp = procLeaveEndpoint(c, vars, jlb)
  1351  	if errRsp == &successResponse {
  1352  		t.Fatalf("Expected failure, got: %v", errRsp)
  1353  	}
  1354  	vars[urlNwName] = "network"
  1355  	vars[urlEpName] = ""
  1356  	_, errRsp = procLeaveEndpoint(c, vars, jlb)
  1357  	if errRsp == &successResponse {
  1358  		t.Fatalf("Expected failure, got: %v", errRsp)
  1359  	}
  1360  	vars[urlEpName] = "2epoint"
  1361  	_, errRsp = procLeaveEndpoint(c, vars, jlb)
  1362  	if errRsp == &successResponse {
  1363  		t.Fatalf("Expected failure, got: %v", errRsp)
  1364  	}
  1365  	vars[urlEpName] = "epoint"
  1366  	vars[urlCnID] = "who"
  1367  	_, errRsp = procLeaveEndpoint(c, vars, jlb)
  1368  	if errRsp == &successResponse {
  1369  		t.Fatalf("Expected failure, got: %v", errRsp)
  1370  	}
  1371  
  1372  	delete(vars, urlCnID)
  1373  	vars[urlEpName] = "endpoint"
  1374  	_, errRsp = procLeaveEndpoint(c, vars, jlb)
  1375  	if errRsp == &successResponse {
  1376  		t.Fatalf("Expected failure, got: %v", errRsp)
  1377  	}
  1378  
  1379  	vars[urlSbID] = sb.ID()
  1380  	_, errRsp = procLeaveEndpoint(c, vars, jlb)
  1381  	if errRsp != &successResponse {
  1382  		t.Fatalf("Unexpected failure: %v", errRsp)
  1383  	}
  1384  
  1385  	_, errRsp = procLeaveEndpoint(c, vars, jlb)
  1386  	if errRsp == &successResponse {
  1387  		t.Fatalf("Expected failure, got: %v", errRsp)
  1388  	}
  1389  
  1390  	_, errRsp = procDeleteEndpoint(c, vars, nil)
  1391  	if errRsp != &successResponse {
  1392  		t.Fatalf("Unexpected failure: %v", errRsp)
  1393  	}
  1394  }
  1395  
  1396  func TestFindEndpointUtilPanic(t *testing.T) {
  1397  	defer testutils.SetupTestOSContext(t)()
  1398  	defer checkPanic(t)
  1399  	c, nw := createTestNetwork(t, "network")
  1400  	defer c.Stop()
  1401  
  1402  	nid := nw.ID()
  1403  	findEndpoint(c, nid, "", byID, -1)
  1404  }
  1405  
  1406  func TestFindServiceUtilPanic(t *testing.T) {
  1407  	defer testutils.SetupTestOSContext(t)()
  1408  	defer checkPanic(t)
  1409  	c, _ := createTestNetwork(t, "network")
  1410  	defer c.Stop()
  1411  
  1412  	findService(c, "random_service", -1)
  1413  }
  1414  
  1415  func TestFindEndpointUtil(t *testing.T) {
  1416  	defer testutils.SetupTestOSContext(t)()
  1417  
  1418  	c, nw := createTestNetwork(t, "network")
  1419  	defer c.Stop()
  1420  
  1421  	nid := nw.ID()
  1422  
  1423  	ep, err := nw.CreateEndpoint("secondEp", nil)
  1424  	if err != nil {
  1425  		t.Fatal(err)
  1426  	}
  1427  	eid := ep.ID()
  1428  
  1429  	_, errRsp := findEndpoint(c, nid, "", byID, byName)
  1430  	if errRsp == &successResponse {
  1431  		t.Fatalf("Expected failure, but got: %v", errRsp)
  1432  	}
  1433  	if errRsp.StatusCode != http.StatusBadRequest {
  1434  		t.Fatalf("Expected %d, but got: %d", http.StatusBadRequest, errRsp.StatusCode)
  1435  	}
  1436  
  1437  	ep0, errRsp := findEndpoint(c, nid, "secondEp", byID, byName)
  1438  	if errRsp != &successResponse {
  1439  		t.Fatalf("Unexpected failure: %v", errRsp)
  1440  	}
  1441  
  1442  	ep1, errRsp := findEndpoint(c, "network", "secondEp", byName, byName)
  1443  	if errRsp != &successResponse {
  1444  		t.Fatalf("Unexpected failure: %v", errRsp)
  1445  	}
  1446  
  1447  	ep2, errRsp := findEndpoint(c, nid, eid, byID, byID)
  1448  	if errRsp != &successResponse {
  1449  		t.Fatalf("Unexpected failure: %v", errRsp)
  1450  	}
  1451  
  1452  	ep3, errRsp := findEndpoint(c, "network", eid, byName, byID)
  1453  	if errRsp != &successResponse {
  1454  		t.Fatalf("Unexpected failure: %v", errRsp)
  1455  	}
  1456  
  1457  	ep4, errRsp := findService(c, "secondEp", byName)
  1458  	if errRsp != &successResponse {
  1459  		t.Fatalf("Unexpected failure: %v", errRsp)
  1460  	}
  1461  
  1462  	ep5, errRsp := findService(c, eid, byID)
  1463  	if errRsp != &successResponse {
  1464  		t.Fatalf("Unexpected failure: %v", errRsp)
  1465  	}
  1466  
  1467  	if ep0.ID() != ep1.ID() || ep0.ID() != ep2.ID() ||
  1468  		ep0.ID() != ep3.ID() || ep0.ID() != ep4.ID() || ep0.ID() != ep5.ID() {
  1469  		t.Fatal("Different queries returned different endpoints")
  1470  	}
  1471  
  1472  	ep.Delete(false)
  1473  
  1474  	_, errRsp = findEndpoint(c, nid, "secondEp", byID, byName)
  1475  	if errRsp == &successResponse {
  1476  		t.Fatalf("Expected failure, but got: %v", errRsp)
  1477  	}
  1478  	if errRsp.StatusCode != http.StatusNotFound {
  1479  		t.Fatalf("Expected %d, but got: %d", http.StatusNotFound, errRsp.StatusCode)
  1480  	}
  1481  
  1482  	_, errRsp = findEndpoint(c, "network", "secondEp", byName, byName)
  1483  	if errRsp == &successResponse {
  1484  		t.Fatalf("Expected failure, but got: %v", errRsp)
  1485  	}
  1486  	if errRsp.StatusCode != http.StatusNotFound {
  1487  		t.Fatalf("Expected %d, but got: %d", http.StatusNotFound, errRsp.StatusCode)
  1488  	}
  1489  
  1490  	_, errRsp = findEndpoint(c, nid, eid, byID, byID)
  1491  	if errRsp == &successResponse {
  1492  		t.Fatalf("Expected failure, but got: %v", errRsp)
  1493  	}
  1494  	if errRsp.StatusCode != http.StatusNotFound {
  1495  		t.Fatalf("Expected %d, but got: %d", http.StatusNotFound, errRsp.StatusCode)
  1496  	}
  1497  
  1498  	_, errRsp = findEndpoint(c, "network", eid, byName, byID)
  1499  	if errRsp == &successResponse {
  1500  		t.Fatalf("Expected failure, but got: %v", errRsp)
  1501  	}
  1502  	if errRsp.StatusCode != http.StatusNotFound {
  1503  		t.Fatalf("Expected %d, but got: %d", http.StatusNotFound, errRsp.StatusCode)
  1504  	}
  1505  
  1506  	_, errRsp = findService(c, "secondEp", byName)
  1507  	if errRsp == &successResponse {
  1508  		t.Fatalf("Expected failure, but got: %v", errRsp)
  1509  	}
  1510  	if errRsp.StatusCode != http.StatusNotFound {
  1511  		t.Fatalf("Expected %d, but got: %d", http.StatusNotFound, errRsp.StatusCode)
  1512  	}
  1513  
  1514  	_, errRsp = findService(c, eid, byID)
  1515  	if errRsp == &successResponse {
  1516  		t.Fatalf("Expected failure, but got: %v", errRsp)
  1517  	}
  1518  	if errRsp.StatusCode != http.StatusNotFound {
  1519  		t.Fatalf("Expected %d, but got: %d", http.StatusNotFound, errRsp.StatusCode)
  1520  	}
  1521  }
  1522  
  1523  func TestEndpointToService(t *testing.T) {
  1524  	r := &responseStatus{Status: "this is one endpoint", StatusCode: http.StatusOK}
  1525  	r = endpointToService(r)
  1526  	if r.Status != "this is one service" {
  1527  		t.Fatalf("endpointToService returned unexpected status string: %s", r.Status)
  1528  	}
  1529  
  1530  	r = &responseStatus{Status: "this is one network", StatusCode: http.StatusOK}
  1531  	r = endpointToService(r)
  1532  	if r.Status != "this is one network" {
  1533  		t.Fatalf("endpointToService returned unexpected status string: %s", r.Status)
  1534  	}
  1535  }
  1536  
  1537  func checkPanic(t *testing.T) {
  1538  	if r := recover(); r != nil {
  1539  		if _, ok := r.(runtime.Error); ok {
  1540  			panic(r)
  1541  		}
  1542  	} else {
  1543  		t.Fatal("Expected to panic, but succeeded")
  1544  	}
  1545  }
  1546  
  1547  func TestDetectNetworkTargetPanic(t *testing.T) {
  1548  	defer checkPanic(t)
  1549  	vars := make(map[string]string)
  1550  	detectNetworkTarget(vars)
  1551  }
  1552  
  1553  func TestDetectEndpointTargetPanic(t *testing.T) {
  1554  	defer checkPanic(t)
  1555  	vars := make(map[string]string)
  1556  	detectEndpointTarget(vars)
  1557  }
  1558  
  1559  func TestResponseStatus(t *testing.T) {
  1560  	list := []int{
  1561  		http.StatusBadGateway,
  1562  		http.StatusBadRequest,
  1563  		http.StatusConflict,
  1564  		http.StatusContinue,
  1565  		http.StatusExpectationFailed,
  1566  		http.StatusForbidden,
  1567  		http.StatusFound,
  1568  		http.StatusGatewayTimeout,
  1569  		http.StatusGone,
  1570  		http.StatusHTTPVersionNotSupported,
  1571  		http.StatusInternalServerError,
  1572  		http.StatusLengthRequired,
  1573  		http.StatusMethodNotAllowed,
  1574  		http.StatusMovedPermanently,
  1575  		http.StatusMultipleChoices,
  1576  		http.StatusNoContent,
  1577  		http.StatusNonAuthoritativeInfo,
  1578  		http.StatusNotAcceptable,
  1579  		http.StatusNotFound,
  1580  		http.StatusNotModified,
  1581  		http.StatusPartialContent,
  1582  		http.StatusPaymentRequired,
  1583  		http.StatusPreconditionFailed,
  1584  		http.StatusProxyAuthRequired,
  1585  		http.StatusRequestEntityTooLarge,
  1586  		http.StatusRequestTimeout,
  1587  		http.StatusRequestURITooLong,
  1588  		http.StatusRequestedRangeNotSatisfiable,
  1589  		http.StatusResetContent,
  1590  		http.StatusServiceUnavailable,
  1591  		http.StatusSwitchingProtocols,
  1592  		http.StatusTemporaryRedirect,
  1593  		http.StatusUnauthorized,
  1594  		http.StatusUnsupportedMediaType,
  1595  		http.StatusUseProxy,
  1596  	}
  1597  	for _, c := range list {
  1598  		r := responseStatus{StatusCode: c}
  1599  		if r.isOK() {
  1600  			t.Fatalf("isOK() returned true for code% d", c)
  1601  		}
  1602  	}
  1603  
  1604  	r := responseStatus{StatusCode: http.StatusOK}
  1605  	if !r.isOK() {
  1606  		t.Fatal("isOK() failed")
  1607  	}
  1608  
  1609  	r = responseStatus{StatusCode: http.StatusCreated}
  1610  	if !r.isOK() {
  1611  		t.Fatal("isOK() failed")
  1612  	}
  1613  }
  1614  
  1615  // Local structs for end to end testing of api.go
  1616  type localReader struct {
  1617  	data  []byte
  1618  	beBad bool
  1619  }
  1620  
  1621  func newLocalReader(data []byte) *localReader {
  1622  	lr := &localReader{data: make([]byte, len(data))}
  1623  	copy(lr.data, data)
  1624  	return lr
  1625  }
  1626  
  1627  func (l *localReader) Read(p []byte) (n int, err error) {
  1628  	if l.beBad {
  1629  		return 0, errors.New("I am a bad reader")
  1630  	}
  1631  	if p == nil {
  1632  		return -1, errors.New("nil buffer passed")
  1633  	}
  1634  	if l.data == nil || len(l.data) == 0 {
  1635  		return 0, io.EOF
  1636  	}
  1637  	copy(p[:], l.data[:])
  1638  	return len(l.data), io.EOF
  1639  }
  1640  
  1641  type localResponseWriter struct {
  1642  	body       []byte
  1643  	statusCode int
  1644  }
  1645  
  1646  func newWriter() *localResponseWriter {
  1647  	return &localResponseWriter{}
  1648  }
  1649  
  1650  func (f *localResponseWriter) Header() http.Header {
  1651  	return make(map[string][]string, 0)
  1652  }
  1653  
  1654  func (f *localResponseWriter) Write(data []byte) (int, error) {
  1655  	if data == nil {
  1656  		return -1, errors.New("nil data passed")
  1657  	}
  1658  
  1659  	f.body = make([]byte, len(data))
  1660  	copy(f.body, data)
  1661  
  1662  	return len(f.body), nil
  1663  }
  1664  
  1665  func (f *localResponseWriter) WriteHeader(c int) {
  1666  	f.statusCode = c
  1667  }
  1668  
  1669  func testWriteJSON(t *testing.T, testCode int, testData interface{}) {
  1670  	testDataMarshalled, err := json.Marshal(testData)
  1671  	if err != nil {
  1672  		t.Fatal(err)
  1673  	}
  1674  
  1675  	rsp := newWriter()
  1676  	writeJSON(rsp, testCode, testData)
  1677  	if rsp.statusCode != testCode {
  1678  		t.Fatalf("writeJSON() failed to set the status code. Expected %d. Got %d", testCode, rsp.statusCode)
  1679  	}
  1680  	// writeJSON calls json.Encode and it appends '\n' to the result,
  1681  	// while json.Marshal not
  1682  	expected := append(testDataMarshalled, byte('\n'))
  1683  	if !bytes.Equal(expected, rsp.body) {
  1684  		t.Fatalf("writeJSON() failed to set the body. Expected %q. Got %q", expected, rsp.body)
  1685  	}
  1686  }
  1687  
  1688  func TestWriteJSON(t *testing.T) {
  1689  	testWriteJSON(t, 55, "test data as string")
  1690  	testWriteJSON(t, 55, []byte("test data as bytes"))
  1691  }
  1692  
  1693  func TestHttpHandlerUninit(t *testing.T) {
  1694  	defer testutils.SetupTestOSContext(t)()
  1695  
  1696  	// Cleanup local datastore file
  1697  	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
  1698  
  1699  	c, err := libnetwork.New()
  1700  	if err != nil {
  1701  		t.Fatal(err)
  1702  	}
  1703  	defer c.Stop()
  1704  
  1705  	h := &httpHandler{c: c}
  1706  	h.initRouter()
  1707  	if h.r == nil {
  1708  		t.Fatal("initRouter() did not initialize the router")
  1709  	}
  1710  
  1711  	rsp := newWriter()
  1712  	req, err := http.NewRequest("GET", "/v1.19/networks", nil)
  1713  	if err != nil {
  1714  		t.Fatal(err)
  1715  	}
  1716  
  1717  	handleRequest := NewHTTPHandler(nil)
  1718  	handleRequest(rsp, req)
  1719  	if rsp.statusCode != http.StatusServiceUnavailable {
  1720  		t.Fatalf("Expected (%d). Got (%d): %s", http.StatusServiceUnavailable, rsp.statusCode, rsp.body)
  1721  	}
  1722  
  1723  	handleRequest = NewHTTPHandler(c)
  1724  
  1725  	handleRequest(rsp, req)
  1726  	if rsp.statusCode != http.StatusOK {
  1727  		t.Fatalf("Expected (%d). Got: (%d): %s", http.StatusOK, rsp.statusCode, rsp.body)
  1728  	}
  1729  
  1730  	var list []*networkResource
  1731  	err = json.Unmarshal(rsp.body, &list)
  1732  	if err != nil {
  1733  		t.Fatal(err)
  1734  	}
  1735  	if len(list) != 0 {
  1736  		t.Fatalf("Expected empty list. Got %v", list)
  1737  	}
  1738  
  1739  	n, err := c.NewNetwork(bridgeNetType, "didietro", "", nil)
  1740  	if err != nil {
  1741  		t.Fatal(err)
  1742  	}
  1743  	nwr := buildNetworkResource(n)
  1744  	expected, err := json.Marshal([]*networkResource{nwr})
  1745  	if err != nil {
  1746  		t.Fatal(err)
  1747  	}
  1748  
  1749  	handleRequest(rsp, req)
  1750  	if rsp.statusCode != http.StatusOK {
  1751  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  1752  	}
  1753  	if len(rsp.body) == 0 {
  1754  		t.Fatal("Empty list of networks")
  1755  	}
  1756  	if bytes.Equal(rsp.body, expected) {
  1757  		t.Fatal("Incorrect list of networks in response's body")
  1758  	}
  1759  }
  1760  
  1761  func TestHttpHandlerBadBody(t *testing.T) {
  1762  	defer testutils.SetupTestOSContext(t)()
  1763  
  1764  	rsp := newWriter()
  1765  
  1766  	// Cleanup local datastore file
  1767  	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
  1768  
  1769  	c, err := libnetwork.New()
  1770  	if err != nil {
  1771  		t.Fatal(err)
  1772  	}
  1773  	defer c.Stop()
  1774  	handleRequest := NewHTTPHandler(c)
  1775  
  1776  	req, err := http.NewRequest("POST", "/v1.19/networks", &localReader{beBad: true})
  1777  	if err != nil {
  1778  		t.Fatal(err)
  1779  	}
  1780  	handleRequest(rsp, req)
  1781  	if rsp.statusCode != http.StatusBadRequest {
  1782  		t.Fatalf("Unexpected status code. Expected (%d). Got (%d): %s.", http.StatusBadRequest, rsp.statusCode, string(rsp.body))
  1783  	}
  1784  
  1785  	body := []byte{}
  1786  	lr := newLocalReader(body)
  1787  	req, err = http.NewRequest("POST", "/v1.19/networks", lr)
  1788  	if err != nil {
  1789  		t.Fatal(err)
  1790  	}
  1791  	handleRequest(rsp, req)
  1792  	if rsp.statusCode != http.StatusBadRequest {
  1793  		t.Fatalf("Unexpected status code. Expected (%d). Got (%d): %s.", http.StatusBadRequest, rsp.statusCode, string(rsp.body))
  1794  	}
  1795  }
  1796  
  1797  func TestEndToEnd(t *testing.T) {
  1798  	defer testutils.SetupTestOSContext(t)()
  1799  
  1800  	rsp := newWriter()
  1801  
  1802  	// Cleanup local datastore file
  1803  	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
  1804  
  1805  	c, err := libnetwork.New()
  1806  	if err != nil {
  1807  		t.Fatal(err)
  1808  	}
  1809  	defer c.Stop()
  1810  
  1811  	handleRequest := NewHTTPHandler(c)
  1812  
  1813  	dops := GetOpsMap("cdef", "1460")
  1814  	nops := map[string]string{}
  1815  
  1816  	// Create network
  1817  	nc := networkCreate{Name: "network-fiftyfive", NetworkType: bridgeNetType, DriverOpts: dops, NetworkOpts: nops}
  1818  	body, err := json.Marshal(nc)
  1819  	if err != nil {
  1820  		t.Fatal(err)
  1821  	}
  1822  	lr := newLocalReader(body)
  1823  	req, err := http.NewRequest("POST", "/v1.19/networks", lr)
  1824  	if err != nil {
  1825  		t.Fatal(err)
  1826  	}
  1827  	handleRequest(rsp, req)
  1828  	if rsp.statusCode != http.StatusCreated {
  1829  		t.Fatalf("Unexpected status code. Expected (%d). Got (%d): %s.", http.StatusCreated, rsp.statusCode, string(rsp.body))
  1830  	}
  1831  	if len(rsp.body) == 0 {
  1832  		t.Fatal("Empty response body")
  1833  	}
  1834  
  1835  	var nid string
  1836  	err = json.Unmarshal(rsp.body, &nid)
  1837  	if err != nil {
  1838  		t.Fatal(err)
  1839  	}
  1840  
  1841  	// Query networks collection
  1842  	req, err = http.NewRequest("GET", "/v1.19/networks?name=", nil)
  1843  	if err != nil {
  1844  		t.Fatal(err)
  1845  	}
  1846  	handleRequest(rsp, req)
  1847  	if rsp.statusCode != http.StatusOK {
  1848  		t.Fatalf("Expected StatusOK. Got (%d): %s", rsp.statusCode, rsp.body)
  1849  	}
  1850  	var list []*networkResource
  1851  	err = json.Unmarshal(rsp.body, &list)
  1852  	if err != nil {
  1853  		t.Fatal(err)
  1854  	}
  1855  	if len(list) != 0 {
  1856  		t.Fatalf("Expected empty list. Got %v", list)
  1857  	}
  1858  
  1859  	req, err = http.NewRequest("GET", "/v1.19/networks", nil)
  1860  	if err != nil {
  1861  		t.Fatal(err)
  1862  	}
  1863  	handleRequest(rsp, req)
  1864  	if rsp.statusCode != http.StatusOK {
  1865  		t.Fatalf("Expected StatusOK. Got (%d): %s", rsp.statusCode, rsp.body)
  1866  	}
  1867  
  1868  	b0 := make([]byte, len(rsp.body))
  1869  	copy(b0, rsp.body)
  1870  
  1871  	req, err = http.NewRequest("GET", "/v1.19/networks?name=network-fiftyfive", nil)
  1872  	if err != nil {
  1873  		t.Fatal(err)
  1874  	}
  1875  	handleRequest(rsp, req)
  1876  	if rsp.statusCode != http.StatusOK {
  1877  		t.Fatalf("Expected StatusOK. Got (%d): %s", rsp.statusCode, rsp.body)
  1878  	}
  1879  
  1880  	if !bytes.Equal(b0, rsp.body) {
  1881  		t.Fatal("Expected same body from GET /networks and GET /networks?name=<nw> when only network <nw> exist.")
  1882  	}
  1883  
  1884  	// Query network by name
  1885  	req, err = http.NewRequest("GET", "/v1.19/networks?name=culo", nil)
  1886  	if err != nil {
  1887  		t.Fatal(err)
  1888  	}
  1889  	handleRequest(rsp, req)
  1890  	if rsp.statusCode != http.StatusOK {
  1891  		t.Fatalf("Expected StatusOK. Got (%d): %s", rsp.statusCode, rsp.body)
  1892  	}
  1893  
  1894  	err = json.Unmarshal(rsp.body, &list)
  1895  	if err != nil {
  1896  		t.Fatal(err)
  1897  	}
  1898  	if len(list) != 0 {
  1899  		t.Fatalf("Expected empty list. Got %v", list)
  1900  	}
  1901  
  1902  	req, err = http.NewRequest("GET", "/v1.19/networks?name=network-fiftyfive", nil)
  1903  	if err != nil {
  1904  		t.Fatal(err)
  1905  	}
  1906  	handleRequest(rsp, req)
  1907  	if rsp.statusCode != http.StatusOK {
  1908  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  1909  	}
  1910  
  1911  	err = json.Unmarshal(rsp.body, &list)
  1912  	if err != nil {
  1913  		t.Fatal(err)
  1914  	}
  1915  	if len(list) == 0 {
  1916  		t.Fatal("Expected non empty list")
  1917  	}
  1918  	if list[0].Name != "network-fiftyfive" || nid != list[0].ID {
  1919  		t.Fatalf("Incongruent resource found: %v", list[0])
  1920  	}
  1921  
  1922  	// Query network by partial id
  1923  	chars := []byte(nid)
  1924  	partial := string(chars[0 : len(chars)/2])
  1925  	req, err = http.NewRequest("GET", "/v1.19/networks?partial-id="+partial, nil)
  1926  	if err != nil {
  1927  		t.Fatal(err)
  1928  	}
  1929  	handleRequest(rsp, req)
  1930  	if rsp.statusCode != http.StatusOK {
  1931  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  1932  	}
  1933  
  1934  	err = json.Unmarshal(rsp.body, &list)
  1935  	if err != nil {
  1936  		t.Fatal(err)
  1937  	}
  1938  	if len(list) == 0 {
  1939  		t.Fatal("Expected non empty list")
  1940  	}
  1941  	if list[0].Name != "network-fiftyfive" || nid != list[0].ID {
  1942  		t.Fatalf("Incongruent resource found: %v", list[0])
  1943  	}
  1944  
  1945  	// Get network by id
  1946  	req, err = http.NewRequest("GET", "/v1.19/networks/"+nid, nil)
  1947  	if err != nil {
  1948  		t.Fatal(err)
  1949  	}
  1950  	handleRequest(rsp, req)
  1951  	if rsp.statusCode != http.StatusOK {
  1952  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  1953  	}
  1954  
  1955  	var nwr networkResource
  1956  	err = json.Unmarshal(rsp.body, &nwr)
  1957  	if err != nil {
  1958  		t.Fatal(err)
  1959  	}
  1960  	if nwr.Name != "network-fiftyfive" || nid != nwr.ID {
  1961  		t.Fatalf("Incongruent resource found: %v", nwr)
  1962  	}
  1963  
  1964  	// Create endpoint
  1965  	eb, err := json.Marshal(endpointCreate{Name: "ep-TwentyTwo"})
  1966  	if err != nil {
  1967  		t.Fatal(err)
  1968  	}
  1969  
  1970  	lr = newLocalReader(eb)
  1971  	req, err = http.NewRequest("POST", "/v1.19/networks/"+nid+"/endpoints", lr)
  1972  	if err != nil {
  1973  		t.Fatal(err)
  1974  	}
  1975  	handleRequest(rsp, req)
  1976  	if rsp.statusCode != http.StatusCreated {
  1977  		t.Fatalf("Unexpected status code. Expected (%d). Got (%d): %s.", http.StatusCreated, rsp.statusCode, string(rsp.body))
  1978  	}
  1979  	if len(rsp.body) == 0 {
  1980  		t.Fatal("Empty response body")
  1981  	}
  1982  
  1983  	var eid string
  1984  	err = json.Unmarshal(rsp.body, &eid)
  1985  	if err != nil {
  1986  		t.Fatal(err)
  1987  	}
  1988  
  1989  	// Query endpoint(s)
  1990  	req, err = http.NewRequest("GET", "/v1.19/networks/"+nid+"/endpoints", nil)
  1991  	if err != nil {
  1992  		t.Fatal(err)
  1993  	}
  1994  	handleRequest(rsp, req)
  1995  	if rsp.statusCode != http.StatusOK {
  1996  		t.Fatalf("Expected StatusOK. Got (%d): %s", rsp.statusCode, rsp.body)
  1997  	}
  1998  
  1999  	req, err = http.NewRequest("GET", "/v1.19/networks/"+nid+"/endpoints?name=bla", nil)
  2000  	if err != nil {
  2001  		t.Fatal(err)
  2002  	}
  2003  	handleRequest(rsp, req)
  2004  	if rsp.statusCode != http.StatusOK {
  2005  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  2006  	}
  2007  	var epList []*endpointResource
  2008  	err = json.Unmarshal(rsp.body, &epList)
  2009  	if err != nil {
  2010  		t.Fatal(err)
  2011  	}
  2012  	if len(epList) != 0 {
  2013  		t.Fatalf("Expected empty list. Got %v", epList)
  2014  	}
  2015  
  2016  	// Query endpoint by name
  2017  	req, err = http.NewRequest("GET", "/v1.19/networks/"+nid+"/endpoints?name=ep-TwentyTwo", nil)
  2018  	if err != nil {
  2019  		t.Fatal(err)
  2020  	}
  2021  	handleRequest(rsp, req)
  2022  	if rsp.statusCode != http.StatusOK {
  2023  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  2024  	}
  2025  
  2026  	err = json.Unmarshal(rsp.body, &epList)
  2027  	if err != nil {
  2028  		t.Fatal(err)
  2029  	}
  2030  	if len(epList) == 0 {
  2031  		t.Fatal("Empty response body")
  2032  	}
  2033  	if epList[0].Name != "ep-TwentyTwo" || eid != epList[0].ID {
  2034  		t.Fatalf("Incongruent resource found: %v", epList[0])
  2035  	}
  2036  
  2037  	// Query endpoint by partial id
  2038  	chars = []byte(eid)
  2039  	partial = string(chars[0 : len(chars)/2])
  2040  	req, err = http.NewRequest("GET", "/v1.19/networks/"+nid+"/endpoints?partial-id="+partial, nil)
  2041  	if err != nil {
  2042  		t.Fatal(err)
  2043  	}
  2044  	handleRequest(rsp, req)
  2045  	if rsp.statusCode != http.StatusOK {
  2046  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  2047  	}
  2048  
  2049  	err = json.Unmarshal(rsp.body, &epList)
  2050  	if err != nil {
  2051  		t.Fatal(err)
  2052  	}
  2053  	if len(epList) == 0 {
  2054  		t.Fatal("Empty response body")
  2055  	}
  2056  	if epList[0].Name != "ep-TwentyTwo" || eid != epList[0].ID {
  2057  		t.Fatalf("Incongruent resource found: %v", epList[0])
  2058  	}
  2059  
  2060  	// Get endpoint by id
  2061  	req, err = http.NewRequest("GET", "/v1.19/networks/"+nid+"/endpoints/"+eid, nil)
  2062  	if err != nil {
  2063  		t.Fatal(err)
  2064  	}
  2065  	handleRequest(rsp, req)
  2066  	if rsp.statusCode != http.StatusOK {
  2067  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  2068  	}
  2069  
  2070  	var epr endpointResource
  2071  	err = json.Unmarshal(rsp.body, &epr)
  2072  	if err != nil {
  2073  		t.Fatal(err)
  2074  	}
  2075  	if epr.Name != "ep-TwentyTwo" || epr.ID != eid {
  2076  		t.Fatalf("Incongruent resource found: %v", epr)
  2077  	}
  2078  
  2079  	// Store two container ids and one partial ids
  2080  	cid1 := "container10010000000"
  2081  	cid2 := "container20010000000"
  2082  	chars = []byte(cid1)
  2083  	cpid1 := string(chars[0 : len(chars)/2])
  2084  
  2085  	// Create sandboxes
  2086  	sb1, err := json.Marshal(sandboxCreate{
  2087  		ContainerID: cid1,
  2088  		PortMapping: getPortMapping(),
  2089  	})
  2090  	if err != nil {
  2091  		t.Fatal(err)
  2092  	}
  2093  
  2094  	lr = newLocalReader(sb1)
  2095  	req, err = http.NewRequest("POST", "/v5.22/sandboxes", lr)
  2096  	if err != nil {
  2097  		t.Fatal(err)
  2098  	}
  2099  	handleRequest(rsp, req)
  2100  	if rsp.statusCode != http.StatusCreated {
  2101  		t.Fatalf("Unexpected status code. Expected (%d). Got (%d): %s.", http.StatusCreated, rsp.statusCode, string(rsp.body))
  2102  	}
  2103  	if len(rsp.body) == 0 {
  2104  		t.Fatal("Empty response body")
  2105  	}
  2106  	// Get sandbox id and partial id
  2107  	var sid1 string
  2108  	err = json.Unmarshal(rsp.body, &sid1)
  2109  	if err != nil {
  2110  		t.Fatal(err)
  2111  	}
  2112  
  2113  	sb2, err := json.Marshal(sandboxCreate{
  2114  		ContainerID:  cid2,
  2115  		ExposedPorts: getExposedPorts(),
  2116  	})
  2117  	if err != nil {
  2118  		t.Fatal(err)
  2119  	}
  2120  
  2121  	lr = newLocalReader(sb2)
  2122  	req, err = http.NewRequest("POST", "/v5.22/sandboxes", lr)
  2123  	if err != nil {
  2124  		t.Fatal(err)
  2125  	}
  2126  	handleRequest(rsp, req)
  2127  	if rsp.statusCode != http.StatusCreated {
  2128  		t.Fatalf("Unexpected status code. Expected (%d). Got (%d): %s.", http.StatusCreated, rsp.statusCode, string(rsp.body))
  2129  	}
  2130  	if len(rsp.body) == 0 {
  2131  		t.Fatal("Empty response body")
  2132  	}
  2133  	// Get sandbox id and partial id
  2134  	var sid2 string
  2135  	err = json.Unmarshal(rsp.body, &sid2)
  2136  	if err != nil {
  2137  		t.Fatal(err)
  2138  	}
  2139  	chars = []byte(sid2)
  2140  	spid2 := string(chars[0 : len(chars)/2])
  2141  
  2142  	// Query sandboxes
  2143  	req, err = http.NewRequest("GET", "/sandboxes", nil)
  2144  	if err != nil {
  2145  		t.Fatal(err)
  2146  	}
  2147  	handleRequest(rsp, req)
  2148  	if rsp.statusCode != http.StatusOK {
  2149  		t.Fatalf("Expected StatusOK. Got (%d): %s", rsp.statusCode, rsp.body)
  2150  	}
  2151  
  2152  	var sbList []*sandboxResource
  2153  	err = json.Unmarshal(rsp.body, &sbList)
  2154  	if err != nil {
  2155  		t.Fatal(err)
  2156  	}
  2157  	if len(sbList) != 2 {
  2158  		t.Fatalf("Expected 2 elements in list. Got %v", sbList)
  2159  	}
  2160  
  2161  	// Get sandbox by id
  2162  	req, err = http.NewRequest("GET", "/sandboxes/"+sid1, nil)
  2163  	if err != nil {
  2164  		t.Fatal(err)
  2165  	}
  2166  	handleRequest(rsp, req)
  2167  	if rsp.statusCode != http.StatusOK {
  2168  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  2169  	}
  2170  
  2171  	var sbr sandboxResource
  2172  	err = json.Unmarshal(rsp.body, &sbr)
  2173  	if err != nil {
  2174  		t.Fatal(err)
  2175  	}
  2176  	if sbr.ContainerID != cid1 {
  2177  		t.Fatalf("Incongruent resource found: %v", sbr)
  2178  	}
  2179  
  2180  	// Query sandbox by partial sandbox id
  2181  	req, err = http.NewRequest("GET", "/sandboxes?partial-id="+spid2, nil)
  2182  	if err != nil {
  2183  		t.Fatal(err)
  2184  	}
  2185  	handleRequest(rsp, req)
  2186  	if rsp.statusCode != http.StatusOK {
  2187  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  2188  	}
  2189  
  2190  	err = json.Unmarshal(rsp.body, &sbList)
  2191  	if err != nil {
  2192  		t.Fatal(err)
  2193  	}
  2194  	if len(sbList) == 0 {
  2195  		t.Fatal("Empty response body")
  2196  	}
  2197  	if sbList[0].ID != sid2 {
  2198  		t.Fatalf("Incongruent resource found: %v", sbList[0])
  2199  	}
  2200  
  2201  	// Query sandbox by container id
  2202  	req, err = http.NewRequest("GET", "/sandboxes?container-id="+cid2, nil)
  2203  	if err != nil {
  2204  		t.Fatal(err)
  2205  	}
  2206  	handleRequest(rsp, req)
  2207  	if rsp.statusCode != http.StatusOK {
  2208  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  2209  	}
  2210  
  2211  	err = json.Unmarshal(rsp.body, &sbList)
  2212  	if err != nil {
  2213  		t.Fatal(err)
  2214  	}
  2215  	if len(sbList) == 0 {
  2216  		t.Fatal("Empty response body")
  2217  	}
  2218  	if sbList[0].ContainerID != cid2 {
  2219  		t.Fatalf("Incongruent resource found: %v", sbList[0])
  2220  	}
  2221  
  2222  	// Query sandbox by partial container id
  2223  	req, err = http.NewRequest("GET", "/sandboxes?partial-container-id="+cpid1, nil)
  2224  	if err != nil {
  2225  		t.Fatal(err)
  2226  	}
  2227  	handleRequest(rsp, req)
  2228  	if rsp.statusCode != http.StatusOK {
  2229  		t.Fatalf("Unexpected failure: (%d): %s", rsp.statusCode, rsp.body)
  2230  	}
  2231  
  2232  	err = json.Unmarshal(rsp.body, &sbList)
  2233  	if err != nil {
  2234  		t.Fatal(err)
  2235  	}
  2236  	if len(sbList) == 0 {
  2237  		t.Fatal("Empty response body")
  2238  	}
  2239  	if sbList[0].ContainerID != cid1 {
  2240  		t.Fatalf("Incongruent resource found: %v", sbList[0])
  2241  	}
  2242  }
  2243  
  2244  func TestEndToEndErrorMessage(t *testing.T) {
  2245  	defer testutils.SetupTestOSContext(t)()
  2246  
  2247  	rsp := newWriter()
  2248  
  2249  	// Cleanup local datastore file
  2250  	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
  2251  
  2252  	c, err := libnetwork.New()
  2253  	if err != nil {
  2254  		t.Fatal(err)
  2255  	}
  2256  	defer c.Stop()
  2257  	handleRequest := NewHTTPHandler(c)
  2258  
  2259  	body := []byte{}
  2260  	lr := newLocalReader(body)
  2261  	req, err := http.NewRequest("POST", "/v1.19/networks", lr)
  2262  	if err != nil {
  2263  		t.Fatal(err)
  2264  	}
  2265  	handleRequest(rsp, req)
  2266  
  2267  	if len(rsp.body) == 0 {
  2268  		t.Fatal("Empty response body.")
  2269  	}
  2270  	empty := []byte("\"\"")
  2271  	if bytes.Equal(empty, bytes.TrimSpace(rsp.body)) {
  2272  		t.Fatal("Empty response error message.")
  2273  	}
  2274  }
  2275  
  2276  type bre struct{}
  2277  
  2278  func (b *bre) Error() string {
  2279  	return "I am a bad request error"
  2280  }
  2281  func (b *bre) BadRequest() {}
  2282  
  2283  type nfe struct{}
  2284  
  2285  func (n *nfe) Error() string {
  2286  	return "I am a not found error"
  2287  }
  2288  func (n *nfe) NotFound() {}
  2289  
  2290  type forb struct{}
  2291  
  2292  func (f *forb) Error() string {
  2293  	return "I am a bad request error"
  2294  }
  2295  func (f *forb) Forbidden() {}
  2296  
  2297  type notimpl struct{}
  2298  
  2299  func (nip *notimpl) Error() string {
  2300  	return "I am a not implemented error"
  2301  }
  2302  func (nip *notimpl) NotImplemented() {}
  2303  
  2304  type inter struct{}
  2305  
  2306  func (it *inter) Error() string {
  2307  	return "I am an internal error"
  2308  }
  2309  func (it *inter) Internal() {}
  2310  
  2311  type tout struct{}
  2312  
  2313  func (to *tout) Error() string {
  2314  	return "I am a timeout error"
  2315  }
  2316  func (to *tout) Timeout() {}
  2317  
  2318  type noserv struct{}
  2319  
  2320  func (nos *noserv) Error() string {
  2321  	return "I am a no service error"
  2322  }
  2323  func (nos *noserv) NoService() {}
  2324  
  2325  type notclassified struct{}
  2326  
  2327  func (noc *notclassified) Error() string {
  2328  	return "I am a non classified error"
  2329  }
  2330  
  2331  func TestErrorConversion(t *testing.T) {
  2332  	if convertNetworkError(new(bre)).StatusCode != http.StatusBadRequest {
  2333  		t.Fatal("Failed to recognize BadRequest error")
  2334  	}
  2335  
  2336  	if convertNetworkError(new(nfe)).StatusCode != http.StatusNotFound {
  2337  		t.Fatal("Failed to recognize NotFound error")
  2338  	}
  2339  
  2340  	if convertNetworkError(new(forb)).StatusCode != http.StatusForbidden {
  2341  		t.Fatal("Failed to recognize Forbidden error")
  2342  	}
  2343  
  2344  	if convertNetworkError(new(notimpl)).StatusCode != http.StatusNotImplemented {
  2345  		t.Fatal("Failed to recognize NotImplemented error")
  2346  	}
  2347  
  2348  	if convertNetworkError(new(inter)).StatusCode != http.StatusInternalServerError {
  2349  		t.Fatal("Failed to recognize Internal error")
  2350  	}
  2351  
  2352  	if convertNetworkError(new(tout)).StatusCode != http.StatusRequestTimeout {
  2353  		t.Fatal("Failed to recognize Timeout error")
  2354  	}
  2355  
  2356  	if convertNetworkError(new(noserv)).StatusCode != http.StatusServiceUnavailable {
  2357  		t.Fatal("Failed to recognize No Service error")
  2358  	}
  2359  
  2360  	if convertNetworkError(new(notclassified)).StatusCode != http.StatusInternalServerError {
  2361  		t.Fatal("Failed to recognize not classified error as Internal error")
  2362  	}
  2363  }
  2364  
  2365  func TestFieldRegex(t *testing.T) {
  2366  	pr := regexp.MustCompile(regex)
  2367  	qr := regexp.MustCompile(`^` + qregx + `$`) // mux compiles it like this
  2368  
  2369  	if pr.MatchString("") {
  2370  		t.Fatal("Unexpected match")
  2371  	}
  2372  	if !qr.MatchString("") {
  2373  		t.Fatal("Unexpected match failure")
  2374  	}
  2375  
  2376  	if pr.MatchString(":") {
  2377  		t.Fatal("Unexpected match")
  2378  	}
  2379  	if qr.MatchString(":") {
  2380  		t.Fatal("Unexpected match")
  2381  	}
  2382  
  2383  	if pr.MatchString(".") {
  2384  		t.Fatal("Unexpected match")
  2385  	}
  2386  	if qr.MatchString(".") {
  2387  		t.Fatal("Unexpected match")
  2388  	}
  2389  }