github.com/Psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/portlist_test.go (about) 1 /* 2 * Copyright (c) 2021, Psiphon Inc. 3 * All rights reserved. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package common 21 22 import ( 23 "encoding/json" 24 "strings" 25 "testing" 26 "unicode" 27 ) 28 29 func TestPortList(t *testing.T) { 30 31 var p *PortList 32 33 err := json.Unmarshal([]byte("[1.5]"), &p) 34 if err == nil { 35 t.Fatalf("unexpected parse of float port number") 36 } 37 38 err = json.Unmarshal([]byte("[-1]"), &p) 39 if err == nil { 40 t.Fatalf("unexpected parse of negative port number") 41 } 42 43 err = json.Unmarshal([]byte("[0]"), &p) 44 if err == nil { 45 t.Fatalf("unexpected parse of invalid port number") 46 } 47 48 err = json.Unmarshal([]byte("[65536]"), &p) 49 if err == nil { 50 t.Fatalf("unexpected parse of invalid port number") 51 } 52 53 err = json.Unmarshal([]byte("[[2,1]]"), &p) 54 if err == nil { 55 t.Fatalf("unexpected parse of invalid port range") 56 } 57 58 p = nil 59 60 if p.Lookup(1) != false { 61 t.Fatalf("unexpected nil PortList Lookup result") 62 } 63 64 if !p.IsEmpty() { 65 t.Fatalf("unexpected nil PortList IsEmpty result") 66 } 67 68 err = json.Unmarshal([]byte("[]"), &p) 69 if err != nil { 70 t.Fatalf("Unmarshal failed: %v", err) 71 } 72 73 if !p.IsEmpty() { 74 t.Fatalf("unexpected IsEmpty result") 75 } 76 77 err = json.Unmarshal([]byte("[1]"), &p) 78 if err != nil { 79 t.Fatalf("Unmarshal failed: %v", err) 80 } 81 82 if p.IsEmpty() { 83 t.Fatalf("unexpected IsEmpty result") 84 } 85 86 s := struct { 87 List1 *PortList 88 List2 *PortList 89 }{} 90 91 jsonString := ` 92 { 93 "List1" : [1,2,[10,20],100,[1000,2000]], 94 "List2" : [3,4,5,[300,400],1000,2000,[3000,3996],3997,3998,3999,4000] 95 } 96 ` 97 98 err = json.Unmarshal([]byte(jsonString), &s) 99 if err != nil { 100 t.Fatalf("Unmarshal failed: %v", err) 101 } 102 103 // Marshal and re-Unmarshal to exercise PortList.MarshalJSON. 104 105 jsonBytes, err := json.Marshal(s) 106 if err != nil { 107 t.Fatalf("Marshal failed: %v", err) 108 } 109 110 strip := func(s string) string { 111 return strings.Map(func(r rune) rune { 112 if unicode.IsSpace(r) { 113 return -1 114 } 115 return r 116 }, s) 117 } 118 119 if strip(jsonString) != strip(string(jsonBytes)) { 120 121 t.Fatalf("unexpected JSON encoding") 122 } 123 124 err = json.Unmarshal(jsonBytes, &s) 125 if err != nil { 126 t.Fatalf("Unmarshal failed: %v", err) 127 } 128 129 s.List1.OptimizeLookups() 130 if s.List1.lookup != nil { 131 t.Fatalf("unexpected lookup initialization") 132 } 133 134 s.List2.OptimizeLookups() 135 if s.List2.lookup == nil { 136 t.Fatalf("unexpected lookup initialization") 137 } 138 139 for port := 0; port < 65536; port++ { 140 141 lookup1 := s.List1.Lookup(port) 142 expected1 := port == 1 || 143 port == 2 || 144 (port >= 10 && port <= 20) || 145 port == 100 || 146 (port >= 1000 && port <= 2000) 147 if lookup1 != expected1 { 148 t.Fatalf("unexpected port lookup: %d %v", port, lookup1) 149 } 150 151 lookup2 := s.List2.Lookup(port) 152 expected2 := port == 3 || 153 port == 4 || 154 port == 5 || 155 (port >= 300 && port <= 400) || 156 port == 1000 || port == 2000 || 157 (port >= 3000 && port <= 4000) 158 if lookup2 != expected2 { 159 t.Fatalf("unexpected port lookup: %d %v", port, lookup2) 160 } 161 } 162 } 163 164 func BenchmarkPortListLinear(b *testing.B) { 165 166 s := struct { 167 List PortList 168 }{} 169 170 jsonStruct := ` 171 { 172 "List" : [1,2,3,4,5,6,7,8,9,[10,20]] 173 } 174 ` 175 176 err := json.Unmarshal([]byte(jsonStruct), &s) 177 if err != nil { 178 b.Fatalf("Unmarshal failed: %v", err) 179 } 180 s.List.OptimizeLookups() 181 if s.List.lookup != nil { 182 b.Fatalf("unexpected lookup initialization") 183 } 184 185 b.ResetTimer() 186 187 for i := 0; i < b.N; i++ { 188 for port := 0; port < 65536; port++ { 189 s.List.Lookup(port) 190 } 191 } 192 } 193 194 func BenchmarkPortListMap(b *testing.B) { 195 196 s := struct { 197 List PortList 198 }{} 199 200 jsonStruct := ` 201 { 202 "List" : [1,2,3,4,5,6,7,8,9,10,[11,20]] 203 } 204 ` 205 206 err := json.Unmarshal([]byte(jsonStruct), &s) 207 if err != nil { 208 b.Fatalf("Unmarshal failed: %v", err) 209 } 210 s.List.OptimizeLookups() 211 if s.List.lookup == nil { 212 b.Fatalf("unexpected lookup initialization") 213 } 214 215 b.ResetTimer() 216 217 for i := 0; i < b.N; i++ { 218 for port := 0; port < 65536; port++ { 219 s.List.Lookup(port) 220 } 221 } 222 }