/* * Copyright (c) 2013 Conformal Systems LLC * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package tx import ( "bytes" "code.google.com/p/go.crypto/ripemd160" "encoding/binary" "github.com/conformal/btcwire" "github.com/davecgh/go-spew/spew" "io" "reflect" "testing" ) var ( recvtx = &RecvTx{ TxHash: [btcwire.HashSize]byte{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, }, Amt: 69, SenderAddr: [ripemd160.Size]byte{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, }, ReceiverAddr: [ripemd160.Size]byte{ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, }, } sendtx = &SendTx{ TxHash: [btcwire.HashSize]byte{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, }, SenderAddr: [ripemd160.Size]byte{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, }, ReceiverAddrs: []struct { Addr [ripemd160.Size]byte Amt uint64 }{ struct { Addr [ripemd160.Size]byte Amt uint64 }{ Amt: 69, Addr: [ripemd160.Size]byte{ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, }, }, struct { Addr [ripemd160.Size]byte Amt uint64 }{ Amt: 96, Addr: [ripemd160.Size]byte{ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, }, }, }, } ) func TestUtxoWriteRead(t *testing.T) { utxo1 := &Utxo{ Addr: [ripemd160.Size]byte{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, }, Out: OutPoint{ Hash: [btcwire.HashSize]byte{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, }, Index: 1, }, Subscript: []byte{}, Amt: 69, Height: 1337, } bufWriter := &bytes.Buffer{} written, err := utxo1.WriteTo(bufWriter) if err != nil { t.Error(err) } utxoBytes := bufWriter.Bytes() utxo2 := new(Utxo) read, err := utxo2.ReadFrom(bytes.NewBuffer(utxoBytes)) if err != nil { t.Error(err) } if written != read { t.Error("Reading and Writing Utxo: Size Mismatch") } if !reflect.DeepEqual(utxo1, utxo2) { spew.Dump(utxo1, utxo2) t.Error("Utxos do not match.") } truncatedReadBuf := bytes.NewBuffer(utxoBytes) truncatedReadBuf.Truncate(btcwire.HashSize) utxo3 := new(Utxo) n, err := utxo3.ReadFrom(truncatedReadBuf) if err != io.EOF { t.Error("Expected err = io.EOF reading from truncated buffer.") } if n != btcwire.HashSize { t.Error("Incorrect number of bytes read from truncated buffer.") } } func TestUtxoStoreWriteRead(t *testing.T) { store1 := new(UtxoStore) for i := 0; i < 20; i++ { utxo := new(Utxo) for j := range utxo.Out.Hash[:] { utxo.Out.Hash[j] = byte(i + 1) } utxo.Out.Index = uint32(i + 2) utxo.Subscript = []byte{} utxo.Amt = uint64(i + 3) utxo.Height = int64(i + 4) *store1 = append(*store1, utxo) } bufWriter := &bytes.Buffer{} n, err := store1.WriteTo(bufWriter) if err != nil { t.Error(err) } storeBytes := bufWriter.Bytes() store2 := new(UtxoStore) n, err = store2.ReadFrom(bytes.NewBuffer(storeBytes)) if err != nil { t.Error(err) } if int(n) != len(storeBytes) { t.Error("Incorrect number of bytes read.") } if !reflect.DeepEqual(store1, store2) { spew.Dump(store1, store2) t.Error("Stores do not match.") } truncatedLen := 100 truncatedReadBuf := bytes.NewBuffer(storeBytes[:truncatedLen]) store3 := new(UtxoStore) n, err = store3.ReadFrom(truncatedReadBuf) if err != io.EOF { t.Errorf("Expected err = io.EOF reading from truncated buffer, got: %v", err) } if int(n) != truncatedLen { t.Error("Incorrect number of bytes read from truncated buffer.") } } func TestRecvTxWriteRead(t *testing.T) { bufWriter := &bytes.Buffer{} n, err := recvtx.WriteTo(bufWriter) if err != nil { t.Error(err) return } if int(n) != binary.Size(recvtx) { t.Error("Writing Tx: Size Mismatch") return } txBytes := bufWriter.Bytes() tx := new(RecvTx) n, err = tx.ReadFrom(bytes.NewBuffer(txBytes)) if err != nil { t.Error(err) return } if int(n) != binary.Size(tx) { t.Error("Reading Tx: Size Mismatch") return } if !reflect.DeepEqual(recvtx, tx) { t.Error("Txs do not match.") return } truncatedReadBuf := bytes.NewBuffer(txBytes) truncatedReadBuf.Truncate(btcwire.HashSize) n, err = tx.ReadFrom(truncatedReadBuf) if err != io.EOF { t.Error("Expected err = io.EOF reading from truncated buffer.") return } if n != btcwire.HashSize { t.Error("Incorrect number of bytes read from truncated buffer.") return } } func TestSendTxWriteRead(t *testing.T) { bufWriter := &bytes.Buffer{} n1, err := sendtx.WriteTo(bufWriter) if err != nil { t.Error(err) return } txBytes := bufWriter.Bytes() tx := new(SendTx) n2, err := tx.ReadFrom(bytes.NewBuffer(txBytes)) if err != nil { t.Error(err) return } if n1 != n2 { t.Error("Number of bytes written and read mismatch.") return } if !reflect.DeepEqual(sendtx, tx) { t.Error("Txs do not match.") return } truncatedReadBuf := bytes.NewBuffer(txBytes) truncatedReadBuf.Truncate(btcwire.HashSize) n, err := tx.ReadFrom(truncatedReadBuf) if err != io.EOF { t.Error("Expected err = io.EOF reading from truncated buffer.") return } if n != btcwire.HashSize { t.Error("Incorrect number of bytes read from truncated buffer.") return } } func TestTxStoreWriteRead(t *testing.T) { s := []interface{}{recvtx, sendtx} store := TxStore(s) bufWriter := &bytes.Buffer{} n1, err := store.WriteTo(bufWriter) if err != nil { t.Error(err) return } txsBytes := bufWriter.Bytes() txs := TxStore{} n2, err := txs.ReadFrom(bytes.NewBuffer(txsBytes)) if err != nil { t.Error(err) return } if n1 != n2 { t.Error("Number of bytes written and read mismatch.") return } if !reflect.DeepEqual(store, txs) { spew.Dump(store, txs) t.Error("TxStores do not match.") return } truncatedReadBuf := bytes.NewBuffer(txsBytes) truncatedReadBuf.Truncate(50) n, err := txs.ReadFrom(truncatedReadBuf) if err != io.EOF { t.Error("Expected err = io.EOF reading from truncated buffer.") return } if n != 50 { t.Error("Incorrect number of bytes read from truncated buffer.") return } }