github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/ClientLibrary/clientlib/clientlib_test.go (about)

     1  /*
     2   * Copyright (c) 2018, 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 clientlib
    21  
    22  import (
    23  	"context"
    24  	"encoding/json"
    25  	"io/ioutil"
    26  	"os"
    27  	"testing"
    28  	"time"
    29  )
    30  
    31  func TestStartTunnel(t *testing.T) {
    32  	// TODO: More comprehensive tests. This is only a smoke test.
    33  
    34  	clientPlatform := "clientlib_test.go"
    35  	networkID := "UNKNOWN"
    36  	timeout := 60
    37  	quickTimeout := 1
    38  
    39  	configJSON, err := ioutil.ReadFile("../../psiphon/controller_test.config")
    40  	if err != nil {
    41  		// Skip, don't fail, if config file is not present
    42  		t.Skipf("error loading configuration file: %s", err)
    43  	}
    44  
    45  	// Initialize a fresh datastore and create a modified config which cannot
    46  	// connect without known servers, to be used in timeout cases.
    47  
    48  	testDataDirName, err := ioutil.TempDir("", "psiphon-clientlib-test")
    49  	if err != nil {
    50  		t.Fatalf("ioutil.TempDir failed: %v", err)
    51  	}
    52  	defer os.RemoveAll(testDataDirName)
    53  
    54  	var config map[string]interface{}
    55  	err = json.Unmarshal(configJSON, &config)
    56  	if err != nil {
    57  		t.Fatalf("json.Unmarshal failed: %v", err)
    58  	}
    59  	config["DisableRemoteServerListFetcher"] = true
    60  	configJSONNoFetcher, err := json.Marshal(config)
    61  	if err != nil {
    62  		t.Fatalf("json.Marshal failed: %v", err)
    63  	}
    64  
    65  	type args struct {
    66  		ctxTimeout              time.Duration
    67  		configJSON              []byte
    68  		embeddedServerEntryList string
    69  		params                  Parameters
    70  		paramsDelta             ParametersDelta
    71  		noticeReceiver          func(NoticeEvent)
    72  	}
    73  	tests := []struct {
    74  		name        string
    75  		args        args
    76  		wantTunnel  bool
    77  		expectedErr error
    78  	}{
    79  		{
    80  			name: "Failure: context timeout",
    81  			args: args{
    82  				ctxTimeout:              10 * time.Millisecond,
    83  				configJSON:              configJSONNoFetcher,
    84  				embeddedServerEntryList: "",
    85  				params: Parameters{
    86  					DataRootDirectory:             &testDataDirName,
    87  					ClientPlatform:                &clientPlatform,
    88  					NetworkID:                     &networkID,
    89  					EstablishTunnelTimeoutSeconds: &timeout,
    90  				},
    91  				paramsDelta:    nil,
    92  				noticeReceiver: nil,
    93  			},
    94  			wantTunnel:  false,
    95  			expectedErr: ErrTimeout,
    96  		},
    97  		{
    98  			name: "Failure: config timeout",
    99  			args: args{
   100  				ctxTimeout:              0,
   101  				configJSON:              configJSONNoFetcher,
   102  				embeddedServerEntryList: "",
   103  				params: Parameters{
   104  					DataRootDirectory:             &testDataDirName,
   105  					ClientPlatform:                &clientPlatform,
   106  					NetworkID:                     &networkID,
   107  					EstablishTunnelTimeoutSeconds: &quickTimeout,
   108  				},
   109  				paramsDelta:    nil,
   110  				noticeReceiver: nil,
   111  			},
   112  			wantTunnel:  false,
   113  			expectedErr: ErrTimeout,
   114  		},
   115  		{
   116  			name: "Success: simple",
   117  			args: args{
   118  				ctxTimeout:              0,
   119  				configJSON:              configJSON,
   120  				embeddedServerEntryList: "",
   121  				params: Parameters{
   122  					DataRootDirectory:             &testDataDirName,
   123  					ClientPlatform:                &clientPlatform,
   124  					NetworkID:                     &networkID,
   125  					EstablishTunnelTimeoutSeconds: &timeout,
   126  				},
   127  				paramsDelta:    nil,
   128  				noticeReceiver: nil,
   129  			},
   130  			wantTunnel:  true,
   131  			expectedErr: nil,
   132  		},
   133  	}
   134  	for _, tt := range tests {
   135  		t.Run(tt.name, func(t *testing.T) {
   136  
   137  			ctx := context.Background()
   138  			var cancelFunc context.CancelFunc
   139  			if tt.args.ctxTimeout > 0 {
   140  				ctx, cancelFunc = context.WithTimeout(ctx, tt.args.ctxTimeout)
   141  			}
   142  
   143  			tunnel, err := StartTunnel(
   144  				ctx,
   145  				tt.args.configJSON,
   146  				tt.args.embeddedServerEntryList,
   147  				tt.args.params,
   148  				tt.args.paramsDelta,
   149  				tt.args.noticeReceiver)
   150  
   151  			gotTunnel := (tunnel != nil)
   152  
   153  			if cancelFunc != nil {
   154  				cancelFunc()
   155  			}
   156  
   157  			if tunnel != nil {
   158  				tunnel.Stop()
   159  			}
   160  
   161  			if gotTunnel != tt.wantTunnel {
   162  				t.Errorf("StartTunnel() gotTunnel = %v, wantTunnel %v", err, tt.wantTunnel)
   163  			}
   164  
   165  			if err != tt.expectedErr {
   166  				t.Fatalf("StartTunnel() error = %v, expectedErr %v", err, tt.expectedErr)
   167  				return
   168  			}
   169  
   170  		})
   171  	}
   172  }