github.com/ferranbt/nomad@v0.9.3-0.20190607002617-85c449b7667c/nomad/structs/network_test.go (about)

     1  package structs
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"reflect"
     7  	"testing"
     8  )
     9  
    10  func TestNetworkIndex_Overcommitted(t *testing.T) {
    11  	idx := NewNetworkIndex()
    12  
    13  	// Consume some network
    14  	reserved := &NetworkResource{
    15  		Device:        "eth0",
    16  		IP:            "192.168.0.100",
    17  		MBits:         505,
    18  		ReservedPorts: []Port{{"one", 8000}, {"two", 9000}},
    19  	}
    20  	collide := idx.AddReserved(reserved)
    21  	if collide {
    22  		t.Fatalf("bad")
    23  	}
    24  	if !idx.Overcommitted() {
    25  		t.Fatalf("have no resources")
    26  	}
    27  
    28  	// Add resources
    29  	n := &Node{
    30  		NodeResources: &NodeResources{
    31  			Networks: []*NetworkResource{
    32  				{
    33  					Device: "eth0",
    34  					CIDR:   "192.168.0.100/32",
    35  					MBits:  1000,
    36  				},
    37  			},
    38  		},
    39  	}
    40  	idx.SetNode(n)
    41  	if idx.Overcommitted() {
    42  		t.Fatalf("have resources")
    43  	}
    44  
    45  	// Double up our usage
    46  	idx.AddReserved(reserved)
    47  	if !idx.Overcommitted() {
    48  		t.Fatalf("should be overcommitted")
    49  	}
    50  }
    51  
    52  func TestNetworkIndex_SetNode(t *testing.T) {
    53  	idx := NewNetworkIndex()
    54  	n := &Node{
    55  		NodeResources: &NodeResources{
    56  			Networks: []*NetworkResource{
    57  				{
    58  					Device: "eth0",
    59  					CIDR:   "192.168.0.100/32",
    60  					IP:     "192.168.0.100",
    61  					MBits:  1000,
    62  				},
    63  			},
    64  		},
    65  		ReservedResources: &NodeReservedResources{
    66  			Networks: NodeReservedNetworkResources{
    67  				ReservedHostPorts: "22",
    68  			},
    69  		},
    70  	}
    71  	collide := idx.SetNode(n)
    72  	if collide {
    73  		t.Fatalf("bad")
    74  	}
    75  
    76  	if len(idx.AvailNetworks) != 1 {
    77  		t.Fatalf("Bad")
    78  	}
    79  	if idx.AvailBandwidth["eth0"] != 1000 {
    80  		t.Fatalf("Bad")
    81  	}
    82  	if !idx.UsedPorts["192.168.0.100"].Check(22) {
    83  		t.Fatalf("Bad")
    84  	}
    85  }
    86  
    87  func TestNetworkIndex_AddAllocs(t *testing.T) {
    88  	idx := NewNetworkIndex()
    89  	allocs := []*Allocation{
    90  		{
    91  			AllocatedResources: &AllocatedResources{
    92  				Tasks: map[string]*AllocatedTaskResources{
    93  					"web": {
    94  						Networks: []*NetworkResource{
    95  							{
    96  								Device:        "eth0",
    97  								IP:            "192.168.0.100",
    98  								MBits:         20,
    99  								ReservedPorts: []Port{{"one", 8000}, {"two", 9000}},
   100  							},
   101  						},
   102  					},
   103  				},
   104  			},
   105  		},
   106  		{
   107  			AllocatedResources: &AllocatedResources{
   108  				Tasks: map[string]*AllocatedTaskResources{
   109  					"api": {
   110  						Networks: []*NetworkResource{
   111  							{
   112  								Device:        "eth0",
   113  								IP:            "192.168.0.100",
   114  								MBits:         50,
   115  								ReservedPorts: []Port{{"one", 10000}},
   116  							},
   117  						},
   118  					},
   119  				},
   120  			},
   121  		},
   122  	}
   123  	collide := idx.AddAllocs(allocs)
   124  	if collide {
   125  		t.Fatalf("bad")
   126  	}
   127  
   128  	if idx.UsedBandwidth["eth0"] != 70 {
   129  		t.Fatalf("Bad")
   130  	}
   131  	if !idx.UsedPorts["192.168.0.100"].Check(8000) {
   132  		t.Fatalf("Bad")
   133  	}
   134  	if !idx.UsedPorts["192.168.0.100"].Check(9000) {
   135  		t.Fatalf("Bad")
   136  	}
   137  	if !idx.UsedPorts["192.168.0.100"].Check(10000) {
   138  		t.Fatalf("Bad")
   139  	}
   140  }
   141  
   142  func TestNetworkIndex_AddReserved(t *testing.T) {
   143  	idx := NewNetworkIndex()
   144  
   145  	reserved := &NetworkResource{
   146  		Device:        "eth0",
   147  		IP:            "192.168.0.100",
   148  		MBits:         20,
   149  		ReservedPorts: []Port{{"one", 8000}, {"two", 9000}},
   150  	}
   151  	collide := idx.AddReserved(reserved)
   152  	if collide {
   153  		t.Fatalf("bad")
   154  	}
   155  
   156  	if idx.UsedBandwidth["eth0"] != 20 {
   157  		t.Fatalf("Bad")
   158  	}
   159  	if !idx.UsedPorts["192.168.0.100"].Check(8000) {
   160  		t.Fatalf("Bad")
   161  	}
   162  	if !idx.UsedPorts["192.168.0.100"].Check(9000) {
   163  		t.Fatalf("Bad")
   164  	}
   165  
   166  	// Try to reserve the same network
   167  	collide = idx.AddReserved(reserved)
   168  	if !collide {
   169  		t.Fatalf("bad")
   170  	}
   171  }
   172  
   173  // XXX Reserving ports doesn't work when yielding from a CIDR block. This is
   174  // okay for now since we do not actually fingerprint CIDR blocks.
   175  func TestNetworkIndex_yieldIP(t *testing.T) {
   176  	idx := NewNetworkIndex()
   177  	n := &Node{
   178  		NodeResources: &NodeResources{
   179  			Networks: []*NetworkResource{
   180  				{
   181  					Device: "eth0",
   182  					CIDR:   "192.168.0.100/30",
   183  					MBits:  1000,
   184  				},
   185  			},
   186  		},
   187  	}
   188  	idx.SetNode(n)
   189  
   190  	var out []string
   191  	idx.yieldIP(func(n *NetworkResource, ip net.IP) (stop bool) {
   192  		out = append(out, ip.String())
   193  		return
   194  	})
   195  
   196  	expect := []string{"192.168.0.100", "192.168.0.101",
   197  		"192.168.0.102", "192.168.0.103"}
   198  	if !reflect.DeepEqual(out, expect) {
   199  		t.Fatalf("bad: %v", out)
   200  	}
   201  }
   202  
   203  func TestNetworkIndex_AssignNetwork(t *testing.T) {
   204  	idx := NewNetworkIndex()
   205  	n := &Node{
   206  		NodeResources: &NodeResources{
   207  			Networks: []*NetworkResource{
   208  				{
   209  					Device: "eth0",
   210  					CIDR:   "192.168.0.100/30",
   211  					MBits:  1000,
   212  				},
   213  			},
   214  		},
   215  	}
   216  	idx.SetNode(n)
   217  
   218  	allocs := []*Allocation{
   219  		{
   220  			TaskResources: map[string]*Resources{
   221  				"web": {
   222  					Networks: []*NetworkResource{
   223  						{
   224  							Device:        "eth0",
   225  							IP:            "192.168.0.100",
   226  							MBits:         20,
   227  							ReservedPorts: []Port{{"one", 8000}, {"two", 9000}},
   228  						},
   229  					},
   230  				},
   231  			},
   232  		},
   233  		{
   234  			TaskResources: map[string]*Resources{
   235  				"api": {
   236  					Networks: []*NetworkResource{
   237  						{
   238  							Device:        "eth0",
   239  							IP:            "192.168.0.100",
   240  							MBits:         50,
   241  							ReservedPorts: []Port{{"main", 10000}},
   242  						},
   243  					},
   244  				},
   245  			},
   246  		},
   247  	}
   248  	idx.AddAllocs(allocs)
   249  
   250  	// Ask for a reserved port
   251  	ask := &NetworkResource{
   252  		ReservedPorts: []Port{{"main", 8000}},
   253  	}
   254  	offer, err := idx.AssignNetwork(ask)
   255  	if err != nil {
   256  		t.Fatalf("err: %v", err)
   257  	}
   258  	if offer == nil {
   259  		t.Fatalf("bad")
   260  	}
   261  	if offer.IP != "192.168.0.101" {
   262  		t.Fatalf("bad: %#v", offer)
   263  	}
   264  	rp := Port{"main", 8000}
   265  	if len(offer.ReservedPorts) != 1 || offer.ReservedPorts[0] != rp {
   266  		t.Fatalf("bad: %#v", offer)
   267  	}
   268  
   269  	// Ask for dynamic ports
   270  	ask = &NetworkResource{
   271  		DynamicPorts: []Port{{"http", 0}, {"https", 0}, {"admin", 0}},
   272  	}
   273  	offer, err = idx.AssignNetwork(ask)
   274  	if err != nil {
   275  		t.Fatalf("err: %v", err)
   276  	}
   277  	if offer == nil {
   278  		t.Fatalf("bad")
   279  	}
   280  	if offer.IP != "192.168.0.100" {
   281  		t.Fatalf("bad: %#v", offer)
   282  	}
   283  	if len(offer.DynamicPorts) != 3 {
   284  		t.Fatalf("There should be three dynamic ports")
   285  	}
   286  	for _, port := range offer.DynamicPorts {
   287  		if port.Value == 0 {
   288  			t.Fatalf("Dynamic Port: %v should have been assigned a host port", port.Label)
   289  		}
   290  	}
   291  
   292  	// Ask for reserved + dynamic ports
   293  	ask = &NetworkResource{
   294  		ReservedPorts: []Port{{"main", 2345}},
   295  		DynamicPorts:  []Port{{"http", 0}, {"https", 0}, {"admin", 0}},
   296  	}
   297  	offer, err = idx.AssignNetwork(ask)
   298  	if err != nil {
   299  		t.Fatalf("err: %v", err)
   300  	}
   301  	if offer == nil {
   302  		t.Fatalf("bad")
   303  	}
   304  	if offer.IP != "192.168.0.100" {
   305  		t.Fatalf("bad: %#v", offer)
   306  	}
   307  
   308  	rp = Port{"main", 2345}
   309  	if len(offer.ReservedPorts) != 1 || offer.ReservedPorts[0] != rp {
   310  		t.Fatalf("bad: %#v", offer)
   311  	}
   312  
   313  	// Ask for too much bandwidth
   314  	ask = &NetworkResource{
   315  		MBits: 1000,
   316  	}
   317  	offer, err = idx.AssignNetwork(ask)
   318  	if err.Error() != "bandwidth exceeded" {
   319  		t.Fatalf("err: %v", err)
   320  	}
   321  	if offer != nil {
   322  		t.Fatalf("bad")
   323  	}
   324  }
   325  
   326  // This test ensures that even with a small domain of available ports we are
   327  // able to make a dynamic port allocation.
   328  func TestNetworkIndex_AssignNetwork_Dynamic_Contention(t *testing.T) {
   329  
   330  	// Create a node that only has one free port
   331  	idx := NewNetworkIndex()
   332  	n := &Node{
   333  		NodeResources: &NodeResources{
   334  			Networks: []*NetworkResource{
   335  				{
   336  					Device: "eth0",
   337  					CIDR:   "192.168.0.100/32",
   338  					IP:     "192.168.0.100",
   339  					MBits:  1000,
   340  				},
   341  			},
   342  		},
   343  		ReservedResources: &NodeReservedResources{
   344  			Networks: NodeReservedNetworkResources{
   345  				ReservedHostPorts: fmt.Sprintf("%d-%d", MinDynamicPort, MaxDynamicPort-1),
   346  			},
   347  		},
   348  	}
   349  	idx.SetNode(n)
   350  
   351  	// Ask for dynamic ports
   352  	ask := &NetworkResource{
   353  		DynamicPorts: []Port{{"http", 0}},
   354  	}
   355  	offer, err := idx.AssignNetwork(ask)
   356  	if err != nil {
   357  		t.Fatalf("err: %v", err)
   358  	}
   359  	if offer == nil {
   360  		t.Fatalf("bad")
   361  	}
   362  	if offer.IP != "192.168.0.100" {
   363  		t.Fatalf("bad: %#v", offer)
   364  	}
   365  	if len(offer.DynamicPorts) != 1 {
   366  		t.Fatalf("There should be one dynamic ports")
   367  	}
   368  	if p := offer.DynamicPorts[0].Value; p != MaxDynamicPort {
   369  		t.Fatalf("Dynamic Port: should have been assigned %d; got %d", p, MaxDynamicPort)
   370  	}
   371  }
   372  
   373  // COMPAT(0.11): Remove in 0.11
   374  func TestNetworkIndex_Overcommitted_Old(t *testing.T) {
   375  	idx := NewNetworkIndex()
   376  
   377  	// Consume some network
   378  	reserved := &NetworkResource{
   379  		Device:        "eth0",
   380  		IP:            "192.168.0.100",
   381  		MBits:         505,
   382  		ReservedPorts: []Port{{"one", 8000}, {"two", 9000}},
   383  	}
   384  	collide := idx.AddReserved(reserved)
   385  	if collide {
   386  		t.Fatalf("bad")
   387  	}
   388  	if !idx.Overcommitted() {
   389  		t.Fatalf("have no resources")
   390  	}
   391  
   392  	// Add resources
   393  	n := &Node{
   394  		Resources: &Resources{
   395  			Networks: []*NetworkResource{
   396  				{
   397  					Device: "eth0",
   398  					CIDR:   "192.168.0.100/32",
   399  					MBits:  1000,
   400  				},
   401  			},
   402  		},
   403  	}
   404  	idx.SetNode(n)
   405  	if idx.Overcommitted() {
   406  		t.Fatalf("have resources")
   407  	}
   408  
   409  	// Double up our usage
   410  	idx.AddReserved(reserved)
   411  	if !idx.Overcommitted() {
   412  		t.Fatalf("should be overcommitted")
   413  	}
   414  }
   415  
   416  // COMPAT(0.11): Remove in 0.11
   417  func TestNetworkIndex_SetNode_Old(t *testing.T) {
   418  	idx := NewNetworkIndex()
   419  	n := &Node{
   420  		Resources: &Resources{
   421  			Networks: []*NetworkResource{
   422  				{
   423  					Device: "eth0",
   424  					CIDR:   "192.168.0.100/32",
   425  					MBits:  1000,
   426  				},
   427  			},
   428  		},
   429  		Reserved: &Resources{
   430  			Networks: []*NetworkResource{
   431  				{
   432  					Device:        "eth0",
   433  					IP:            "192.168.0.100",
   434  					ReservedPorts: []Port{{"ssh", 22}},
   435  					MBits:         1,
   436  				},
   437  			},
   438  		},
   439  	}
   440  	collide := idx.SetNode(n)
   441  	if collide {
   442  		t.Fatalf("bad")
   443  	}
   444  
   445  	if len(idx.AvailNetworks) != 1 {
   446  		t.Fatalf("Bad")
   447  	}
   448  	if idx.AvailBandwidth["eth0"] != 1000 {
   449  		t.Fatalf("Bad")
   450  	}
   451  	if idx.UsedBandwidth["eth0"] != 1 {
   452  		t.Fatalf("Bad")
   453  	}
   454  	if !idx.UsedPorts["192.168.0.100"].Check(22) {
   455  		t.Fatalf("Bad")
   456  	}
   457  }
   458  
   459  // COMPAT(0.11): Remove in 0.11
   460  func TestNetworkIndex_AddAllocs_Old(t *testing.T) {
   461  	idx := NewNetworkIndex()
   462  	allocs := []*Allocation{
   463  		{
   464  			TaskResources: map[string]*Resources{
   465  				"web": {
   466  					Networks: []*NetworkResource{
   467  						{
   468  							Device:        "eth0",
   469  							IP:            "192.168.0.100",
   470  							MBits:         20,
   471  							ReservedPorts: []Port{{"one", 8000}, {"two", 9000}},
   472  						},
   473  					},
   474  				},
   475  			},
   476  		},
   477  		{
   478  			TaskResources: map[string]*Resources{
   479  				"api": {
   480  					Networks: []*NetworkResource{
   481  						{
   482  							Device:        "eth0",
   483  							IP:            "192.168.0.100",
   484  							MBits:         50,
   485  							ReservedPorts: []Port{{"one", 10000}},
   486  						},
   487  					},
   488  				},
   489  			},
   490  		},
   491  	}
   492  	collide := idx.AddAllocs(allocs)
   493  	if collide {
   494  		t.Fatalf("bad")
   495  	}
   496  
   497  	if idx.UsedBandwidth["eth0"] != 70 {
   498  		t.Fatalf("Bad")
   499  	}
   500  	if !idx.UsedPorts["192.168.0.100"].Check(8000) {
   501  		t.Fatalf("Bad")
   502  	}
   503  	if !idx.UsedPorts["192.168.0.100"].Check(9000) {
   504  		t.Fatalf("Bad")
   505  	}
   506  	if !idx.UsedPorts["192.168.0.100"].Check(10000) {
   507  		t.Fatalf("Bad")
   508  	}
   509  }
   510  
   511  // COMPAT(0.11): Remove in 0.11
   512  func TestNetworkIndex_yieldIP_Old(t *testing.T) {
   513  	idx := NewNetworkIndex()
   514  	n := &Node{
   515  		Resources: &Resources{
   516  			Networks: []*NetworkResource{
   517  				{
   518  					Device: "eth0",
   519  					CIDR:   "192.168.0.100/30",
   520  					MBits:  1000,
   521  				},
   522  			},
   523  		},
   524  		Reserved: &Resources{
   525  			Networks: []*NetworkResource{
   526  				{
   527  					Device:        "eth0",
   528  					IP:            "192.168.0.100",
   529  					ReservedPorts: []Port{{"ssh", 22}},
   530  					MBits:         1,
   531  				},
   532  			},
   533  		},
   534  	}
   535  	idx.SetNode(n)
   536  
   537  	var out []string
   538  	idx.yieldIP(func(n *NetworkResource, ip net.IP) (stop bool) {
   539  		out = append(out, ip.String())
   540  		return
   541  	})
   542  
   543  	expect := []string{"192.168.0.100", "192.168.0.101",
   544  		"192.168.0.102", "192.168.0.103"}
   545  	if !reflect.DeepEqual(out, expect) {
   546  		t.Fatalf("bad: %v", out)
   547  	}
   548  }
   549  
   550  // COMPAT(0.11): Remove in 0.11
   551  func TestNetworkIndex_AssignNetwork_Old(t *testing.T) {
   552  	idx := NewNetworkIndex()
   553  	n := &Node{
   554  		Resources: &Resources{
   555  			Networks: []*NetworkResource{
   556  				{
   557  					Device: "eth0",
   558  					CIDR:   "192.168.0.100/30",
   559  					MBits:  1000,
   560  				},
   561  			},
   562  		},
   563  		Reserved: &Resources{
   564  			Networks: []*NetworkResource{
   565  				{
   566  					Device:        "eth0",
   567  					IP:            "192.168.0.100",
   568  					ReservedPorts: []Port{{"ssh", 22}},
   569  					MBits:         1,
   570  				},
   571  			},
   572  		},
   573  	}
   574  	idx.SetNode(n)
   575  
   576  	allocs := []*Allocation{
   577  		{
   578  			TaskResources: map[string]*Resources{
   579  				"web": {
   580  					Networks: []*NetworkResource{
   581  						{
   582  							Device:        "eth0",
   583  							IP:            "192.168.0.100",
   584  							MBits:         20,
   585  							ReservedPorts: []Port{{"one", 8000}, {"two", 9000}},
   586  						},
   587  					},
   588  				},
   589  			},
   590  		},
   591  		{
   592  			TaskResources: map[string]*Resources{
   593  				"api": {
   594  					Networks: []*NetworkResource{
   595  						{
   596  							Device:        "eth0",
   597  							IP:            "192.168.0.100",
   598  							MBits:         50,
   599  							ReservedPorts: []Port{{"main", 10000}},
   600  						},
   601  					},
   602  				},
   603  			},
   604  		},
   605  	}
   606  	idx.AddAllocs(allocs)
   607  
   608  	// Ask for a reserved port
   609  	ask := &NetworkResource{
   610  		ReservedPorts: []Port{{"main", 8000}},
   611  	}
   612  	offer, err := idx.AssignNetwork(ask)
   613  	if err != nil {
   614  		t.Fatalf("err: %v", err)
   615  	}
   616  	if offer == nil {
   617  		t.Fatalf("bad")
   618  	}
   619  	if offer.IP != "192.168.0.101" {
   620  		t.Fatalf("bad: %#v", offer)
   621  	}
   622  	rp := Port{"main", 8000}
   623  	if len(offer.ReservedPorts) != 1 || offer.ReservedPorts[0] != rp {
   624  		t.Fatalf("bad: %#v", offer)
   625  	}
   626  
   627  	// Ask for dynamic ports
   628  	ask = &NetworkResource{
   629  		DynamicPorts: []Port{{"http", 0}, {"https", 0}, {"admin", 0}},
   630  	}
   631  	offer, err = idx.AssignNetwork(ask)
   632  	if err != nil {
   633  		t.Fatalf("err: %v", err)
   634  	}
   635  	if offer == nil {
   636  		t.Fatalf("bad")
   637  	}
   638  	if offer.IP != "192.168.0.100" {
   639  		t.Fatalf("bad: %#v", offer)
   640  	}
   641  	if len(offer.DynamicPorts) != 3 {
   642  		t.Fatalf("There should be three dynamic ports")
   643  	}
   644  	for _, port := range offer.DynamicPorts {
   645  		if port.Value == 0 {
   646  			t.Fatalf("Dynamic Port: %v should have been assigned a host port", port.Label)
   647  		}
   648  	}
   649  
   650  	// Ask for reserved + dynamic ports
   651  	ask = &NetworkResource{
   652  		ReservedPorts: []Port{{"main", 2345}},
   653  		DynamicPorts:  []Port{{"http", 0}, {"https", 0}, {"admin", 0}},
   654  	}
   655  	offer, err = idx.AssignNetwork(ask)
   656  	if err != nil {
   657  		t.Fatalf("err: %v", err)
   658  	}
   659  	if offer == nil {
   660  		t.Fatalf("bad")
   661  	}
   662  	if offer.IP != "192.168.0.100" {
   663  		t.Fatalf("bad: %#v", offer)
   664  	}
   665  
   666  	rp = Port{"main", 2345}
   667  	if len(offer.ReservedPorts) != 1 || offer.ReservedPorts[0] != rp {
   668  		t.Fatalf("bad: %#v", offer)
   669  	}
   670  
   671  	// Ask for too much bandwidth
   672  	ask = &NetworkResource{
   673  		MBits: 1000,
   674  	}
   675  	offer, err = idx.AssignNetwork(ask)
   676  	if err.Error() != "bandwidth exceeded" {
   677  		t.Fatalf("err: %v", err)
   678  	}
   679  	if offer != nil {
   680  		t.Fatalf("bad")
   681  	}
   682  }
   683  
   684  // COMPAT(0.11): Remove in 0.11
   685  // This test ensures that even with a small domain of available ports we are
   686  // able to make a dynamic port allocation.
   687  func TestNetworkIndex_AssignNetwork_Dynamic_Contention_Old(t *testing.T) {
   688  
   689  	// Create a node that only has one free port
   690  	idx := NewNetworkIndex()
   691  	n := &Node{
   692  		Resources: &Resources{
   693  			Networks: []*NetworkResource{
   694  				{
   695  					Device: "eth0",
   696  					CIDR:   "192.168.0.100/32",
   697  					MBits:  1000,
   698  				},
   699  			},
   700  		},
   701  		Reserved: &Resources{
   702  			Networks: []*NetworkResource{
   703  				{
   704  					Device: "eth0",
   705  					IP:     "192.168.0.100",
   706  					MBits:  1,
   707  				},
   708  			},
   709  		},
   710  	}
   711  	for i := MinDynamicPort; i < MaxDynamicPort; i++ {
   712  		n.Reserved.Networks[0].ReservedPorts = append(n.Reserved.Networks[0].ReservedPorts, Port{Value: i})
   713  	}
   714  
   715  	idx.SetNode(n)
   716  
   717  	// Ask for dynamic ports
   718  	ask := &NetworkResource{
   719  		DynamicPorts: []Port{{"http", 0}},
   720  	}
   721  	offer, err := idx.AssignNetwork(ask)
   722  	if err != nil {
   723  		t.Fatalf("err: %v", err)
   724  	}
   725  	if offer == nil {
   726  		t.Fatalf("bad")
   727  	}
   728  	if offer.IP != "192.168.0.100" {
   729  		t.Fatalf("bad: %#v", offer)
   730  	}
   731  	if len(offer.DynamicPorts) != 1 {
   732  		t.Fatalf("There should be three dynamic ports")
   733  	}
   734  	if p := offer.DynamicPorts[0].Value; p != MaxDynamicPort {
   735  		t.Fatalf("Dynamic Port: should have been assigned %d; got %d", p, MaxDynamicPort)
   736  	}
   737  }
   738  
   739  func TestIntContains(t *testing.T) {
   740  	l := []int{1, 2, 10, 20}
   741  	if isPortReserved(l, 50) {
   742  		t.Fatalf("bad")
   743  	}
   744  	if !isPortReserved(l, 20) {
   745  		t.Fatalf("bad")
   746  	}
   747  	if !isPortReserved(l, 1) {
   748  		t.Fatalf("bad")
   749  	}
   750  }