github.com/NebulousLabs/Sia@v1.3.7/modules/gateway/gateway_test.go (about)

     1  package gateway
     2  
     3  import (
     4  	"io/ioutil"
     5  	"net"
     6  	"os"
     7  	"path/filepath"
     8  	"strconv"
     9  	"sync"
    10  	"testing"
    11  
    12  	"github.com/NebulousLabs/Sia/build"
    13  	"github.com/NebulousLabs/Sia/modules"
    14  	siasync "github.com/NebulousLabs/Sia/sync"
    15  )
    16  
    17  // newTestingGateway returns a gateway ready to use in a testing environment.
    18  func newTestingGateway(t *testing.T) *Gateway {
    19  	if testing.Short() {
    20  		panic("newTestingGateway called during short test")
    21  	}
    22  
    23  	g, err := New("localhost:0", false, build.TempDir("gateway", t.Name()))
    24  	if err != nil {
    25  		panic(err)
    26  	}
    27  	return g
    28  }
    29  
    30  // newNamedTestingGateway returns a gateway ready to use in a testing
    31  // environment. The gateway's persist folder will have the specified suffix.
    32  func newNamedTestingGateway(t *testing.T, suffix string) *Gateway {
    33  	if testing.Short() {
    34  		panic("newTestingGateway called during short test")
    35  	}
    36  
    37  	g, err := New("localhost:0", false, build.TempDir("gateway", t.Name()+suffix))
    38  	if err != nil {
    39  		panic(err)
    40  	}
    41  	return g
    42  }
    43  
    44  // TestExportedMethodsErrAfterClose tests that exported methods like Close and
    45  // Connect error with siasync.ErrStopped after the gateway has been closed.
    46  func TestExportedMethodsErrAfterClose(t *testing.T) {
    47  	if testing.Short() {
    48  		t.SkipNow()
    49  	}
    50  	t.Parallel()
    51  	g := newTestingGateway(t)
    52  
    53  	if err := g.Close(); err != nil {
    54  		t.Fatal(err)
    55  	}
    56  	if err := g.Close(); err != siasync.ErrStopped {
    57  		t.Fatalf("expected %q, got %q", siasync.ErrStopped, err)
    58  	}
    59  	if err := g.Connect("localhost:1234"); err != siasync.ErrStopped {
    60  		t.Fatalf("expected %q, got %q", siasync.ErrStopped, err)
    61  	}
    62  }
    63  
    64  // TestAddress tests that Gateway.Address returns the address of its listener.
    65  // Also tests that the address is not unspecified and is a loopback address.
    66  // The address must be a loopback address for testing.
    67  func TestAddress(t *testing.T) {
    68  	if testing.Short() {
    69  		t.SkipNow()
    70  	}
    71  	t.Parallel()
    72  	g := newTestingGateway(t)
    73  	defer g.Close()
    74  
    75  	if g.Address() != g.myAddr {
    76  		t.Fatal("Address does not return g.myAddr")
    77  	}
    78  	if g.Address() != modules.NetAddress(g.listener.Addr().String()) {
    79  		t.Fatalf("wrong address: expected %v, got %v", g.listener.Addr(), g.Address())
    80  	}
    81  	host := modules.NetAddress(g.listener.Addr().String()).Host()
    82  	ip := net.ParseIP(host)
    83  	if ip == nil {
    84  		t.Fatal("address is not an IP address")
    85  	}
    86  	if ip.IsUnspecified() {
    87  		t.Fatal("expected a non-unspecified address")
    88  	}
    89  	if !ip.IsLoopback() {
    90  		t.Fatal("expected a loopback address")
    91  	}
    92  }
    93  
    94  // TestPeers checks that two gateways are able to connect to each other.
    95  func TestPeers(t *testing.T) {
    96  	if testing.Short() {
    97  		t.SkipNow()
    98  	}
    99  	t.Parallel()
   100  	g1 := newNamedTestingGateway(t, "1")
   101  	defer g1.Close()
   102  	g2 := newNamedTestingGateway(t, "2")
   103  	defer g2.Close()
   104  
   105  	err := g1.Connect(g2.Address())
   106  	if err != nil {
   107  		t.Fatal("failed to connect:", err)
   108  	}
   109  	peers := g1.Peers()
   110  	if len(peers) != 1 || peers[0].NetAddress != g2.Address() {
   111  		t.Fatal("g1 has bad peer list:", peers)
   112  	}
   113  	err = g1.Disconnect(g2.Address())
   114  	if err != nil {
   115  		t.Fatal("failed to disconnect:", err)
   116  	}
   117  	peers = g1.Peers()
   118  	if len(peers) != 0 {
   119  		t.Fatal("g1 has peers after disconnect:", peers)
   120  	}
   121  }
   122  
   123  // TestNew checks that a call to New is effective.
   124  func TestNew(t *testing.T) {
   125  	if testing.Short() {
   126  		t.SkipNow()
   127  	}
   128  	t.Parallel()
   129  
   130  	if _, err := New("", false, ""); err == nil {
   131  		t.Fatal("expecting persistDir error, got nil")
   132  	}
   133  	if _, err := New("localhost:0", false, ""); err == nil {
   134  		t.Fatal("expecting persistDir error, got nil")
   135  	}
   136  	if g, err := New("foo", false, build.TempDir("gateway", t.Name()+"1")); err == nil {
   137  		t.Fatal("expecting listener error, got nil", g.myAddr)
   138  	}
   139  	// create corrupted nodes.json
   140  	dir := build.TempDir("gateway", t.Name()+"2")
   141  	os.MkdirAll(dir, 0700)
   142  	err := ioutil.WriteFile(filepath.Join(dir, "nodes.json"), []byte{1, 2, 3}, 0660)
   143  	if err != nil {
   144  		t.Fatal("couldn't create corrupted file:", err)
   145  	}
   146  	if _, err := New("localhost:0", false, dir); err == nil {
   147  		t.Fatal("expected load error, got nil")
   148  	}
   149  }
   150  
   151  // TestClose creates and closes a gateway.
   152  func TestClose(t *testing.T) {
   153  	if testing.Short() {
   154  		t.SkipNow()
   155  	}
   156  	t.Parallel()
   157  
   158  	g := newTestingGateway(t)
   159  	err := g.Close()
   160  	if err != nil {
   161  		t.Fatal(err)
   162  	}
   163  }
   164  
   165  // TestParallelClose spins up 3 gateways, connects them all, and then closes
   166  // them in parallel. The goal of this test is to make it more vulnerable to any
   167  // potential nondeterministic failures.
   168  func TestParallelClose(t *testing.T) {
   169  	if testing.Short() {
   170  		t.SkipNow()
   171  	}
   172  	t.Parallel()
   173  
   174  	// Spin up three gateways in parallel.
   175  	var gs [3]*Gateway
   176  	var wg sync.WaitGroup
   177  	wg.Add(3)
   178  	for i := range gs {
   179  		go func(i int) {
   180  			gs[i] = newNamedTestingGateway(t, strconv.Itoa(i))
   181  			wg.Done()
   182  		}(i)
   183  	}
   184  	wg.Wait()
   185  
   186  	// Connect g1 to g2, g2 to g3. They may connect to eachother further.
   187  	wg.Add(2)
   188  	for i := range gs[:2] {
   189  		go func(i int) {
   190  			err := gs[i].Connect(gs[i+1].myAddr)
   191  			if err != nil {
   192  				panic(err)
   193  			}
   194  			wg.Done()
   195  		}(i)
   196  	}
   197  	wg.Wait()
   198  
   199  	// Close all three gateways in parallel.
   200  	wg.Add(3)
   201  	for i := range gs {
   202  		go func(i int) {
   203  			err := gs[i].Close()
   204  			if err != nil {
   205  				panic(err)
   206  			}
   207  			wg.Done()
   208  		}(i)
   209  	}
   210  	wg.Wait()
   211  }