github.com/database64128/shadowsocks-go@v1.10.2-0.20240315062903-143a773533f1/portset/portset_test.go (about) 1 package portset 2 3 import ( 4 "slices" 5 "strconv" 6 "testing" 7 ) 8 9 func assertPanic(t *testing.T, f func()) { 10 t.Helper() 11 defer func() { 12 if r := recover(); r == nil { 13 t.Error("expected panic, got none") 14 } 15 }() 16 f() 17 } 18 19 func TestPortSetBadPort(t *testing.T) { 20 var s PortSet 21 assertPanic(t, func() { s.Contains(0) }) 22 assertPanic(t, func() { s.Add(0) }) 23 assertPanic(t, func() { s.AddRange(0, 1) }) 24 assertPanic(t, func() { s.AddRange(1, 0) }) 25 assertPanic(t, func() { s.AddRange(1, 1) }) 26 } 27 28 func assertPortSetFirst(t *testing.T, s *PortSet, from uint16) { 29 t.Helper() 30 if first := s.First(); first != from { 31 t.Errorf("expected first to be %d, got %d", from, first) 32 } 33 } 34 35 func TestPortSetEmptyFirst(t *testing.T) { 36 var s PortSet 37 assertPortSetFirst(t, &s, 0) 38 } 39 40 func assertPortSetCount(t *testing.T, s *PortSet, from, to uint16) { 41 t.Helper() 42 if count, expectedCount := s.Count(), uint(to-from)+1; count != expectedCount { 43 t.Errorf("expected count to be %d, got %d", expectedCount, count) 44 } 45 } 46 47 func assertPortSetSingleRange(t *testing.T, s *PortSet, from, to uint16) { 48 t.Helper() 49 if r := s.RangeSet(); len(r.ranges) != 1 || r.ranges[0].From != from || r.ranges[0].To != to { 50 t.Errorf("expected single range %d-%d, got %v", from, to, r) 51 } 52 } 53 54 func assertPortSetContainsSingleRange(t *testing.T, s *PortSet, from, to uint16) { 55 t.Helper() 56 for i := uint(1); i < uint(from); i++ { 57 if s.Contains(uint16(i)) { 58 t.Errorf("contains unexpected port %d", i) 59 } 60 } 61 for i := uint(from); i <= uint(to); i++ { 62 if !s.Contains(uint16(i)) { 63 t.Errorf("expected port %d to be in set", i) 64 } 65 } 66 for i := uint(to) + 1; i < 65536; i++ { 67 if s.Contains(uint16(i)) { 68 t.Errorf("contains unexpected port %d", i) 69 } 70 } 71 } 72 73 func portSetAddRange(s *PortSet, from, to uint16) { 74 for i := uint(from); i <= uint(to); i++ { 75 s.Add(uint16(i)) 76 } 77 } 78 79 func testPortSetSingleRange(t *testing.T, from, to uint16) { 80 var s0, s1 PortSet 81 82 s0.AddRange(from, to) 83 assertPortSetFirst(t, &s0, from) 84 assertPortSetCount(t, &s0, from, to) 85 assertPortSetSingleRange(t, &s0, from, to) 86 assertPortSetContainsSingleRange(t, &s0, from, to) 87 88 portSetAddRange(&s1, from, to) 89 if s0 != s1 { 90 t.Error("expected AddRange to be equivalent to consecutive Add calls") 91 } 92 } 93 94 func TestPortSetSingleRange(t *testing.T) { 95 testRanges := [...]uint16{1, 2, 62, 63, 64, 65, 126, 127, 128, 129, 254, 255, 256, 257, 65534, 65535} 96 for _, from := range testRanges { 97 for _, to := range testRanges { 98 if from >= to { 99 continue 100 } 101 t.Run(strconv.FormatUint(uint64(from), 10)+"-"+strconv.FormatUint(uint64(to), 10), func(t *testing.T) { 102 testPortSetSingleRange(t, from, to) 103 }) 104 } 105 } 106 } 107 108 func testPortSetMultipleRanges(t *testing.T, portRangeSet PortRangeSet) { 109 var portSet PortSet 110 for _, r := range portRangeSet.ranges { 111 portSet.AddRange(r.From, r.To) 112 } 113 114 for i := uint(1); i < 65536; i++ { 115 portSetContains := portSet.Contains(uint16(i)) 116 portRangeSetContains := portRangeSet.Contains(uint16(i)) 117 if portSetContains != portRangeSetContains { 118 t.Errorf("mismatched results for port %d: portSet says %t, portRangeSet says %t", i, portSetContains, portRangeSetContains) 119 } 120 } 121 122 if portSetRangeCount := portSet.RangeCount(); portSetRangeCount != uint(len(portRangeSet.ranges)) { 123 t.Errorf("expected range count to be %d, got %d", len(portRangeSet.ranges), portSetRangeCount) 124 } 125 126 if portSetRangeSet := portSet.RangeSet(); !slices.Equal(portSetRangeSet.ranges, portRangeSet.ranges) { 127 t.Errorf("expected ranges to be %v, got %v", portRangeSet.ranges, portSetRangeSet.ranges) 128 } 129 } 130 131 func TestPortSetMultipleRanges(t *testing.T) { 132 testPortRangeSets := [...]PortRangeSet{ 133 {}, 134 {ranges: []PortRange{{From: 62, To: 63}}}, 135 {ranges: []PortRange{{From: 62, To: 64}}}, 136 {ranges: []PortRange{{From: 62, To: 65}}}, 137 {ranges: []PortRange{{From: 62, To: 126}}}, 138 {ranges: []PortRange{{From: 62, To: 127}}}, 139 {ranges: []PortRange{{From: 62, To: 128}}}, 140 {ranges: []PortRange{{From: 62, To: 129}}}, 141 {ranges: []PortRange{{From: 62, To: 254}}}, 142 {ranges: []PortRange{{From: 62, To: 255}}}, 143 {ranges: []PortRange{{From: 62, To: 256}}}, 144 {ranges: []PortRange{{From: 62, To: 257}}}, 145 {ranges: []PortRange{{From: 62, To: 63}, {From: 126, To: 127}}}, 146 {ranges: []PortRange{{From: 62, To: 64}, {From: 126, To: 128}}}, 147 {ranges: []PortRange{{From: 62, To: 65}, {From: 126, To: 129}}}, 148 {ranges: []PortRange{{From: 62, To: 63}, {From: 126, To: 127}, {From: 254, To: 255}}}, 149 {ranges: []PortRange{{From: 62, To: 64}, {From: 126, To: 128}, {From: 254, To: 256}}}, 150 {ranges: []PortRange{{From: 62, To: 65}, {From: 126, To: 129}, {From: 254, To: 257}}}, 151 } 152 for i, portRangeSet := range testPortRangeSets { 153 t.Run(strconv.Itoa(i), func(t *testing.T) { 154 testPortSetMultipleRanges(t, portRangeSet) 155 }) 156 } 157 } 158 159 func testPortSetParse(t *testing.T, portSetString string, expectedNoError bool, expectedRanges []PortRange) { 160 var portSet PortSet 161 if err := portSet.Parse(portSetString); (err == nil) != expectedNoError { 162 t.Errorf("unexpected error: %v", err) 163 } 164 if rangeSet := portSet.RangeSet(); !slices.Equal(rangeSet.ranges, expectedRanges) { 165 t.Errorf("expected ranges to be %v, got %v", expectedRanges, rangeSet.ranges) 166 } 167 } 168 169 func TestPortSetParse(t *testing.T) { 170 testData := []struct { 171 portSetString string 172 expectedNoError bool 173 expectedRanges []PortRange 174 }{ 175 {"", true, []PortRange{}}, 176 {"1", true, []PortRange{{From: 1, To: 1}}}, 177 {"1,", true, []PortRange{{From: 1, To: 1}}}, 178 {"1,1", true, []PortRange{{From: 1, To: 1}}}, 179 {"1,2", true, []PortRange{{From: 1, To: 2}}}, 180 {"1-2", true, []PortRange{{From: 1, To: 2}}}, 181 {"1-2,3", true, []PortRange{{From: 1, To: 3}}}, 182 {"1-2,3-4", true, []PortRange{{From: 1, To: 4}}}, 183 {"1-4,2,3", true, []PortRange{{From: 1, To: 4}}}, 184 {"1-4,2-3", true, []PortRange{{From: 1, To: 4}}}, 185 {"1,2,4,5", true, []PortRange{{From: 1, To: 2}, {From: 4, To: 5}}}, 186 {"1-2,4-5", true, []PortRange{{From: 1, To: 2}, {From: 4, To: 5}}}, 187 {"1-65535", true, []PortRange{{From: 1, To: 65535}}}, 188 {"0", false, []PortRange{}}, 189 {"0,1", false, []PortRange{}}, 190 {"0-1", false, []PortRange{}}, 191 {"1-0", false, []PortRange{}}, 192 {"2-1", false, []PortRange{}}, 193 {"1-65536", false, []PortRange{}}, 194 {"1-65535,65536", false, []PortRange{{From: 1, To: 65535}}}, 195 {"abc", false, []PortRange{}}, 196 {"1-abc", false, []PortRange{}}, 197 {"abc-1", false, []PortRange{}}, 198 {",", false, []PortRange{}}, 199 {"-", false, []PortRange{}}, 200 {",1", false, []PortRange{}}, 201 {"-1", false, []PortRange{}}, 202 {"1-", false, []PortRange{}}, 203 {"1-,", false, []PortRange{}}, 204 {"1,-", false, []PortRange{{From: 1, To: 1}}}, 205 {",-1", false, []PortRange{}}, 206 {"-,1", false, []PortRange{}}, 207 } 208 for i, data := range testData { 209 t.Run(strconv.Itoa(i), func(t *testing.T) { 210 testPortSetParse(t, data.portSetString, data.expectedNoError, data.expectedRanges) 211 }) 212 } 213 }