github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/net_test.go (about)

     1  /*
     2   * Copyright (c) 2016, 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  	"net"
    24  	"sync/atomic"
    25  	"testing"
    26  	"testing/iotest"
    27  	"time"
    28  
    29  	"github.com/miekg/dns"
    30  )
    31  
    32  func TestLRUConns(t *testing.T) {
    33  	lruConns := NewLRUConns()
    34  
    35  	dummy1 := &dummyConn{}
    36  	entry1 := lruConns.Add(dummy1)
    37  
    38  	dummy2 := &dummyConn{}
    39  	entry2 := lruConns.Add(dummy2)
    40  
    41  	dummy3 := &dummyConn{}
    42  	entry3 := lruConns.Add(dummy3)
    43  
    44  	entry3.Touch()
    45  	entry2.Touch()
    46  	entry1.Touch()
    47  
    48  	if dummy1.IsClosed() || dummy2.IsClosed() || dummy3.IsClosed() {
    49  		t.Fatalf("unexpected IsClosed state")
    50  	}
    51  
    52  	lruConns.CloseOldest()
    53  
    54  	if dummy1.IsClosed() || dummy2.IsClosed() || !dummy3.IsClosed() {
    55  		t.Fatalf("unexpected IsClosed state")
    56  	}
    57  
    58  	lruConns.CloseOldest()
    59  
    60  	if dummy1.IsClosed() || !dummy2.IsClosed() || !dummy3.IsClosed() {
    61  		t.Fatalf("unexpected IsClosed state")
    62  	}
    63  
    64  	entry1.Remove()
    65  
    66  	lruConns.CloseOldest()
    67  
    68  	if dummy1.IsClosed() || !dummy2.IsClosed() || !dummy3.IsClosed() {
    69  		t.Fatalf("unexpected IsClosed state")
    70  	}
    71  }
    72  
    73  func TestIsBogon(t *testing.T) {
    74  	if IsBogon(net.ParseIP("8.8.8.8")) {
    75  		t.Errorf("unexpected bogon")
    76  	}
    77  	if !IsBogon(net.ParseIP("127.0.0.1")) {
    78  		t.Errorf("unexpected non-bogon")
    79  	}
    80  	if !IsBogon(net.ParseIP("192.168.0.1")) {
    81  		t.Errorf("unexpected non-bogon")
    82  	}
    83  	if !IsBogon(net.ParseIP("::1")) {
    84  		t.Errorf("unexpected non-bogon")
    85  	}
    86  	if !IsBogon(net.ParseIP("fc00::")) {
    87  		t.Errorf("unexpected non-bogon")
    88  	}
    89  }
    90  
    91  func BenchmarkIsBogon(b *testing.B) {
    92  	for i := 0; i < b.N; i++ {
    93  		IsBogon(net.ParseIP("8.8.8.8"))
    94  	}
    95  }
    96  
    97  func makeDNSQuery(domain string) ([]byte, error) {
    98  	query := new(dns.Msg)
    99  	query.SetQuestion(domain, dns.TypeA)
   100  	query.RecursionDesired = true
   101  	msg, err := query.Pack()
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	return msg, nil
   106  }
   107  
   108  func TestParseDNSQuestion(t *testing.T) {
   109  
   110  	domain := dns.Fqdn("www.example.com")
   111  	msg, err := makeDNSQuery(domain)
   112  	if err != nil {
   113  		t.Fatalf("makeDNSQuery failed: %s", err)
   114  	}
   115  
   116  	checkDomain, err := ParseDNSQuestion(msg)
   117  	if err != nil {
   118  		t.Fatalf("ParseDNSQuestion failed: %s", err)
   119  	}
   120  
   121  	if checkDomain != domain {
   122  		t.Fatalf("unexpected domain")
   123  	}
   124  }
   125  
   126  func BenchmarkParseDNSQuestion(b *testing.B) {
   127  
   128  	domain := dns.Fqdn("www.example.com")
   129  	msg, err := makeDNSQuery(domain)
   130  	if err != nil {
   131  		b.Fatalf("makeDNSQuery failed: %s", err)
   132  	}
   133  
   134  	for i := 0; i < b.N; i++ {
   135  		ParseDNSQuestion(msg)
   136  	}
   137  }
   138  
   139  type dummyConn struct {
   140  	t                   *testing.T
   141  	timeout             *time.Timer
   142  	readBytesPerSecond  int64
   143  	writeBytesPerSecond int64
   144  	isClosed            int32
   145  }
   146  
   147  func (c *dummyConn) Read(b []byte) (n int, err error) {
   148  	if c.readBytesPerSecond > 0 {
   149  		sleep := time.Duration(float64(int64(len(b))*int64(time.Second)) / float64(c.readBytesPerSecond))
   150  		time.Sleep(sleep)
   151  	}
   152  	if c.timeout != nil {
   153  		select {
   154  		case <-c.timeout.C:
   155  			return 0, iotest.ErrTimeout
   156  		default:
   157  		}
   158  	}
   159  	return len(b), nil
   160  }
   161  
   162  func (c *dummyConn) Write(b []byte) (n int, err error) {
   163  	if c.writeBytesPerSecond > 0 {
   164  		sleep := time.Duration(float64(int64(len(b))*int64(time.Second)) / float64(c.writeBytesPerSecond))
   165  		time.Sleep(sleep)
   166  	}
   167  	if c.timeout != nil {
   168  		select {
   169  		case <-c.timeout.C:
   170  			return 0, iotest.ErrTimeout
   171  		default:
   172  		}
   173  	}
   174  	return len(b), nil
   175  }
   176  
   177  func (c *dummyConn) Close() error {
   178  	atomic.StoreInt32(&c.isClosed, 1)
   179  	return nil
   180  }
   181  
   182  func (c *dummyConn) IsClosed() bool {
   183  	return atomic.LoadInt32(&c.isClosed) == 1
   184  }
   185  
   186  func (c *dummyConn) LocalAddr() net.Addr {
   187  	c.t.Fatal("LocalAddr not implemented")
   188  	return nil
   189  }
   190  
   191  func (c *dummyConn) RemoteAddr() net.Addr {
   192  	c.t.Fatal("RemoteAddr not implemented")
   193  	return nil
   194  }
   195  
   196  func (c *dummyConn) SetDeadline(t time.Time) error {
   197  	duration := time.Until(t)
   198  	if c.timeout == nil {
   199  		c.timeout = time.NewTimer(duration)
   200  	} else {
   201  		if !c.timeout.Stop() {
   202  			<-c.timeout.C
   203  		}
   204  		c.timeout.Reset(duration)
   205  	}
   206  	return nil
   207  }
   208  
   209  func (c *dummyConn) SetReadDeadline(t time.Time) error {
   210  	c.t.Fatal("SetReadDeadline not implemented")
   211  	return nil
   212  }
   213  
   214  func (c *dummyConn) SetWriteDeadline(t time.Time) error {
   215  	c.t.Fatal("SetWriteDeadline not implemented")
   216  	return nil
   217  }
   218  
   219  func (c *dummyConn) SetRateLimits(readBytesPerSecond, writeBytesPerSecond int64) {
   220  	c.readBytesPerSecond = readBytesPerSecond
   221  	c.writeBytesPerSecond = writeBytesPerSecond
   222  }