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