github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/p2p/node_test.go (about)

     1  package p2p
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sync"
     7  	"testing"
     8  	"time"
     9  
    10  	ma "github.com/multiformats/go-multiaddr"
    11  	testkeys "github.com/qri-io/qri/auth/key/test"
    12  	testcfg "github.com/qri-io/qri/config/test"
    13  	"github.com/qri-io/qri/event"
    14  	p2ptest "github.com/qri-io/qri/p2p/test"
    15  	"github.com/qri-io/qri/profile"
    16  	"github.com/qri-io/qri/repo/test"
    17  )
    18  
    19  func TestNewNode(t *testing.T) {
    20  	ctx, cancel := context.WithCancel(context.Background())
    21  	defer cancel()
    22  
    23  	keyData := testkeys.GetKeyData(0)
    24  	r, err := test.NewTestRepoFromProfileID(profile.IDFromPeerID(keyData.PeerID), 0, -1)
    25  	if err != nil {
    26  		t.Errorf("error creating test repo: %s", err.Error())
    27  		return
    28  	}
    29  
    30  	bus := event.NewBus(ctx)
    31  
    32  	eventFired := make(chan struct{}, 1)
    33  	bus.SubscribeTypes(func(_ context.Context, e event.Event) error {
    34  		if e.Type == event.ETP2PGoneOnline {
    35  			if _, ok := e.Payload.([]ma.Multiaddr); !ok {
    36  				t.Errorf("expected %q event to have a payload of []multiaddr.Multiaddr, got: %T", event.ETP2PGoneOnline, e.Payload)
    37  			}
    38  			eventFired <- struct{}{}
    39  		}
    40  		return nil
    41  	}, event.ETP2PGoneOnline)
    42  
    43  	p2pconf := testcfg.DefaultP2PForTesting()
    44  	n, err := NewQriNode(r, p2pconf, bus, nil)
    45  	if err != nil {
    46  		t.Errorf("error creating qri node: %s", err.Error())
    47  		return
    48  	}
    49  
    50  	if n.Online {
    51  		t.Errorf("default node online flag should be false")
    52  	}
    53  	if err := n.GoOnline(ctx); err != nil {
    54  		t.Error(err.Error())
    55  	}
    56  	if !n.Online {
    57  		t.Errorf("online should equal true")
    58  	}
    59  	<-eventFired
    60  }
    61  
    62  func TestNodeEvents(t *testing.T) {
    63  	t.Skip("TODO(b5): this test is too flaky")
    64  	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    65  	defer cancel()
    66  
    67  	bus := event.NewBus(ctx)
    68  	result := make(chan error, 1)
    69  	events := []event.Type{
    70  		// TODO (b5) - can't check onlineness because of the way this test is constructed
    71  		// event.ETP2PGoneOnline,
    72  		event.ETP2PGoneOffline,
    73  		// TODO (ramfox) - the QriPeerConnected is attempted when the `libp2pevent.EvtPeerIdentificationCompleted`
    74  		// event successfully goes off (which is rare atm, the identification fails
    75  		// with a "stream reset" error), so I'm commenting that out for now
    76  		// event.ETP2PQriPeerConnected,
    77  		// TODO (b5) - this event currently isn't emitted
    78  		// event.ETP2PQriPeerDisconnected,
    79  		event.ETP2PPeerConnected,
    80  		event.ETP2PPeerDisconnected,
    81  	}
    82  
    83  	called := map[event.Type]bool{}
    84  	calledMu := sync.Mutex{}
    85  	remaining := len(events)
    86  
    87  	// TODO (ramfox): when we can figure out the `libp2pevent.EvtPeerIdentificationFailed`
    88  	// "stream reset" error, we can add this back in
    89  	// qriPeerConnectedCh := make(chan struct{}, 1)
    90  
    91  	bus.SubscribeTypes(func(_ context.Context, e event.Event) error {
    92  		calledMu.Lock()
    93  		defer calledMu.Unlock()
    94  		if called[e.Type] {
    95  			// TODO (ramfox): this is commented out currently because I'm not totally
    96  			// sure why connects and disconnects are fireing multiple times
    97  			t.Logf("expected event %q to only fire once", e.Type)
    98  			return nil
    99  		}
   100  
   101  		// TODO (ramfox): when we can figure out the `libp2pevent.EvtPeerIdentificationFailed`
   102  		// "stream reset" error, we can add this back in
   103  		// if typ == event.ETP2PQriPeerConnected {
   104  		// 		qriPeerConnectedCh <- struct{}{}
   105  		// 	}
   106  
   107  		called[e.Type] = true
   108  		remaining--
   109  		t.Logf("remaining: %d", remaining)
   110  		if remaining == 0 {
   111  			result <- nil
   112  			return nil
   113  		}
   114  		return nil
   115  	}, events...)
   116  
   117  	go func() {
   118  		select {
   119  		case <-ctx.Done():
   120  			ok := true
   121  			uncalled := ""
   122  			calledMu.Lock()
   123  			for tp, called := range called {
   124  				if !called {
   125  					uncalled += fmt.Sprintf("%s\n", tp)
   126  					ok = false
   127  				}
   128  			}
   129  			calledMu.Unlock()
   130  			if !ok {
   131  				result <- fmt.Errorf("context cancelled before all events could fire. Uncalled Events:\n%s", uncalled)
   132  				return
   133  			}
   134  			result <- nil
   135  		}
   136  	}()
   137  
   138  	factory := p2ptest.NewTestNodeFactoryWithBus(NewTestableQriNode)
   139  	testPeers, err := p2ptest.NewTestNetwork(ctx, factory, 2)
   140  	if err != nil {
   141  		t.Fatalf("error creating network: %s", err.Error())
   142  	}
   143  	peers := asQriNodes(testPeers)
   144  	peers[0].pub = bus
   145  
   146  	if err := peers[0].Host().Connect(ctx, peers[1].SimpleAddrInfo()); err != nil {
   147  		t.Fatalf("error connecting nodes: %s", err)
   148  	}
   149  
   150  	// TODO (ramfox): when we can figure out the `libp2pevent.EvtPeerIdentificationFailed`
   151  	// "stream reset" error, we can add this back in
   152  	// // because upgrading to a qri peer connection happens async after the `PeerConnect`
   153  	// // event, we need to wait for the qri peer to upgrade before we send the second
   154  	// // peer offline
   155  	// <-qriPeerConnectedCh
   156  
   157  	if err := peers[1].GoOffline(); err != nil {
   158  		t.Error(err)
   159  	}
   160  
   161  	if err := peers[0].GoOffline(); err != nil {
   162  		fmt.Println("error go offline", err)
   163  		t.Error(err)
   164  	}
   165  
   166  	if err := <-result; err != nil {
   167  		t.Error(err)
   168  	}
   169  }