From 1eaa522265150eb942d66408fc833df5fb53e78a Mon Sep 17 00:00:00 2001 From: afederigo Date: Fri, 5 May 2017 10:00:39 +0300 Subject: [PATCH] tests: add test case "disconnecting target peer" Issue: 139 This commit contains test case "disconnecting target peer" (second test case) which takes two connected peers, then checks via assert method one connection exists, then disconnects this remote peer by passing pubKey parameter (just some string) into RPC-call method. Then checks 0 connection exists, and then connects disconnected peer for passing further tests, and then checks one connection exists. --- lnd_test.go | 142 +++++++++++++++++++++++++++++++++++++++++++++++++ networktest.go | 20 ++++++- 2 files changed, 161 insertions(+), 1 deletion(-) diff --git a/lnd_test.go b/lnd_test.go index c1627820..901b7a5d 100644 --- a/lnd_test.go +++ b/lnd_test.go @@ -260,6 +260,29 @@ func assertNumOpenChannelsPending(ctxt context.Context, t *harnessTest, } } +//assertNumConnections asserts number current connections between two peers +func assertNumConnections(ctxt context.Context, t *harnessTest, + alice, bob *lightningNode, expected int) { + aliceNumPeers, err := alice.ListPeers(ctxt, &lnrpc.ListPeersRequest{}) + if err != nil { + t.Fatalf("unable to fetch alice's node (%v) list peers %v", + alice.nodeID, err) + } + bobNumPeers, err := bob.ListPeers(ctxt, &lnrpc.ListPeersRequest{}) + if err != nil { + t.Fatalf("unable to fetch bob's node (%v) list peers %v", + bob.nodeID, err) + } + if len(aliceNumPeers.Peers) != expected { + t.Fatalf("number of peers connected to alice is incorrect: expected %v, got %v", + expected, len(aliceNumPeers.Peers)) + } + if len(bobNumPeers.Peers) != expected { + t.Fatalf("number of peers connected to bob is incorrect: expected %v, got %v", + expected, len(bobNumPeers.Peers)) + } +} + // testBasicChannelFunding performs a test exercising expected behavior from a // basic funding workflow. The test creates a new channel between Alice and // Bob, then immediately closes the channel after asserting some expected post @@ -315,6 +338,121 @@ func testBasicChannelFunding(net *networkHarness, t *harnessTest) { closeChannelAndAssert(ctxt, t, net, net.Alice, chanPoint, false) } +// testDisconnectingTargetPeer performs a test which +// disconnects Alice-peer from Bob-peer and then re-connects them again +func testDisconnectingTargetPeer(net *networkHarness, t *harnessTest) { + + ctxb := context.Background() + + // Check existing connection. + assertNumConnections(ctxb, t, net.Alice, net.Bob, 1) + + chanAmt := btcutil.Amount(btcutil.SatoshiPerBitcoin / 2) + pushAmt := btcutil.Amount(0) + + timeout := time.Duration(time.Second * 10) + ctxt, _ := context.WithTimeout(ctxb, timeout) + + // Create a new channel that requires 1 confs before it's considered + // open, then broadcast the funding transaction + const numConfs = 1 + pendingUpdate, err := net.OpenPendingChannel(ctxt, net.Alice, net.Bob, + chanAmt, pushAmt, numConfs) + if err != nil { + t.Fatalf("unable to open channel: %v", err) + } + + // At this point, the channel's funding transaction will have + // been broadcast, but not confirmed. Alice and Bob's nodes + // should reflect this when queried via RPC. + ctxt, _ = context.WithTimeout(ctxb, timeout) + assertNumOpenChannelsPending(ctxt, t, net.Alice, net.Bob, 1) + + // Disconnect Alice-peer from Bob-peer and get error + // causes by one pending channel with detach node is existing. + if err := net.DisconnectNodes(ctxt, net.Alice, net.Bob); err == nil { + t.Fatalf("Bob's peer was disconnected from Alice's"+ + " while one pending channel is existing: err %v", err) + } + + // Check existing connection. + assertNumConnections(ctxb, t, net.Alice, net.Bob, 1) + + fundingTxID, err := chainhash.NewHash(pendingUpdate.Txid) + if err != nil { + t.Fatalf("unable to convert funding txid into chainhash.Hash:"+ + " %v", err) + } + + // Mine a block, then wait for Alice's node to notify us that the + // channel has been opened. The funding transaction should be found + // within the newly mined block. + block := mineBlocks(t, net, 1)[0] + assertTxInBlock(t, block, fundingTxID) + + // At this point, the channel should be fully opened and there should + // be no pending channels remaining for either node. + time.Sleep(time.Millisecond * 3000) + ctxt, _ = context.WithTimeout(ctxb, timeout) + + assertNumOpenChannelsPending(ctxt, t, net.Alice, net.Bob, 0) + + // The channel should be listed in the peer information returned by + // both peers. + outPoint := wire.OutPoint{ + Hash: *fundingTxID, + Index: pendingUpdate.OutputIndex, + } + + // Check both nodes to ensure that the channel is ready for operation. + ctxt, _ = context.WithTimeout(ctxb, timeout) + if err := net.AssertChannelExists(ctxt, net.Alice, &outPoint); err != nil { + t.Fatalf("unable to assert channel existence: %v", err) + } + ctxt, _ = context.WithTimeout(ctxb, timeout) + if err := net.AssertChannelExists(ctxt, net.Bob, &outPoint); err != nil { + t.Fatalf("unable to assert channel existence: %v", err) + } + + // Finally, immediately close the channel. This function will also + // block until the channel is closed and will additionally assert the + // relevant channel closing post conditions. + chanPoint := &lnrpc.ChannelPoint{ + FundingTxid: pendingUpdate.Txid, + OutputIndex: pendingUpdate.OutputIndex, + } + + // Disconnect Alice-peer from Bob-peer and get error + // causes by one active channel with detach node is existing. + if err := net.DisconnectNodes(ctxt, net.Alice, net.Bob); err == nil { + t.Fatalf("Bob's peer was disconnected from Alice's"+ + " while one active channel is existing: err %v", err) + } + + // Check existing connection. + assertNumConnections(ctxb, t, net.Alice, net.Bob, 1) + + ctxt, _ = context.WithTimeout(ctxb, timeout) + closeChannelAndAssert(ctxt, t, net, net.Alice, chanPoint, true) + + // Disconnect Alice-peer from Bob-peer without getting error + // about existing channels. + if err := net.DisconnectNodes(ctxt, net.Alice, net.Bob); err != nil { + t.Fatalf("unable to disconnect Bob's peer from Alice's: err %v", err) + } + + // Check zero peer connections. + assertNumConnections(ctxb, t, net.Alice, net.Bob, 0) + + // Finally, re-connect both nodes. + if err := net.ConnectNodes(ctxt, net.Alice, net.Bob); err != nil { + t.Fatalf("unable to connect Alice's peer to Bob's: err %v", err) + } + + // Check existing connection. + assertNumConnections(ctxb, t, net.Alice, net.Bob, 1) +} + // testFundingPersistence is intended to ensure that the Funding Manager // persists the state of new channels prior to broadcasting the channel's // funding transaction. This ensures that the daemon maintains an up-to-date @@ -2221,6 +2359,10 @@ var testsCases = []*testCase{ name: "basic funding flow", test: testBasicChannelFunding, }, + { + name: "disconnecting target peer", + test: testDisconnectingTargetPeer, + }, { name: "graph topology notifications", test: testGraphTopologyNotifications, diff --git a/networktest.go b/networktest.go index d551cf24..56a3f295 100644 --- a/networktest.go +++ b/networktest.go @@ -664,7 +664,6 @@ func (n *networkHarness) SetUp() error { // Swap out grpc's default logger with out fake logger which drops the // statements on the floor. grpclog.SetLogger(&fakeLogger{}) - // Start the initial seeder nodes within the test network, then connect // their respective RPC clients. var wg sync.WaitGroup @@ -847,6 +846,25 @@ func (n *networkHarness) ConnectNodes(ctx context.Context, a, b *lightningNode) } } +// DisconnectNodes disconnects node a from node b by sending RPC message +// from a node to b node +func (n *networkHarness) DisconnectNodes(ctx context.Context, a, b *lightningNode) error { + bobInfo, err := b.GetInfo(ctx, &lnrpc.GetInfoRequest{}) + if err != nil { + return err + } + + req := &lnrpc.DisconnectPeerRequest{ + PubKey: bobInfo.IdentityPubkey, + } + + if _, err := a.DisconnectPeer(ctx, req); err != nil { + return err + } + + return nil +} + // RestartNode attempts to restart a lightning node by shutting it down // cleanly, then restarting the process. This function is fully blocking. Upon // restart, the RPC connection to the node will be re-attempted, continuing iff