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 }