github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/modules/gateway/nodes_test.go (about)

     1  package gateway
     2  
     3  import (
     4  	"strconv"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/NebulousLabs/Sia/encoding"
     9  	"github.com/NebulousLabs/Sia/modules"
    10  )
    11  
    12  const dummyNode = "111.111.111.111:1111"
    13  
    14  func TestAddNode(t *testing.T) {
    15  	g := newTestingGateway("TestAddNode", t)
    16  	defer g.Close()
    17  	id := g.mu.Lock()
    18  	defer g.mu.Unlock(id)
    19  	if err := g.addNode(dummyNode); err != nil {
    20  		t.Fatal("addNode failed:", err)
    21  	}
    22  	if err := g.addNode(dummyNode); err == nil {
    23  		t.Error("addNode added duplicate node")
    24  	}
    25  	if err := g.addNode("foo"); err == nil {
    26  		t.Error("addNode added unroutable address")
    27  	}
    28  	if err := g.addNode("foo:9981"); err == nil {
    29  		t.Error("addNode added a non-IP address")
    30  	}
    31  	if err := g.addNode("[::]:9981"); err == nil {
    32  		t.Error("addNode added unspecified address")
    33  	}
    34  }
    35  
    36  func TestRemoveNode(t *testing.T) {
    37  	g := newTestingGateway("TestRemoveNode", t)
    38  	defer g.Close()
    39  	id := g.mu.Lock()
    40  	defer g.mu.Unlock(id)
    41  	if err := g.addNode(dummyNode); err != nil {
    42  		t.Fatal("addNode failed:", err)
    43  	}
    44  	if err := g.removeNode(dummyNode); err != nil {
    45  		t.Fatal("removeNode failed:", err)
    46  	}
    47  	if err := g.removeNode("bar"); err == nil {
    48  		t.Fatal("removeNode removed nonexistent node")
    49  	}
    50  }
    51  
    52  func TestRandomNode(t *testing.T) {
    53  	g := newTestingGateway("TestRandomNode", t)
    54  	defer g.Close()
    55  
    56  	// Test with 0 nodes.
    57  	id := g.mu.RLock()
    58  	_, err := g.randomNode()
    59  	g.mu.RUnlock(id)
    60  	if err != errNoPeers {
    61  		t.Fatal("randomNode should fail when the gateway has 0 nodes")
    62  	}
    63  
    64  	// Test with 1 node.
    65  	id = g.mu.Lock()
    66  	if err = g.addNode(dummyNode); err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	g.mu.Unlock(id)
    70  	id = g.mu.RLock()
    71  	addr, err := g.randomNode()
    72  	g.mu.RUnlock(id)
    73  	if err != nil {
    74  		t.Fatal("randomNode failed:", err)
    75  	} else if addr != dummyNode {
    76  		t.Fatal("randomNode returned wrong address:", addr)
    77  	}
    78  
    79  	// Test again with 0 nodes.
    80  	id = g.mu.Lock()
    81  	err = g.removeNode(dummyNode)
    82  	g.mu.Unlock(id)
    83  	if err != nil {
    84  		t.Fatal(err)
    85  	}
    86  	id = g.mu.RLock()
    87  	_, err = g.randomNode()
    88  	g.mu.RUnlock(id)
    89  	if err != errNoPeers {
    90  		t.Fatalf("randomNode returned wrong error: expected %v, got %v", errNoPeers, err)
    91  	}
    92  
    93  	// Test with 3 nodes.
    94  	nodes := map[modules.NetAddress]int{
    95  		"111.111.111.111:1111": 0,
    96  		"111.111.111.111:2222": 0,
    97  		"111.111.111.111:3333": 0,
    98  	}
    99  	id = g.mu.Lock()
   100  	for addr := range nodes {
   101  		err := g.addNode(addr)
   102  		if err != nil {
   103  			t.Error(err)
   104  		}
   105  	}
   106  	g.mu.Unlock(id)
   107  
   108  	for i := 0; i < len(nodes)*10; i++ {
   109  		id = g.mu.RLock()
   110  		addr, err := g.randomNode()
   111  		g.mu.RUnlock(id)
   112  		if err != nil {
   113  			t.Fatal("randomNode failed:", err)
   114  		}
   115  		nodes[addr]++
   116  	}
   117  	for node, count := range nodes {
   118  		if count == 0 { // 1-in-200000 chance of occurring naturally
   119  			t.Errorf("node %v was never selected", node)
   120  		}
   121  	}
   122  }
   123  
   124  func TestShareNodes(t *testing.T) {
   125  	if testing.Short() {
   126  		t.SkipNow()
   127  	}
   128  	g1 := newTestingGateway("TestShareNodes1", t)
   129  	defer g1.Close()
   130  	g2 := newTestingGateway("TestShareNodes2", t)
   131  	defer g2.Close()
   132  
   133  	// add a node to g2
   134  	id := g2.mu.Lock()
   135  	err := g2.addNode(dummyNode)
   136  	g2.mu.Unlock(id)
   137  	if err != nil {
   138  		t.Fatal(err)
   139  	}
   140  
   141  	// connect
   142  	err = g1.Connect(g2.Address())
   143  	if err != nil {
   144  		t.Fatal("couldn't connect:", err)
   145  	}
   146  
   147  	// g1 should have received the node
   148  	time.Sleep(100 * time.Millisecond)
   149  	id = g1.mu.Lock()
   150  	err = g1.addNode(dummyNode)
   151  	g1.mu.Unlock(id)
   152  	if err == nil {
   153  		t.Fatal("gateway did not receive nodes during Connect:", g1.nodes)
   154  	}
   155  
   156  	// remove all nodes from both peers
   157  	id = g1.mu.Lock()
   158  	g1.nodes = map[modules.NetAddress]struct{}{}
   159  	g1.mu.Unlock(id)
   160  	id = g2.mu.Lock()
   161  	g2.nodes = map[modules.NetAddress]struct{}{}
   162  	g2.mu.Unlock(id)
   163  
   164  	// SharePeers should now return no peers
   165  	var nodes []modules.NetAddress
   166  	err = g1.RPC(g2.Address(), "ShareNodes", func(conn modules.PeerConn) error {
   167  		return encoding.ReadObject(conn, &nodes, maxSharedNodes*maxAddrLength)
   168  	})
   169  	if err != nil {
   170  		t.Fatal(err)
   171  	}
   172  	if len(nodes) != 0 {
   173  		t.Fatal("gateway gave non-existent addresses:", nodes)
   174  	}
   175  
   176  	// sharing should be capped at maxSharedNodes
   177  	for i := 1; i < maxSharedNodes+11; i++ {
   178  		id := g2.mu.Lock()
   179  		err := g2.addNode(modules.NetAddress("111.111.111.111:" + strconv.Itoa(i)))
   180  		g2.mu.Unlock(id)
   181  		if err != nil {
   182  			t.Fatal(err)
   183  		}
   184  	}
   185  	err = g1.RPC(g2.Address(), "ShareNodes", func(conn modules.PeerConn) error {
   186  		return encoding.ReadObject(conn, &nodes, maxSharedNodes*maxAddrLength)
   187  	})
   188  	if err != nil {
   189  		t.Fatal(err)
   190  	}
   191  	if len(nodes) != maxSharedNodes {
   192  		t.Fatalf("gateway gave wrong number of nodes: expected %v, got %v", maxSharedNodes, len(nodes))
   193  	}
   194  }
   195  
   196  func TestRelayNodes(t *testing.T) {
   197  	if testing.Short() {
   198  		t.SkipNow()
   199  	}
   200  	g1 := newTestingGateway("TestRelayNodes1", t)
   201  	defer g1.Close()
   202  	g2 := newTestingGateway("TestRelayNodes2", t)
   203  	defer g2.Close()
   204  	g3 := newTestingGateway("TestRelayNodes3", t)
   205  	defer g3.Close()
   206  
   207  	// normally the Gateway will only register this RPC if has discovered its
   208  	// IP through external means.
   209  	g3.RegisterConnectCall("RelayNode", g3.sendAddress)
   210  
   211  	// connect g2 to g1
   212  	err := g2.Connect(g1.Address())
   213  	if err != nil {
   214  		t.Fatal("couldn't connect:", err)
   215  	}
   216  
   217  	// connect g3 to g1
   218  	err = g3.Connect(g1.Address())
   219  	if err != nil {
   220  		t.Fatal("couldn't connect:", err)
   221  	}
   222  
   223  	// g2 should have received g3's address from g1
   224  	time.Sleep(200 * time.Millisecond)
   225  	id := g2.mu.Lock()
   226  	defer g2.mu.Unlock(id)
   227  	if _, ok := g2.nodes[g3.Address()]; !ok {
   228  		t.Fatal("node was not relayed:", g2.nodes)
   229  	}
   230  }