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  }