github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/core/network/portrange_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package network_test
     5  
     6  import (
     7  	jc "github.com/juju/testing/checkers"
     8  	gc "gopkg.in/check.v1"
     9  
    10  	"github.com/juju/juju/core/network"
    11  	"github.com/juju/juju/testing"
    12  )
    13  
    14  type PortRangeSuite struct {
    15  	testing.BaseSuite
    16  }
    17  
    18  var _ = gc.Suite(&PortRangeSuite{})
    19  
    20  func (*PortRangeSuite) TestConflictsWith(c *gc.C) {
    21  	var testCases = []struct {
    22  		about          string
    23  		first          network.PortRange
    24  		second         network.PortRange
    25  		expectConflict bool
    26  	}{{
    27  		"identical ports",
    28  		network.PortRange{80, 80, "TCP"},
    29  		network.PortRange{80, 80, "TCP"},
    30  		true,
    31  	}, {
    32  		"different ports",
    33  		network.PortRange{80, 80, "TCP"},
    34  		network.PortRange{90, 90, "TCP"},
    35  		false,
    36  	}, {
    37  		"touching ranges",
    38  		network.PortRange{100, 200, "TCP"},
    39  		network.PortRange{201, 240, "TCP"},
    40  		false,
    41  	}, {
    42  		"touching ranges with overlap",
    43  		network.PortRange{100, 200, "TCP"},
    44  		network.PortRange{200, 240, "TCP"},
    45  		true,
    46  	}, {
    47  		"different protocols",
    48  		network.PortRange{80, 80, "UDP"},
    49  		network.PortRange{80, 80, "TCP"},
    50  		false,
    51  	}, {
    52  		"outside range",
    53  		network.PortRange{100, 200, "TCP"},
    54  		network.PortRange{80, 80, "TCP"},
    55  		false,
    56  	}, {
    57  		"overlap end",
    58  		network.PortRange{100, 200, "TCP"},
    59  		network.PortRange{80, 120, "TCP"},
    60  		true,
    61  	}, {
    62  		"complete overlap",
    63  		network.PortRange{100, 200, "TCP"},
    64  		network.PortRange{120, 140, "TCP"},
    65  		true,
    66  	}}
    67  
    68  	for i, t := range testCases {
    69  		c.Logf("test %d: %s", i, t.about)
    70  		c.Check(t.first.ConflictsWith(t.second), gc.Equals, t.expectConflict)
    71  		c.Check(t.second.ConflictsWith(t.first), gc.Equals, t.expectConflict)
    72  	}
    73  }
    74  
    75  func (*PortRangeSuite) TestStrings(c *gc.C) {
    76  	c.Assert(
    77  		network.PortRange{80, 80, "TCP"}.String(),
    78  		gc.Equals,
    79  		"80/tcp",
    80  	)
    81  	c.Assert(
    82  		network.PortRange{80, 80, "TCP"}.GoString(),
    83  		gc.Equals,
    84  		"80/tcp",
    85  	)
    86  	c.Assert(
    87  		network.PortRange{80, 100, "TCP"}.String(),
    88  		gc.Equals,
    89  		"80-100/tcp",
    90  	)
    91  	c.Assert(
    92  		network.PortRange{80, 100, "TCP"}.GoString(),
    93  		gc.Equals,
    94  		"80-100/tcp",
    95  	)
    96  	c.Assert(
    97  		network.PortRange{-1, -1, "ICMP"}.String(),
    98  		gc.Equals,
    99  		"icmp",
   100  	)
   101  }
   102  
   103  func (*PortRangeSuite) TestValidate(c *gc.C) {
   104  	testCases := []struct {
   105  		about    string
   106  		ports    network.PortRange
   107  		expected string
   108  	}{{
   109  		"single valid port",
   110  		network.PortRange{80, 80, "tcp"},
   111  		"",
   112  	}, {
   113  		"valid port range",
   114  		network.PortRange{80, 90, "tcp"},
   115  		"",
   116  	}, {
   117  		"valid udp port range",
   118  		network.PortRange{80, 90, "UDP"},
   119  		"",
   120  	}, {
   121  		"invalid port range boundaries",
   122  		network.PortRange{90, 80, "tcp"},
   123  		"invalid port range 90-80/tcp",
   124  	}, {
   125  		"both FromPort and ToPort too large",
   126  		network.PortRange{88888, 99999, "tcp"},
   127  		"invalid port range 88888-99999/tcp",
   128  	}, {
   129  		"FromPort too large",
   130  		network.PortRange{88888, 65535, "tcp"},
   131  		"invalid port range 88888-65535/tcp",
   132  	}, {
   133  		"FromPort too small",
   134  		network.PortRange{0, 80, "tcp"},
   135  		"invalid port range 0-80/tcp",
   136  	}, {
   137  		"ToPort too large",
   138  		network.PortRange{1, 99999, "tcp"},
   139  		"invalid port range 1-99999/tcp",
   140  	}, {
   141  		"both ports 0",
   142  		network.PortRange{0, 0, "tcp"},
   143  		"invalid port range 0-0/tcp",
   144  	}, {
   145  		"invalid protocol",
   146  		network.PortRange{80, 80, "some protocol"},
   147  		`invalid protocol "some protocol", expected "tcp", "udp", or "icmp"`,
   148  	}, {
   149  		"invalid icmp port",
   150  		network.PortRange{1, 1, "icmp"},
   151  		`protocol "icmp" doesn't support any ports; got "1"`,
   152  	}}
   153  
   154  	for i, t := range testCases {
   155  		c.Logf("test %d: %s", i, t.about)
   156  		if t.expected == "" {
   157  			c.Check(t.ports.Validate(), gc.IsNil)
   158  		} else {
   159  			c.Check(t.ports.Validate(), gc.ErrorMatches, t.expected)
   160  		}
   161  	}
   162  }
   163  
   164  func (*PortRangeSuite) TestSortPortRanges(c *gc.C) {
   165  	ranges := []network.PortRange{
   166  		{10, 100, "udp"},
   167  		{80, 90, "tcp"},
   168  		{80, 80, "tcp"},
   169  	}
   170  	expected := []network.PortRange{
   171  		{80, 80, "tcp"},
   172  		{80, 90, "tcp"},
   173  		{10, 100, "udp"},
   174  	}
   175  	network.SortPortRanges(ranges)
   176  	c.Assert(ranges, gc.DeepEquals, expected)
   177  }
   178  
   179  func (*PortRangeSuite) TestCollapsePorts(c *gc.C) {
   180  	testCases := []struct {
   181  		about    string
   182  		ports    []network.Port
   183  		expected []network.PortRange
   184  	}{{
   185  		"single port",
   186  		[]network.Port{{"tcp", 80}},
   187  		[]network.PortRange{{80, 80, "tcp"}},
   188  	}, {
   189  		"continuous port range (increasing)",
   190  		[]network.Port{{"tcp", 80}, {"tcp", 81}, {"tcp", 82}, {"tcp", 83}},
   191  		[]network.PortRange{{80, 83, "tcp"}},
   192  	}, {
   193  		"continuous port range (decreasing)",
   194  		[]network.Port{{"tcp", 83}, {"tcp", 82}, {"tcp", 81}, {"tcp", 80}},
   195  		[]network.PortRange{{80, 83, "tcp"}},
   196  	}, {
   197  		"non-continuous port range (increasing)",
   198  		[]network.Port{{"tcp", 80}, {"tcp", 81}, {"tcp", 82}, {"tcp", 84}, {"tcp", 85}},
   199  		[]network.PortRange{{80, 82, "tcp"}, {84, 85, "tcp"}},
   200  	}, {
   201  		"non-continuous port range (decreasing)",
   202  		[]network.Port{{"tcp", 85}, {"tcp", 84}, {"tcp", 82}, {"tcp", 81}, {"tcp", 80}},
   203  		[]network.PortRange{{80, 82, "tcp"}, {84, 85, "tcp"}},
   204  	}, {
   205  		"alternating tcp / udp ports (increasing)",
   206  		[]network.Port{{"tcp", 80}, {"udp", 81}, {"tcp", 82}, {"udp", 83}, {"tcp", 84}},
   207  		[]network.PortRange{{80, 80, "tcp"}, {82, 82, "tcp"}, {84, 84, "tcp"}, {81, 81, "udp"}, {83, 83, "udp"}},
   208  	}, {
   209  		"alternating tcp / udp ports (decreasing)",
   210  		[]network.Port{{"tcp", 84}, {"udp", 83}, {"tcp", 82}, {"udp", 81}, {"tcp", 80}},
   211  		[]network.PortRange{{80, 80, "tcp"}, {82, 82, "tcp"}, {84, 84, "tcp"}, {81, 81, "udp"}, {83, 83, "udp"}},
   212  	}, {
   213  		"non-continuous port range (udp vs tcp - increasing)",
   214  		[]network.Port{{"tcp", 80}, {"tcp", 81}, {"tcp", 82}, {"udp", 84}, {"tcp", 83}},
   215  		[]network.PortRange{{80, 83, "tcp"}, {84, 84, "udp"}},
   216  	}, {
   217  		"non-continuous port range (udp vs tcp - decreasing)",
   218  		[]network.Port{{"tcp", 83}, {"udp", 84}, {"tcp", 82}, {"tcp", 81}, {"tcp", 80}},
   219  		[]network.PortRange{{80, 83, "tcp"}, {84, 84, "udp"}},
   220  	}}
   221  	for i, t := range testCases {
   222  		c.Logf("test %d: %s", i, t.about)
   223  		c.Check(network.CollapsePorts(t.ports), jc.DeepEquals, t.expected)
   224  	}
   225  }
   226  
   227  func (*PortRangeSuite) TestParsePortRange(c *gc.C) {
   228  	portRange, err := network.ParsePortRange("8000-8099/tcp")
   229  	c.Assert(err, jc.ErrorIsNil)
   230  
   231  	c.Check(portRange.Protocol, gc.Equals, "tcp")
   232  	c.Check(portRange.FromPort, gc.Equals, 8000)
   233  	c.Check(portRange.ToPort, gc.Equals, 8099)
   234  }
   235  
   236  func (*PortRangeSuite) TestParsePortRangeSingle(c *gc.C) {
   237  	portRange, err := network.ParsePortRange("80/tcp")
   238  	c.Assert(err, jc.ErrorIsNil)
   239  
   240  	c.Check(portRange.Protocol, gc.Equals, "tcp")
   241  	c.Check(portRange.FromPort, gc.Equals, 80)
   242  	c.Check(portRange.ToPort, gc.Equals, 80)
   243  }
   244  
   245  func (*PortRangeSuite) TestParsePortRangeDefaultProtocol(c *gc.C) {
   246  	portRange, err := network.ParsePortRange("80")
   247  	c.Assert(err, jc.ErrorIsNil)
   248  
   249  	c.Check(portRange.Protocol, gc.Equals, "tcp")
   250  	c.Check(portRange.FromPort, gc.Equals, 80)
   251  	c.Check(portRange.ToPort, gc.Equals, 80)
   252  }
   253  
   254  func (*PortRangeSuite) TestParseIcmpProtocol(c *gc.C) {
   255  	portRange, err := network.ParsePortRange("icmp")
   256  	c.Assert(err, jc.ErrorIsNil)
   257  
   258  	c.Check(portRange.Protocol, gc.Equals, "icmp")
   259  	c.Check(portRange.FromPort, gc.Equals, -1)
   260  	c.Check(portRange.ToPort, gc.Equals, -1)
   261  }
   262  
   263  func (*PortRangeSuite) TestParseIcmpProtocolRoundTrip(c *gc.C) {
   264  	portRange, err := network.ParsePortRange("icmp")
   265  	c.Assert(err, jc.ErrorIsNil)
   266  	portRangeStr := portRange.String()
   267  
   268  	c.Check(portRangeStr, gc.Equals, "icmp")
   269  }
   270  
   271  func (*PortRangeSuite) TestParsePortRangeRoundTrip(c *gc.C) {
   272  	portRange, err := network.ParsePortRange("8000-8099/tcp")
   273  	c.Assert(err, jc.ErrorIsNil)
   274  	portRangeStr := portRange.String()
   275  
   276  	c.Check(portRangeStr, gc.Equals, "8000-8099/tcp")
   277  }
   278  
   279  func (*PortRangeSuite) TestParsePortRangeMultiRange(c *gc.C) {
   280  	_, err := network.ParsePortRange("10-55-100")
   281  
   282  	c.Check(err, gc.ErrorMatches, `invalid port range "10-55-100".*`)
   283  }
   284  
   285  func (*PortRangeSuite) TestParsePortRangeNonIntPort(c *gc.C) {
   286  	_, err := network.ParsePortRange("spam-100")
   287  
   288  	c.Check(err, gc.ErrorMatches, `invalid port "spam".*`)
   289  }
   290  
   291  func (*PortRangeSuite) TestMustParsePortRange(c *gc.C) {
   292  	portRange := network.MustParsePortRange("8000-8099/tcp")
   293  
   294  	c.Check(portRange.Protocol, gc.Equals, "tcp")
   295  	c.Check(portRange.FromPort, gc.Equals, 8000)
   296  	c.Check(portRange.ToPort, gc.Equals, 8099)
   297  }
   298  
   299  func (*PortRangeSuite) TestMustParsePortRangeInvalid(c *gc.C) {
   300  	f := func() {
   301  		network.MustParsePortRange("10-55-100")
   302  	}
   303  
   304  	c.Check(f, gc.PanicMatches, `invalid port range "10-55-100".*`)
   305  }
   306  
   307  func (*PortRangeSuite) TestCombinePortRanges(c *gc.C) {
   308  	testCases := []struct {
   309  		in       []network.PortRange
   310  		expected []network.PortRange
   311  	}{{
   312  		[]network.PortRange{{80, 80, "tcp"}},
   313  		[]network.PortRange{{80, 80, "tcp"}},
   314  	}, {
   315  		[]network.PortRange{{80, 82, "tcp"}, {83, 85, "tcp"}},
   316  		[]network.PortRange{{80, 85, "tcp"}},
   317  	}, {
   318  		[]network.PortRange{{83, 85, "tcp"}, {80, 82, "tcp"}},
   319  		[]network.PortRange{{80, 85, "tcp"}},
   320  	}, {
   321  		[]network.PortRange{{80, 83, "tcp"}, {85, 87, "tcp"}},
   322  		[]network.PortRange{{80, 83, "tcp"}, {85, 87, "tcp"}},
   323  	}, {
   324  		[]network.PortRange{{85, 87, "tcp"}, {80, 83, "tcp"}},
   325  		[]network.PortRange{{80, 83, "tcp"}, {85, 87, "tcp"}},
   326  	}, {
   327  		[]network.PortRange{{85, 87, "tcp"}, {80, 83, "tcp"}},
   328  		[]network.PortRange{{80, 83, "tcp"}, {85, 87, "tcp"}},
   329  	}, {
   330  		[]network.PortRange{{80, 83, "tcp"}, {84, 87, "udp"}},
   331  		[]network.PortRange{{80, 83, "tcp"}, {84, 87, "udp"}},
   332  	}, {
   333  		[]network.PortRange{{80, 82, "tcp"}, {80, 80, "udp"}, {83, 83, "tcp"}, {81, 84, "udp"}, {84, 85, "tcp"}},
   334  		[]network.PortRange{{80, 85, "tcp"}, {80, 84, "udp"}},
   335  	}, {
   336  		[]network.PortRange{{80, 82, "tcp"}, {81, 84, "udp"}, {84, 84, "tcp"}, {86, 87, "udp"}, {80, 80, "udp"}},
   337  		[]network.PortRange{{80, 82, "tcp"}, {84, 84, "tcp"}, {80, 84, "udp"}, {86, 87, "udp"}},
   338  	}}
   339  	for i, t := range testCases {
   340  		c.Logf("test %d", i)
   341  		c.Check(network.CombinePortRanges(t.in...), jc.DeepEquals, t.expected)
   342  	}
   343  }