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 }