From b705d3dcb9c4541fe7c759e901498e51ac29b634 Mon Sep 17 00:00:00 2001 From: Bruno Bachmann Date: Sat, 16 Sep 2017 10:37:39 -0700 Subject: [PATCH] Add blockchain tests --- blockchain/block_test.go | 44 +++++++++++++++++++++++++ blockchain/blockchain.go | 9 +++--- blockchain/blockchain_test.go | 60 +++++++++++++++++++++++++++++++++-- blockchain/test_utils.go | 50 ----------------------------- blockchain/wallet.go | 4 +-- blockchain/wallet_test.go | 23 ++++++++++++++ 6 files changed, 130 insertions(+), 60 deletions(-) diff --git a/blockchain/block_test.go b/blockchain/block_test.go index dbdfd34..fc582df 100644 --- a/blockchain/block_test.go +++ b/blockchain/block_test.go @@ -78,3 +78,47 @@ func TestEqual(t *testing.T) { block2 := NewTestBlock() assert.False(t, (&block1.BlockHeader).Equal(&block2.BlockHeader)) } + +func TestBlockLen(t *testing.T) { + assert.True(t, NewTestBlock().Len() > 0) +} + +func TestGetCloudBaseTransaction(t *testing.T) { + b := NewTestBlock() + assert.Equal(t, b.GetCloudBaseTransaction(), b.Transactions[0]) +} + +func TestGetTransactionsFrom(t *testing.T) { + bc, wallets := NewValidBlockChainFixture() + expectedResult := []*Transaction{ + bc.Blocks[2].Transactions[1], + } + senderHash := wallets["sender"].Public().Repr() + assert.Equal(t, bc.Blocks[2].GetTransactionsFrom(senderHash), expectedResult) +} + +func TestGetTransactionsTo(t *testing.T) { + bc, wallets := NewValidBlockChainFixture() + expectedResult := []*Transaction{ + bc.Blocks[2].Transactions[1], + } + bobHash := wallets["bob"].Public().Repr() + assert.Equal(t, bc.Blocks[2].GetTransactionsTo(bobHash), expectedResult) +} + +func TestGetTotalInputFrom(t *testing.T) { + bc, wallets := NewValidBlockChainFixture() + expectedAmount := bc.Blocks[2].Transactions[1].Outputs[0].Amount + senderHash := wallets["sender"].Public().Repr() + amount, err := bc.Blocks[2].GetTotalInputFrom(senderHash, bc) + assert.Nil(t, err) + assert.Equal(t, amount, expectedAmount) +} + +func TestBlockGetTotalOutputFor(t *testing.T) { + bc, wallets := NewValidBlockChainFixture() + expectedAmount := bc.Blocks[2].Transactions[1].Outputs[0].Amount + bobHash := wallets["bob"].Public().Repr() + amount := bc.Blocks[2].GetTotalOutputFor(bobHash) + assert.Equal(t, amount, expectedAmount) +} diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index d273f80..00a5ba6 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -13,7 +13,7 @@ const ( // StartingBlockReward is the mining reward that the blockchain will begin // with. StartingBlockReward uint64 = 25 * CoinValue - // blockRewardHalvingRate is the number of blocks that need to be mined + // BlockRewardHalvingRate is the number of blocks that need to be mined // before the blockReward is halved BlockRewardHalvingRate int = 210000 ) @@ -147,15 +147,16 @@ func (bc *BlockChain) GetAllInputs(t *Transaction) ([]*Transaction, error) { for _, tx := range t.Inputs { nextTxn := bc.GetInputTransaction(&tx) if nextTxn == nil { - return nil, errors.New("input transaction not found") + return nil, errors.New("Input transaction not found") } txns = append(txns, nextTxn) } return txns, nil } -// ContainsTransaction returns true if the BlockChain contains the transaction -// in a block between start and stop as indexes. +// ContainsTransaction returns true, the block index, and the transaction index +// if the BlockChain contains the transaction in a block between start and stop +// indexes. func (bc *BlockChain) ContainsTransaction(t *Transaction, start, stop uint32) (bool, uint32, uint32) { for i := start; i < stop; i++ { if exists, j := bc.Blocks[i].ContainsTransaction(t); exists { diff --git a/blockchain/blockchain_test.go b/blockchain/blockchain_test.go index 5325049..ed7cf81 100644 --- a/blockchain/blockchain_test.go +++ b/blockchain/blockchain_test.go @@ -9,12 +9,24 @@ import ( "github.com/stretchr/testify/assert" ) -const blockchainFileName = "blockchain.json" - func TestMain(t *testing.T) { log.SetLevel(log.DebugLevel) } +func TestNew(t *testing.T) { + assert.NotNil(t, New()) +} + +func TestMarshal(t *testing.T) { + b := NewTestBlock() + assert.NotNil(t, b.Marshal()) +} + +func TestLen(t *testing.T) { + bc, _ := NewValidTestChainAndBlock() + assert.True(t, bc.Len() > 0) +} + func TestSaveAndLoad(t *testing.T) { bc1, _ := NewValidTestChainAndBlock() assert.Nil(t, bc1.Save("blockchainTestFile.json")) @@ -39,7 +51,7 @@ func TestWalletRepr(t *testing.T) { assert.Equal(t, len(w.Public().Repr()), 40) } -func TestAppend(t *testing.T) { +func TestAppendBlock(t *testing.T) { bc, block := NewValidTestChainAndBlock() bc.AppendBlock(block) if bc.Head != HashSum(block) || bc.LastBlock() != block { @@ -68,3 +80,45 @@ func TestRollBack(t *testing.T) { t.FailNow() } } + +func TestGetInputTransaction(t *testing.T) { + bc := NewTestBlockChain() + txnPtr := &TxHashPointer{ + BlockNumber: 0, + Index: 0, + } + assert.NotNil(t, bc.GetInputTransaction(txnPtr)) +} + +func TestGetAllInputs(t *testing.T) { + bc := NewTestBlockChain() + txn := NewTestTransaction() + _, err := bc.GetAllInputs(txn) + assert.EqualError(t, err, "Input transaction not found") + bc, b := NewValidTestChainAndBlock() + expectedResult := []*Transaction{ + bc.Blocks[1].Transactions[1], + } + result, err := bc.GetAllInputs(b.Transactions[1]) + assert.Nil(t, err) + assert.Equal(t, expectedResult, result) +} + +func TestBlockchainContainsTransaction(t *testing.T) { + bc, txn := NewValidChainAndTxn() + found, blockIndex, txnIndex := bc.ContainsTransaction(bc.Blocks[1].Transactions[0], 0, 2) + assert.True(t, found) + assert.Equal(t, blockIndex, uint32(1)) + assert.Equal(t, txnIndex, uint32(0)) + found, _, _ = bc.ContainsTransaction(txn, 0, 2) + assert.False(t, found) +} + +func TestGetBlockByLastBlockHash(t *testing.T) { + bc := NewTestBlockChain() + block, err := bc.GetBlockByLastBlockHash(bc.Blocks[1].BlockHeader.LastBlock) + assert.Nil(t, err) + assert.Equal(t, block, bc.Blocks[1]) + _, err = bc.GetBlockByLastBlockHash(NewTestHash()) + assert.EqualError(t, err, "No such block") +} diff --git a/blockchain/test_utils.go b/blockchain/test_utils.go index 56f20b1..ede39b9 100644 --- a/blockchain/test_utils.go +++ b/blockchain/test_utils.go @@ -9,7 +9,6 @@ import ( "sync" c "github.com/ubclaunchpad/cumulus/common/constants" - "github.com/ubclaunchpad/cumulus/common/util" ) // NewTestHash produces a hash. @@ -101,55 +100,6 @@ func NewTestBlockChain() *BlockChain { return &bc } -// NewTestInputBlock produces new block with given transactions. -func NewTestInputBlock(t []*Transaction) *Block { - return &Block{ - BlockHeader: BlockHeader{ - BlockNumber: 0, - LastBlock: NewTestHash(), - Target: NewValidTestTarget(), - Time: util.UnixNow(), - Nonce: 0, - }, - Transactions: t, - } -} - -// NewTestOutputBlock produces new block with given transactions and given input -// block. -func NewTestOutputBlock(t []*Transaction, input *Block) *Block { - return &Block{ - BlockHeader: BlockHeader{ - BlockNumber: input.BlockNumber + 1, - LastBlock: HashSum(input), - Target: NewValidTestTarget(), - Time: util.UnixNow(), - Nonce: 0, - }, - Transactions: t, - } -} - -// NewTestTransactionValue creates a new transaction with specific value a at -// index i in block number b. -func NewTestTransactionValue(s, r *Wallet, a uint64, i uint32, b uint32) (*Transaction, error) { - tbody := TxBody{ - Sender: s.Public(), - Inputs: make([]TxHashPointer, 1), - Outputs: make([]TxOutput, 1), - } - tbody.Outputs[0] = TxOutput{ - Amount: a, - Recipient: r.Public().Repr(), - } - tbody.Inputs[0] = TxHashPointer{ - BlockNumber: b, - Hash: NewTestHash(), - Index: i, - } - return tbody.Sign(*s, crand.Reader) -} - // NewValidBlockChainFixture creates a valid blockchain of three blocks // and returns the wallets involved in the transactions. // The returning wallets will have balances of 3, 1, and 0 respectively. diff --git a/blockchain/wallet.go b/blockchain/wallet.go index a86fb6d..dcc90d7 100644 --- a/blockchain/wallet.go +++ b/blockchain/wallet.go @@ -8,7 +8,6 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" - "errors" "fmt" "io" "math/big" @@ -249,8 +248,7 @@ func (w *Wallet) SetPending(txn *Transaction) error { if bal >= spend { w.PendingTxns = append(w.PendingTxns, txn) } else { - msg := fmt.Sprintf("wallet balance is too low %v < %v", bal, spend) - return errors.New(msg) + return fmt.Errorf("Wallet balance is too low %v < %v", bal, spend) } return nil } diff --git a/blockchain/wallet_test.go b/blockchain/wallet_test.go index 6416d6f..d7a56ce 100644 --- a/blockchain/wallet_test.go +++ b/blockchain/wallet_test.go @@ -1,6 +1,7 @@ package blockchain import ( + "encoding/json" "testing" "github.com/stretchr/testify/assert" @@ -72,3 +73,25 @@ func TestGetWalletBalances(t *testing.T) { assert.Equal(t, w.Balance, txn.GetTotalOutput()) assert.Equal(t, w.GetEffectiveBalance(), uint64(0)) } + +func TestUnmarshalJSON(t *testing.T) { + w1 := NewWallet() + walletBytes, err := json.Marshal(w1) + assert.Nil(t, err) + var w2 Wallet + err = w2.UnmarshalJSON(walletBytes) + assert.Nil(t, err) + assert.Equal(t, w1, &w2) +} + +func TestUpdate(t *testing.T) { + bc, wallets := NewValidBlockChainFixture() + assert.Nil(t, wallets["bob"].Update(bc.Blocks[2], bc)) + assert.Equal(t, wallets["bob"].Balance, uint64(1)) +} + +func TestRefresh(t *testing.T) { + bc, wallets := NewValidBlockChainFixture() + assert.Nil(t, wallets["bob"].Refresh(bc)) + assert.Equal(t, wallets["bob"].Balance, uint64(1)) +}