github.com/metacurrency/holochain@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/kad_table_test.go (about)

     1  // This code is adapted from the libp2p project, specifically:
     2  // https://github.com/libp2p/go-libp2p-kbucket/table_test.go
     3  // we don't need to unify keyspaces between random strings and peer.IDs which ipfs requires.
     4  
     5  package holochain
     6  
     7  import (
     8  	. "github.com/holochain/holochain-proto/hash"
     9  	peer "github.com/libp2p/go-libp2p-peer"
    10  	pstore "github.com/libp2p/go-libp2p-peerstore"
    11  	tu "github.com/libp2p/go-testutil"
    12  	"math/rand"
    13  	"testing"
    14  	"time"
    15  )
    16  
    17  // Test basic features of the bucket struct
    18  func TestBucket(t *testing.T) {
    19  	b := newBucket()
    20  
    21  	peers := make([]peer.ID, 100)
    22  	for i := 0; i < 100; i++ {
    23  		peers[i] = tu.RandPeerIDFatal(t)
    24  		b.PushFront(peers[i])
    25  	}
    26  
    27  	localID := tu.RandPeerIDFatal(t)
    28  
    29  	i := rand.Intn(len(peers))
    30  	if !b.Has(peers[i]) {
    31  		t.Errorf("Failed to find peer: %v", peers[i])
    32  	}
    33  
    34  	spl := b.Split(0, localID)
    35  	llist := b.list
    36  	for e := llist.Front(); e != nil; e = e.Next() {
    37  		p := e.Value.(peer.ID)
    38  		cpl := commonPrefixLen(p, localID)
    39  		if cpl > 0 {
    40  			t.Fatalf("Split failed. found id with cpl > 0 in 0 bucket")
    41  		}
    42  	}
    43  
    44  	rlist := spl.list
    45  	for e := rlist.Front(); e != nil; e = e.Next() {
    46  		p := e.Value.(peer.ID)
    47  		cpl := commonPrefixLen(p, localID)
    48  		if cpl == 0 {
    49  			t.Fatalf("Split failed. found id with cpl == 0 in non 0 bucket")
    50  		}
    51  	}
    52  }
    53  
    54  func TestTableCallbacks(t *testing.T) {
    55  	local := tu.RandPeerIDFatal(t)
    56  	m := pstore.NewMetrics()
    57  	rt := NewRoutingTable(10, local, time.Hour, m)
    58  
    59  	peers := make([]peer.ID, 100)
    60  	for i := 0; i < 100; i++ {
    61  		peers[i] = tu.RandPeerIDFatal(t)
    62  	}
    63  
    64  	pset := make(map[peer.ID]struct{})
    65  	rt.PeerAdded = func(p peer.ID) {
    66  		pset[p] = struct{}{}
    67  	}
    68  	rt.PeerRemoved = func(p peer.ID) {
    69  		delete(pset, p)
    70  	}
    71  
    72  	rt.Update(peers[0])
    73  	if _, ok := pset[peers[0]]; !ok {
    74  		t.Fatal("should have this peer")
    75  	}
    76  
    77  	rt.Remove(peers[0])
    78  	if _, ok := pset[peers[0]]; ok {
    79  		t.Fatal("should not have this peer")
    80  	}
    81  
    82  	for _, p := range peers {
    83  		rt.Update(p)
    84  	}
    85  
    86  	out := rt.ListPeers()
    87  	for _, outp := range out {
    88  		if _, ok := pset[outp]; !ok {
    89  			t.Fatal("should have peer in the peerset")
    90  		}
    91  		delete(pset, outp)
    92  	}
    93  
    94  	if len(pset) > 0 {
    95  		t.Fatal("have peers in peerset that were not in the table", len(pset))
    96  	}
    97  }
    98  
    99  // Right now, this just makes sure that it doesnt hang or crash
   100  func TestTableUpdate(t *testing.T) {
   101  	local := tu.RandPeerIDFatal(t)
   102  	m := pstore.NewMetrics()
   103  	rt := NewRoutingTable(10, local, time.Hour, m)
   104  
   105  	peers := make([]peer.ID, 100)
   106  	for i := 0; i < 100; i++ {
   107  		peers[i] = tu.RandPeerIDFatal(t)
   108  	}
   109  
   110  	// Testing Update
   111  	for i := 0; i < 10000; i++ {
   112  		rt.Update(peers[rand.Intn(len(peers))])
   113  	}
   114  
   115  	for i := 0; i < 100; i++ {
   116  		id := tu.RandPeerIDFatal(t)
   117  		ret := rt.NearestPeers(HashFromPeerID(id), 5)
   118  		if len(ret) == 0 {
   119  			t.Fatal("Failed to find node near ID.")
   120  		}
   121  	}
   122  }
   123  
   124  func TestTableFind(t *testing.T) {
   125  	local := tu.RandPeerIDFatal(t)
   126  	m := pstore.NewMetrics()
   127  	rt := NewRoutingTable(10, local, time.Hour, m)
   128  
   129  	peers := make([]peer.ID, 100)
   130  	for i := 0; i < 5; i++ {
   131  		peers[i] = tu.RandPeerIDFatal(t)
   132  		rt.Update(peers[i])
   133  	}
   134  
   135  	t.Logf("Searching for peer: '%s'", peers[2])
   136  	found := rt.NearestPeer(HashFromPeerID(peers[2]))
   137  	if !(found == peers[2]) {
   138  		t.Fatalf("Failed to lookup known node...")
   139  	}
   140  }
   141  
   142  func TestTableFindMultiple(t *testing.T) {
   143  	local := tu.RandPeerIDFatal(t)
   144  	m := pstore.NewMetrics()
   145  	rt := NewRoutingTable(20, local, time.Hour, m)
   146  
   147  	peers := make([]peer.ID, 100)
   148  	for i := 0; i < 18; i++ {
   149  		peers[i] = tu.RandPeerIDFatal(t)
   150  		rt.Update(peers[i])
   151  	}
   152  
   153  	t.Logf("Searching for peer: '%s'", peers[2])
   154  	found := rt.NearestPeers(HashFromPeerID(peers[2]), 15)
   155  	if len(found) != 15 {
   156  		t.Fatalf("Got back different number of peers than we expected.")
   157  	}
   158  }
   159  
   160  // Looks for race conditions in table operations. For a more 'certain'
   161  // test, increase the loop counter from 1000 to a much higher number
   162  // and set GOMAXPROCS above 1
   163  func TestTableMultithreaded(t *testing.T) {
   164  	local, _ := peer.IDB58Decode("QmY8Mzg9F69e5P9AoQPYat655HEhc1TVGs11tmfNSzkqh2")
   165  	m := pstore.NewMetrics()
   166  	tab := NewRoutingTable(20, local, time.Hour, m)
   167  	var peers []peer.ID
   168  	for i := 0; i < 500; i++ {
   169  		peers = append(peers, tu.RandPeerIDFatal(t))
   170  	}
   171  
   172  	count := 1000
   173  	done := make(chan struct{})
   174  	go func() {
   175  		for i := 0; i < count; i++ {
   176  			n := rand.Intn(len(peers))
   177  			tab.Update(peers[n])
   178  		}
   179  		done <- struct{}{}
   180  	}()
   181  
   182  	go func() {
   183  		for i := 0; i < count; i++ {
   184  			n := rand.Intn(len(peers))
   185  			tab.Update(peers[n])
   186  		}
   187  		done <- struct{}{}
   188  	}()
   189  
   190  	go func() {
   191  		for i := 0; i < count; i++ {
   192  			n := rand.Intn(len(peers))
   193  			tab.Find(peers[n])
   194  		}
   195  		done <- struct{}{}
   196  	}()
   197  	<-done
   198  	<-done
   199  	<-done
   200  }
   201  
   202  /*
   203  func BenchmarkUpdates(b *testing.B) {
   204  	b.StopTimer()
   205  	local := ConvertKey("localKey")
   206  	m := pstore.NewMetrics()
   207  	tab := NewRoutingTable(20, local, time.Hour, m)
   208  
   209  	var peers []peer.ID
   210  	for i := 0; i < b.N; i++ {
   211  		peers = append(peers, tu.RandPeerIDFatal(b))
   212  	}
   213  
   214  	b.StartTimer()
   215  	for i := 0; i < b.N; i++ {
   216  		tab.Update(peers[i])
   217  	}
   218  }
   219  
   220  func BenchmarkFinds(b *testing.B) {
   221  	b.StopTimer()
   222  	local := ConvertKey("localKey")
   223  	m := pstore.NewMetrics()
   224  	tab := NewRoutingTable(20, local, time.Hour, m)
   225  
   226  	var peers []peer.ID
   227  	for i := 0; i < b.N; i++ {
   228  		peers = append(peers, tu.RandPeerIDFatal(b))
   229  		tab.Update(peers[i])
   230  	}
   231  
   232  	b.StartTimer()
   233  	for i := 0; i < b.N; i++ {
   234  		tab.Find(peers[i])
   235  	}
   236  }
   237  */