github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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/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 } 97 98 func (*PortRangeSuite) TestValidate(c *gc.C) { 99 testCases := []struct { 100 about string 101 ports network.PortRange 102 expected string 103 }{{ 104 "single valid port", 105 network.PortRange{80, 80, "tcp"}, 106 "", 107 }, { 108 "valid port range", 109 network.PortRange{80, 90, "tcp"}, 110 "", 111 }, { 112 "valid udp port range", 113 network.PortRange{80, 90, "UDP"}, 114 "", 115 }, { 116 "invalid port range boundaries", 117 network.PortRange{90, 80, "tcp"}, 118 "invalid port range 90-80/tcp", 119 }, { 120 "both FromPort and ToPort too large", 121 network.PortRange{88888, 99999, "tcp"}, 122 "invalid port range 88888-99999/tcp", 123 }, { 124 "FromPort too large", 125 network.PortRange{88888, 65535, "tcp"}, 126 "invalid port range 88888-65535/tcp", 127 }, { 128 "FromPort too small", 129 network.PortRange{0, 80, "tcp"}, 130 "invalid port range 0-80/tcp", 131 }, { 132 "ToPort too large", 133 network.PortRange{1, 99999, "tcp"}, 134 "invalid port range 1-99999/tcp", 135 }, { 136 "both ports 0", 137 network.PortRange{0, 0, "tcp"}, 138 "invalid port range 0-0/tcp", 139 }, { 140 "invalid protocol", 141 network.PortRange{80, 80, "some protocol"}, 142 `invalid protocol "some protocol", expected "tcp" or "udp"`, 143 }} 144 145 for i, t := range testCases { 146 c.Logf("test %d: %s", i, t.about) 147 if t.expected == "" { 148 c.Check(t.ports.Validate(), gc.IsNil) 149 } else { 150 c.Check(t.ports.Validate(), gc.ErrorMatches, t.expected) 151 } 152 } 153 } 154 155 func (*PortRangeSuite) TestSortPortRanges(c *gc.C) { 156 ranges := []network.PortRange{ 157 {10, 100, "udp"}, 158 {80, 90, "tcp"}, 159 {80, 80, "tcp"}, 160 } 161 expected := []network.PortRange{ 162 {80, 80, "tcp"}, 163 {80, 90, "tcp"}, 164 {10, 100, "udp"}, 165 } 166 network.SortPortRanges(ranges) 167 c.Assert(ranges, gc.DeepEquals, expected) 168 } 169 170 func (*PortRangeSuite) TestCollapsePorts(c *gc.C) { 171 testCases := []struct { 172 about string 173 ports []network.Port 174 expected []network.PortRange 175 }{{ 176 "single port", 177 []network.Port{{"tcp", 80}}, 178 []network.PortRange{{80, 80, "tcp"}}, 179 }, { 180 "continuous port range (increasing)", 181 []network.Port{{"tcp", 80}, {"tcp", 81}, {"tcp", 82}, {"tcp", 83}}, 182 []network.PortRange{{80, 83, "tcp"}}, 183 }, { 184 "continuous port range (decreasing)", 185 []network.Port{{"tcp", 83}, {"tcp", 82}, {"tcp", 81}, {"tcp", 80}}, 186 []network.PortRange{{80, 83, "tcp"}}, 187 }, { 188 "non-continuous port range (increasing)", 189 []network.Port{{"tcp", 80}, {"tcp", 81}, {"tcp", 82}, {"tcp", 84}, {"tcp", 85}}, 190 []network.PortRange{{80, 82, "tcp"}, {84, 85, "tcp"}}, 191 }, { 192 "non-continuous port range (decreasing)", 193 []network.Port{{"tcp", 85}, {"tcp", 84}, {"tcp", 82}, {"tcp", 81}, {"tcp", 80}}, 194 []network.PortRange{{80, 82, "tcp"}, {84, 85, "tcp"}}, 195 }, { 196 "alternating tcp / udp ports (increasing)", 197 []network.Port{{"tcp", 80}, {"udp", 81}, {"tcp", 82}, {"udp", 83}, {"tcp", 84}}, 198 []network.PortRange{{80, 80, "tcp"}, {82, 82, "tcp"}, {84, 84, "tcp"}, {81, 81, "udp"}, {83, 83, "udp"}}, 199 }, { 200 "alternating tcp / udp ports (decreasing)", 201 []network.Port{{"tcp", 84}, {"udp", 83}, {"tcp", 82}, {"udp", 81}, {"tcp", 80}}, 202 []network.PortRange{{80, 80, "tcp"}, {82, 82, "tcp"}, {84, 84, "tcp"}, {81, 81, "udp"}, {83, 83, "udp"}}, 203 }, { 204 "non-continuous port range (udp vs tcp - increasing)", 205 []network.Port{{"tcp", 80}, {"tcp", 81}, {"tcp", 82}, {"udp", 84}, {"tcp", 83}}, 206 []network.PortRange{{80, 83, "tcp"}, {84, 84, "udp"}}, 207 }, { 208 "non-continuous port range (udp vs tcp - decreasing)", 209 []network.Port{{"tcp", 83}, {"udp", 84}, {"tcp", 82}, {"tcp", 81}, {"tcp", 80}}, 210 []network.PortRange{{80, 83, "tcp"}, {84, 84, "udp"}}, 211 }} 212 for i, t := range testCases { 213 c.Logf("test %d: %s", i, t.about) 214 c.Check(network.CollapsePorts(t.ports), jc.DeepEquals, t.expected) 215 } 216 } 217 218 func (*PortRangeSuite) TestParsePortRange(c *gc.C) { 219 portRange, err := network.ParsePortRange("8000-8099/tcp") 220 c.Assert(err, jc.ErrorIsNil) 221 222 c.Check(portRange.Protocol, gc.Equals, "tcp") 223 c.Check(portRange.FromPort, gc.Equals, 8000) 224 c.Check(portRange.ToPort, gc.Equals, 8099) 225 } 226 227 func (*PortRangeSuite) TestParsePortRangeSingle(c *gc.C) { 228 portRange, err := network.ParsePortRange("80/tcp") 229 c.Assert(err, jc.ErrorIsNil) 230 231 c.Check(portRange.Protocol, gc.Equals, "tcp") 232 c.Check(portRange.FromPort, gc.Equals, 80) 233 c.Check(portRange.ToPort, gc.Equals, 80) 234 } 235 236 func (*PortRangeSuite) TestParsePortRangeDefaultProtocol(c *gc.C) { 237 portRange, err := network.ParsePortRange("80") 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) TestParsePortRangeRoundTrip(c *gc.C) { 246 portRange, err := network.ParsePortRange("8000-8099/tcp") 247 c.Assert(err, jc.ErrorIsNil) 248 portRangeStr := portRange.String() 249 250 c.Check(portRangeStr, gc.Equals, "8000-8099/tcp") 251 } 252 253 func (*PortRangeSuite) TestParsePortRangeMultiRange(c *gc.C) { 254 _, err := network.ParsePortRange("10-55-100") 255 256 c.Check(err, gc.ErrorMatches, `invalid port range "10-55-100".*`) 257 } 258 259 func (*PortRangeSuite) TestParsePortRangeNonIntPort(c *gc.C) { 260 _, err := network.ParsePortRange("spam-100") 261 262 c.Check(err, gc.ErrorMatches, `invalid port "spam".*`) 263 } 264 265 func (*PortRangeSuite) TestMustParsePortRange(c *gc.C) { 266 portRange := network.MustParsePortRange("8000-8099/tcp") 267 268 c.Check(portRange.Protocol, gc.Equals, "tcp") 269 c.Check(portRange.FromPort, gc.Equals, 8000) 270 c.Check(portRange.ToPort, gc.Equals, 8099) 271 } 272 273 func (*PortRangeSuite) TestMustParsePortRangeInvalid(c *gc.C) { 274 f := func() { 275 network.MustParsePortRange("10-55-100") 276 } 277 278 c.Check(f, gc.PanicMatches, `invalid port range "10-55-100".*`) 279 } 280 281 func (*PortRangeSuite) TestParsePortRanges(c *gc.C) { 282 portRanges, err := network.ParsePortRanges("80/tcp,8000-8099/tcp") 283 c.Assert(err, jc.ErrorIsNil) 284 285 c.Assert(portRanges, gc.HasLen, 2) 286 c.Check(portRanges[0].Protocol, gc.Equals, "tcp") 287 c.Check(portRanges[0].FromPort, gc.Equals, 80) 288 c.Check(portRanges[0].ToPort, gc.Equals, 80) 289 c.Check(portRanges[1].Protocol, gc.Equals, "tcp") 290 c.Check(portRanges[1].FromPort, gc.Equals, 8000) 291 c.Check(portRanges[1].ToPort, gc.Equals, 8099) 292 } 293 294 func (*PortRangeSuite) TestParsePortRangesSingle(c *gc.C) { 295 portRanges, err := network.ParsePortRanges("80") 296 c.Assert(err, jc.ErrorIsNil) 297 298 c.Assert(portRanges, gc.HasLen, 1) 299 c.Check(portRanges[0].Protocol, gc.Equals, "tcp") 300 c.Check(portRanges[0].FromPort, gc.Equals, 80) 301 c.Check(portRanges[0].ToPort, gc.Equals, 80) 302 } 303 304 func (*PortRangeSuite) TestParsePortRangesSpaces(c *gc.C) { 305 portRanges, err := network.ParsePortRanges(" 80, 8000-8099 ") 306 c.Assert(err, jc.ErrorIsNil) 307 308 c.Assert(portRanges, gc.HasLen, 2) 309 c.Check(portRanges[0].Protocol, gc.Equals, "tcp") 310 c.Check(portRanges[0].FromPort, gc.Equals, 80) 311 c.Check(portRanges[0].ToPort, gc.Equals, 80) 312 c.Check(portRanges[1].Protocol, gc.Equals, "tcp") 313 c.Check(portRanges[1].FromPort, gc.Equals, 8000) 314 c.Check(portRanges[1].ToPort, gc.Equals, 8099) 315 }