chainntfns: extend testSpendNotification to test for multi-client dispatch

This commit is contained in:
Olaoluwa Osuntokun 2016-11-27 19:18:18 -08:00
parent d1f12627d2
commit 7b016fef0a
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
1 changed files with 65 additions and 34 deletions

View File

@ -46,6 +46,8 @@ func getTestTxId(miner *rpctest.Harness) (*wire.ShaHash, error) {
func testSingleConfirmationNotification(miner *rpctest.Harness, func testSingleConfirmationNotification(miner *rpctest.Harness,
notifier chainntnfs.ChainNotifier, t *testing.T) { notifier chainntnfs.ChainNotifier, t *testing.T) {
t.Logf("testing single conf notification")
// We'd like to test the case of being notified once a txid reaches // We'd like to test the case of being notified once a txid reaches
// a *single* confirmation. // a *single* confirmation.
// //
@ -88,6 +90,8 @@ func testSingleConfirmationNotification(miner *rpctest.Harness,
func testMultiConfirmationNotification(miner *rpctest.Harness, func testMultiConfirmationNotification(miner *rpctest.Harness,
notifier chainntnfs.ChainNotifier, t *testing.T) { notifier chainntnfs.ChainNotifier, t *testing.T) {
t.Logf("testing mulit-conf notification")
// We'd like to test the case of being notified once a txid reaches // We'd like to test the case of being notified once a txid reaches
// N confirmations, where N > 1. // N confirmations, where N > 1.
// //
@ -125,6 +129,8 @@ func testMultiConfirmationNotification(miner *rpctest.Harness,
func testBatchConfirmationNotification(miner *rpctest.Harness, func testBatchConfirmationNotification(miner *rpctest.Harness,
notifier chainntnfs.ChainNotifier, t *testing.T) { notifier chainntnfs.ChainNotifier, t *testing.T) {
t.Logf("testing batch mulit-conf notification")
// We'd like to test a case of serving notifiations to multiple // We'd like to test a case of serving notifiations to multiple
// clients, each requesting to be notified once a txid receives // clients, each requesting to be notified once a txid receives
// various numbers of confirmations. // various numbers of confirmations.
@ -184,11 +190,12 @@ func testBatchConfirmationNotification(miner *rpctest.Harness,
func testSpendNotification(miner *rpctest.Harness, func testSpendNotification(miner *rpctest.Harness,
notifier chainntnfs.ChainNotifier, t *testing.T) { notifier chainntnfs.ChainNotifier, t *testing.T) {
// We'd like to test the spend notifiations for all t.Logf("testing multi-client spend notification")
// ChainNotifier concrete implemenations.
// We'd like to test the spend notifiations for all ChainNotifier
// concrete implemenations.
// //
// To do so, we first create a new output to our test target // To do so, we first create a new output to our test target address.
// address.
txid, err := getTestTxId(miner) txid, err := getTestTxId(miner)
if err != nil { if err != nil {
t.Fatalf("unable to create test addr: %v", err) t.Fatalf("unable to create test addr: %v", err)
@ -206,8 +213,8 @@ func testSpendNotification(miner *rpctest.Harness,
} }
tx := wrappedTx.MsgTx() tx := wrappedTx.MsgTx()
// Locate the output index sent to us. We need this so we can // Locate the output index sent to us. We need this so we can construct
// construct a spending txn below. // a spending txn below.
outIndex := -1 outIndex := -1
var pkScript []byte var pkScript []byte
for i, txOut := range tx.TxOut { for i, txOut := range tx.TxOut {
@ -222,11 +229,20 @@ func testSpendNotification(miner *rpctest.Harness,
} }
// Now that we've found the output index, register for a spentness // Now that we've found the output index, register for a spentness
// notification for the newly created output. // notification for the newly created output with multiple clients in
// order to ensure the implementation can support multi-client spend
// notifiations.
outpoint := wire.NewOutPoint(txid, uint32(outIndex)) outpoint := wire.NewOutPoint(txid, uint32(outIndex))
spentIntent, err := notifier.RegisterSpendNtfn(outpoint)
if err != nil { const numClients = 5
t.Fatalf("unable to register for spend ntfn: %v", err) spendClients := make([]*chainntnfs.SpendEvent, numClients)
for i := 0; i < numClients; i++ {
spentIntent, err := notifier.RegisterSpendNtfn(outpoint)
if err != nil {
t.Fatalf("unable to register for spend ntfn: %v", err)
}
spendClients[i] = spentIntent
} }
// Next, create a new transaction spending that output. // Next, create a new transaction spending that output.
@ -257,35 +273,47 @@ func testSpendNotification(miner *rpctest.Harness,
t.Fatalf("unable to generate single block: %v", err) t.Fatalf("unable to generate single block: %v", err)
} }
spentNtfn := make(chan *chainntnfs.SpendDetail) // For each event we registered for above, we create a goroutine which
go func() { // will listen on the event channel, passing it proxying each
spentNtfn <- <-spentIntent.Spend // notification into a single which will be examined belwo.
}() spentNtfn := make(chan *chainntnfs.SpendDetail, numClients)
for i := 0; i < numClients; i++ {
go func(c *chainntnfs.SpendEvent) {
spentNtfn <- <-c.Spend
}(spendClients[i])
}
select { for i := 0; i < numClients; i++ {
case ntfn := <-spentNtfn: select {
// We've received the spend nftn. So now verify all the fields case ntfn := <-spentNtfn:
// have been set properly. // We've received the spend nftn. So now verify all the
if ntfn.SpentOutPoint != outpoint { // fields have been set properly.
t.Fatalf("ntfn includes wrong output, reports %v instead of %v", if ntfn.SpentOutPoint != outpoint {
ntfn.SpentOutPoint, outpoint) t.Fatalf("ntfn includes wrong output, reports "+
"%v instead of %v",
ntfn.SpentOutPoint, outpoint)
}
if !bytes.Equal(ntfn.SpenderTxHash.Bytes(), spenderSha.Bytes()) {
t.Fatalf("ntfn includes wrong spender tx sha, "+
"reports %v intead of %v",
ntfn.SpenderTxHash.Bytes(), spenderSha.Bytes())
}
if ntfn.SpenderInputIndex != 0 {
t.Fatalf("ntfn includes wrong spending input "+
"index, reports %v, should be %v",
ntfn.SpenderInputIndex, 0)
}
case <-time.After(2 * time.Second):
t.Fatalf("spend ntfn never received")
} }
if !bytes.Equal(ntfn.SpenderTxHash.Bytes(), spenderSha.Bytes()) {
t.Fatalf("ntfn includes wrong spender tx sha, reports %v intead of %v",
ntfn.SpenderTxHash.Bytes(), spenderSha.Bytes())
}
if ntfn.SpenderInputIndex != 0 {
t.Fatalf("ntfn includes wrong spending input index, reports %v, should be %v",
ntfn.SpenderInputIndex, 0)
}
case <-time.After(2 * time.Second):
t.Fatalf("spend ntfn never received")
} }
} }
func testBlockEpochNotification(miner *rpctest.Harness, func testBlockEpochNotification(miner *rpctest.Harness,
notifier chainntnfs.ChainNotifier, t *testing.T) { notifier chainntnfs.ChainNotifier, t *testing.T) {
t.Logf("testing block epoch notification")
// We'd like to test the case of multiple registered clients receiving // We'd like to test the case of multiple registered clients receiving
// block epoch notifications. // block epoch notifications.
@ -333,7 +361,8 @@ func testBlockEpochNotification(miner *rpctest.Harness,
func testMultiClientConfirmationNotification(miner *rpctest.Harness, func testMultiClientConfirmationNotification(miner *rpctest.Harness,
notifier chainntnfs.ChainNotifier, t *testing.T) { notifier chainntnfs.ChainNotifier, t *testing.T) {
// TODO(roasbeef): test various conf targets w/ same txid
t.Logf("testing multi-client multi-conf notification")
// We'd like to test the case of a multiple clients registered to // We'd like to test the case of a multiple clients registered to
// receive a confirmation notification for the same transaction. // receive a confirmation notification for the same transaction.
@ -344,8 +373,10 @@ func testMultiClientConfirmationNotification(miner *rpctest.Harness,
} }
var wg sync.WaitGroup var wg sync.WaitGroup
const numConfsClients = 5 const (
const numConfs = 1 numConfsClients = 5
numConfs = 1
)
// Register for a conf notification for the above generated txid with // Register for a conf notification for the above generated txid with
// numConfsClients distinct clients. // numConfsClients distinct clients.