diff --git a/app/app.go b/app/app.go index 5aafff04ce..f8cc5b739e 100644 --- a/app/app.go +++ b/app/app.go @@ -37,7 +37,7 @@ func NewBasecoin(eyesCli *eyes.Client) *Basecoin { } } -// For testing, not thread safe! +// XXX For testing, not thread safe! func (app *Basecoin) GetState() *sm.State { return app.state.CacheWrap() } @@ -136,7 +136,7 @@ func (app *Basecoin) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQu // handle special path for account info if reqQuery.Path == "/account" { reqQuery.Path = "/key" - reqQuery.Data = append([]byte("base/a/"), reqQuery.Data...) + reqQuery.Data = sm.AccountKey(reqQuery.Data) } resQuery, err := app.eyesCli.QuerySync(reqQuery) diff --git a/app/app_test.go b/app/app_test.go new file mode 100644 index 0000000000..011d9d7561 --- /dev/null +++ b/app/app_test.go @@ -0,0 +1,182 @@ +package app + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + abci "github.com/tendermint/abci/types" + "github.com/tendermint/basecoin/types" + "github.com/tendermint/go-wire" + eyes "github.com/tendermint/merkleeyes/client" +) + +//-------------------------------------------------------- +// test environment is a list of input and output accounts + +type appTest struct { + t *testing.T + chainID string + app *Basecoin + accIn types.PrivAccount + accOut types.PrivAccount +} + +func newAppTest(t *testing.T) *appTest { + at := &appTest{ + t: t, + chainID: "test_chain_id", + } + at.reset() + return at +} + +// make a tx sending 5mycoin from each accIn to accOut +func (at *appTest) getTx(seq int) *types.SendTx { + tx := types.GetTx(seq, at.accOut, at.accIn) + types.SignTx(at.chainID, tx, at.accIn) + return tx +} + +// set the account on the app through SetOption +func (at *appTest) acc2app(acc types.Account) { + accBytes, err := json.Marshal(acc) + require.Nil(at.t, err) + res := at.app.SetOption("base/account", string(accBytes)) + require.EqualValues(at.t, res, "Success") +} + +// reset the in and out accs to be one account each with 7mycoin +func (at *appTest) reset() { + at.accIn = types.MakeAcc("input0") + at.accOut = types.MakeAcc("output0") + + eyesCli := eyes.NewLocalClient("", 0) + at.app = NewBasecoin(eyesCli) + + res := at.app.SetOption("base/chain_id", at.chainID) + require.EqualValues(at.t, res, "Success") + + at.acc2app(at.accIn.Account) + at.acc2app(at.accOut.Account) + + resabci := at.app.Commit() + require.True(at.t, resabci.IsOK(), resabci) +} + +// returns the final balance and expected balance for input and output accounts +func (at *appTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, inputGot, inputExp, outputGot, outputExpected types.Coins) { + + initBalIn := at.app.GetState().GetAccount(at.accIn.Account.PubKey.Address()).Balance + initBalOut := at.app.GetState().GetAccount(at.accOut.Account.PubKey.Address()).Balance + + txBytes := []byte(wire.BinaryBytes(struct{ types.Tx }{tx})) + if checkTx { + res = at.app.CheckTx(txBytes) + } else { + res = at.app.DeliverTx(txBytes) + } + + endBalIn := at.app.GetState().GetAccount(at.accIn.Account.PubKey.Address()).Balance + endBalOut := at.app.GetState().GetAccount(at.accOut.Account.PubKey.Address()).Balance + decrBalInExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) + return res, endBalIn, initBalIn.Minus(decrBalInExp), endBalOut, initBalOut.Plus(tx.Outputs[0].Coins) +} + +//-------------------------------------------------------- + +func TestSplitKey(t *testing.T) { + assert := assert.New(t) + prefix, suffix := splitKey("foo/bar") + assert.EqualValues("foo", prefix) + assert.EqualValues("bar", suffix) + + prefix, suffix = splitKey("foobar") + assert.EqualValues("foobar", prefix) + assert.EqualValues("", suffix) +} + +func TestSetOption(t *testing.T) { + assert := assert.New(t) + + eyesCli := eyes.NewLocalClient("", 0) + app := NewBasecoin(eyesCli) + + //testing ChainID + chainID := "testChain" + res := app.SetOption("base/chain_id", chainID) + assert.EqualValues(app.GetState().GetChainID(), chainID) + assert.EqualValues(res, "Success") + + accIn := types.MakeAcc("input0") + accsInBytes, err := json.Marshal(accIn.Account) + assert.Nil(err) + res = app.SetOption("base/account", string(accsInBytes)) + assert.EqualValues(res, "Success") + + res = app.SetOption("base/dslfkgjdas", "") + assert.NotEqual(res, "Success") + + res = app.SetOption("dslfkgjdas", "") + assert.NotEqual(res, "Success") + + res = app.SetOption("dslfkgjdas/szfdjzs", "") + assert.NotEqual(res, "Success") +} + +// Test CheckTx and DeliverTx with insufficient and sufficient balance +func TestTx(t *testing.T) { + assert := assert.New(t) + at := newAppTest(t) + + //Bad Balance + at.accIn.Balance = types.Coins{{"mycoin", 2}} + at.acc2app(at.accIn.Account) + res, _, _, _, _ := at.exec(at.getTx(1), true) + assert.True(res.IsErr(), "ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res) + res, inGot, inExp, outGot, outExp := at.exec(at.getTx(1), false) + assert.True(res.IsErr(), "ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res) + assert.False(inGot.IsEqual(inExp), "ExecTx/Bad DeliverTx: shouldn't be equal, inGot: %v, inExp: %v", inGot, inExp) + assert.False(outGot.IsEqual(outExp), "ExecTx/Bad DeliverTx: shouldn't be equal, outGot: %v, outExp: %v", outGot, outExp) + + //Regular CheckTx + at.reset() + res, _, _, _, _ = at.exec(at.getTx(1), true) + assert.True(res.IsOK(), "ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res) + + //Regular DeliverTx + at.reset() + res, inGot, inExp, outGot, outExp = at.exec(at.getTx(1), false) + assert.True(res.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res) + assert.True(inGot.IsEqual(inExp), + "ExecTx/good DeliverTx: unexpected change in input coins, inGot: %v, inExp: %v", inGot, inExp) + assert.True(outGot.IsEqual(outExp), + "ExecTx/good DeliverTx: unexpected change in output coins, outGot: %v, outExp: %v", outGot, outExp) +} + +func TestQuery(t *testing.T) { + assert := assert.New(t) + at := newAppTest(t) + + res, _, _, _, _ := at.exec(at.getTx(1), false) + assert.True(res.IsOK(), "Commit, DeliverTx: Expected OK return from DeliverTx, Error: %v", res) + + resQueryPreCommit := at.app.Query(abci.RequestQuery{ + Path: "/account", + Data: at.accIn.Account.PubKey.Address(), + }) + + res = at.app.Commit() + assert.True(res.IsOK(), res) + + resQueryPostCommit := at.app.Query(abci.RequestQuery{ + Path: "/account", + Data: at.accIn.Account.PubKey.Address(), + }) + fmt.Println(resQueryPreCommit) + fmt.Println(resQueryPostCommit) + assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit") +} diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index b8e4bcf041..338bbcb22b 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -92,11 +92,11 @@ func cmdSendTx(c *cli.Context) error { } //parse the fee and amounts into coin types - feeCoin, err := ParseCoin(fee) + feeCoin, err := types.ParseCoin(fee) if err != nil { return err } - amountCoins, err := ParseCoins(amount) + amountCoins, err := types.ParseCoins(amount) if err != nil { return err } @@ -153,11 +153,11 @@ func AppTx(c *cli.Context, name string, data []byte) error { } //parse the fee and amounts into coin types - feeCoin, err := ParseCoin(fee) + feeCoin, err := types.ParseCoin(fee) if err != nil { return err } - amountCoins, err := ParseCoins(amount) + amountCoins, err := types.ParseCoins(amount) if err != nil { return err } diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 6348ef3cd7..efff67e0bf 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -4,9 +4,6 @@ import ( "encoding/hex" "errors" "os" - "regexp" - "strconv" - "strings" "github.com/urfave/cli" @@ -50,44 +47,6 @@ func StripHex(s string) string { return s } -//regex codes for extracting coins from CLI input -var reDenom = regexp.MustCompile("([^\\d\\W]+)") -var reAmt = regexp.MustCompile("(\\d+)") - -func ParseCoin(str string) (types.Coin, error) { - - var coin types.Coin - - if len(str) > 0 { - amt, err := strconv.Atoi(reAmt.FindString(str)) - if err != nil { - return coin, err - } - denom := reDenom.FindString(str) - coin = types.Coin{denom, int64(amt)} - } - - return coin, nil -} - -func ParseCoins(str string) (types.Coins, error) { - - split := strings.Split(str, ",") - var coins []types.Coin - - for _, el := range split { - if len(el) > 0 { - coin, err := ParseCoin(el) - if err != nil { - return coins, err - } - coins = append(coins, coin) - } - } - - return coins, nil -} - func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) { uriClient := client.NewURIClient(tmAddr) tmResult := new(ctypes.TMResult) diff --git a/cmd/commands/utils_test.go b/cmd/commands/utils_test.go index f16927d486..692fec7433 100644 --- a/cmd/commands/utils_test.go +++ b/cmd/commands/utils_test.go @@ -5,10 +5,10 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/tendermint/basecoin/types" ) func TestHex(t *testing.T) { + assert := assert.New(t) //test isHex hexNoPrefix := hex.EncodeToString([]byte("foobar")) @@ -16,65 +16,9 @@ func TestHex(t *testing.T) { str := "foobar" strWPrefix := "0xfoobar" - //define the list of coin tests - var testList = []struct { - testPass bool - errMsg string - }{ - {isHex(hexWPrefix), "isHex not identifying hex with 0x prefix"}, - {!isHex(hexNoPrefix), "isHex shouldn't identify hex without 0x prefix"}, - {!isHex(str), "isHex shouldn't identify non-hex string"}, - {!isHex(strWPrefix), "isHex shouldn't identify non-hex string with 0x prefix"}, - {StripHex(hexWPrefix) == hexNoPrefix, "StripHex doesn't remove first two characters"}, - } - - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass, tl.errMsg) - } - -} - -//Test the parse coin and parse coins functionality -func TestParse(t *testing.T) { - - makeCoin := func(str string) types.Coin { - coin, err := ParseCoin(str) - if err != nil { - panic(err.Error()) - } - return coin - } - - makeCoins := func(str string) types.Coins { - coin, err := ParseCoins(str) - if err != nil { - panic(err.Error()) - } - return coin - } - - //define the list of coin tests - var testList = []struct { - testPass bool - errMsg string - }{ - //testing ParseCoin Function - {types.Coin{} == makeCoin(""), "parseCoin makes bad empty coin"}, - {types.Coin{"fooCoin", 1} == makeCoin("1fooCoin"), "parseCoin makes bad coins"}, - {types.Coin{"barCoin", 10} == makeCoin("10 barCoin"), "parseCoin makes bad coins"}, - - //testing ParseCoins Function - {types.Coins{{"fooCoin", 1}}.IsEqual(makeCoins("1fooCoin")), - "parseCoins doesn't parse a single coin"}, - {types.Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99barCoin,1fooCoin")), - "parseCoins doesn't properly parse two coins"}, - {types.Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99 barCoin, 1 fooCoin")), - "parseCoins doesn't properly parse two coins which use spaces"}, - } - - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass, tl.errMsg) - } + assert.True(isHex(hexWPrefix), "isHex not identifying hex with 0x prefix") + assert.False(isHex(hexNoPrefix), "isHex shouldn't identify hex without 0x prefix") + assert.False(isHex(str), "isHex shouldn't identify non-hex string") + assert.False(isHex(strWPrefix), "isHex shouldn't identify non-hex string with 0x prefix") + assert.True(StripHex(hexWPrefix) == hexNoPrefix, "StripHex doesn't remove first two characters") } diff --git a/glide.lock b/glide.lock index ccb7c25322..6d411f59ae 100644 --- a/glide.lock +++ b/glide.lock @@ -156,11 +156,11 @@ imports: - transport testImports: - name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + version: 346938d642f2ec3594ed81d874461961cd0faa76 subpackages: - spew - name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + version: 792786c7400a136282c1664665ae0a8db921c6c2 subpackages: - difflib - name: github.com/stretchr/testify diff --git a/plugins/counter/counter_test.go b/plugins/counter/counter_test.go index 9c76544bc5..f7c658a9af 100644 --- a/plugins/counter/counter_test.go +++ b/plugins/counter/counter_test.go @@ -15,6 +15,7 @@ import ( ) func TestCounterPlugin(t *testing.T) { + assert := assert.New(t) // Basecoin initialization eyesCli := eyescli.NewLocalClient("", 0) @@ -64,39 +65,40 @@ func TestCounterPlugin(t *testing.T) { // Test a basic send, no fee res := DeliverCounterTx(0, types.Coin{}, types.Coins{{"", 1}}, 1, types.Coins{}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test fee prevented transaction res = DeliverCounterTx(0, types.Coin{"", 2}, types.Coins{{"", 1}}, 2, types.Coins{}) - assert.True(t, res.IsErr(), res.String()) + assert.True(res.IsErr(), res.String()) // Test input equals fee res = DeliverCounterTx(0, types.Coin{"", 2}, types.Coins{{"", 2}}, 2, types.Coins{}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test more input than fee res = DeliverCounterTx(0, types.Coin{"", 2}, types.Coins{{"", 3}}, 3, types.Coins{}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test input equals fee+appFee res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 3}, {"gold", 1}}, 4, types.Coins{{"", 2}, {"gold", 1}}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test fee+appFee prevented transaction, not enough "" res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 2}, {"gold", 1}}, 5, types.Coins{{"", 2}, {"gold", 1}}) - assert.True(t, res.IsErr(), res.String()) + assert.True(res.IsErr(), res.String()) // Test fee+appFee prevented transaction, not enough "gold" res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 3}, {"gold", 1}}, 5, types.Coins{{"", 2}, {"gold", 2}}) - assert.True(t, res.IsErr(), res.String()) + assert.True(res.IsErr(), res.String()) // Test more input than fee, more "" res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 4}, {"gold", 1}}, 6, types.Coins{{"", 2}, {"gold", 1}}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test more input than fee, more "gold" res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 3}, {"gold", 2}}, 7, types.Coins{{"", 2}, {"gold", 1}}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) + + // REF: DeliverCounterTx(gas, fee, inputCoins, inputSequence, appFee) {w - // REF: DeliverCounterTx(gas, fee, inputCoins, inputSequence, appFee) { } diff --git a/plugins/ibc/ibc_test.go b/plugins/ibc/ibc_test.go index 0f2ab88540..9439f43784 100644 --- a/plugins/ibc/ibc_test.go +++ b/plugins/ibc/ibc_test.go @@ -65,6 +65,7 @@ func (pas PrivAccountsByAddress) Swap(i, j int) { //-------------------------------------------------------------------------------- func TestIBCPlugin(t *testing.T) { + assert := assert.New(t) eyesClient := eyes.NewLocalClient("", 0) store := types.NewKVCache(eyesClient) @@ -88,7 +89,7 @@ func TestIBCPlugin(t *testing.T) { Genesis: "", }, }})) - assert.Equal(t, IBCCodeEncodingError, res.Code) + assert.Equal(IBCCodeEncodingError, res.Code) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -99,7 +100,7 @@ func TestIBCPlugin(t *testing.T) { Genesis: string(genDocJSON_1), }, }})) - assert.True(t, res.IsOK(), res.Log) + assert.True(res.IsOK(), res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -110,7 +111,7 @@ func TestIBCPlugin(t *testing.T) { Genesis: string(genDocJSON_1), }, }})) - assert.Equal(t, IBCCodeChainAlreadyExists, res.Code, res.Log) + assert.Equal(IBCCodeChainAlreadyExists, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -125,7 +126,7 @@ func TestIBCPlugin(t *testing.T) { res = ibcPlugin.RunTx(store, ctx, wire.BinaryBytes(struct{ IBCTx }{IBCPacketCreateTx{ Packet: packet, }})) - assert.Equal(t, abci.CodeType_OK, res.Code, res.Log) + assert.Equal(abci.CodeType_OK, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -133,7 +134,7 @@ func TestIBCPlugin(t *testing.T) { res = ibcPlugin.RunTx(store, ctx, wire.BinaryBytes(struct{ IBCTx }{IBCPacketCreateTx{ Packet: packet, }})) - assert.Equal(t, IBCCodePacketAlreadyExists, res.Code, res.Log) + assert.Equal(IBCCodePacketAlreadyExists, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -175,7 +176,7 @@ func TestIBCPlugin(t *testing.T) { Header: header, Commit: commit, }})) - assert.Equal(t, abci.CodeType_OK, res.Code, res.Log) + assert.Equal(abci.CodeType_OK, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -190,10 +191,10 @@ func TestIBCPlugin(t *testing.T) { Data: packetKey, Prove: true, }) - assert.Nil(t, err) + assert.Nil(err) var proof *merkle.IAVLProof err = wire.ReadBinaryBytes(resQuery.Proof, &proof) - assert.Nil(t, err) + assert.Nil(err) // Post a packet res = ibcPlugin.RunTx(store, ctx, wire.BinaryBytes(struct{ IBCTx }{IBCPacketPostTx{ @@ -202,12 +203,13 @@ func TestIBCPlugin(t *testing.T) { Packet: packet, Proof: proof, }})) - assert.Equal(t, abci.CodeType_OK, res.Code, res.Log) + assert.Equal(abci.CodeType_OK, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() } func TestIBCPluginBadCommit(t *testing.T) { + assert := assert.New(t) eyesClient := eyes.NewLocalClient("", 0) store := types.NewKVCache(eyesClient) @@ -231,7 +233,7 @@ func TestIBCPluginBadCommit(t *testing.T) { Genesis: string(genDocJSON_1), }, }})) - assert.True(t, res.IsOK(), res.Log) + assert.True(res.IsOK(), res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -273,13 +275,14 @@ func TestIBCPluginBadCommit(t *testing.T) { Header: header, Commit: commit, }})) - assert.Equal(t, IBCCodeInvalidCommit, res.Code, res.Log) + assert.Equal(IBCCodeInvalidCommit, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() } func TestIBCPluginBadProof(t *testing.T) { + assert := assert.New(t) eyesClient := eyes.NewLocalClient("", 0) store := types.NewKVCache(eyesClient) @@ -303,7 +306,7 @@ func TestIBCPluginBadProof(t *testing.T) { Genesis: string(genDocJSON_1), }, }})) - assert.True(t, res.IsOK(), res.Log) + assert.True(res.IsOK(), res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -318,7 +321,7 @@ func TestIBCPluginBadProof(t *testing.T) { res = ibcPlugin.RunTx(store, ctx, wire.BinaryBytes(struct{ IBCTx }{IBCPacketCreateTx{ Packet: packet, }})) - assert.Equal(t, abci.CodeType_OK, res.Code, res.Log) + assert.Equal(abci.CodeType_OK, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -360,7 +363,7 @@ func TestIBCPluginBadProof(t *testing.T) { Header: header, Commit: commit, }})) - assert.Equal(t, abci.CodeType_OK, res.Code, res.Log) + assert.Equal(abci.CodeType_OK, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -375,10 +378,10 @@ func TestIBCPluginBadProof(t *testing.T) { Data: packetKey, Prove: true, }) - assert.Nil(t, err) + assert.Nil(err) var proof *merkle.IAVLProof err = wire.ReadBinaryBytes(resQuery.Proof, &proof) - assert.Nil(t, err) + assert.Nil(err) // Mutate the proof proof.InnerNodes[0].Height += 1 @@ -390,7 +393,7 @@ func TestIBCPluginBadProof(t *testing.T) { Packet: packet, Proof: proof, }})) - assert.Equal(t, IBCCodeInvalidProof, res.Code, res.Log) + assert.Equal(IBCCodeInvalidProof, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() } diff --git a/scripts/print_test_account.go b/scripts/print_test_account.go index 11998c6639..12e4bd005f 100644 --- a/scripts/print_test_account.go +++ b/scripts/print_test_account.go @@ -15,8 +15,8 @@ Address: D9B727742AA29FA638DC63D70813C976014C4CE0 */ func main() { tAcc := tests.PrivAccountFromSecret("test") - fmt.Println("PrivKey:", fmt.Sprintf("%X", tAcc.PrivKey.Bytes())) - fmt.Println("PubKey:", fmt.Sprintf("%X", tAcc.Account.PubKey.Bytes())) - fmt.Println("Address:", fmt.Sprintf("%X", tAcc.Account.PubKey.Address())) + fmt.Printf("PrivKey:%X\n", tAcc.PrivKey.Bytes()) + fmt.Printf("PubKey:%X\n", tAcc.Account.PubKey.Bytes()) + fmt.Printf("Address:%X\n", tAcc.Account.PubKey.Address()) fmt.Println(string(wire.JSONBytesPretty(tAcc))) } diff --git a/state/execution_test.go b/state/execution_test.go new file mode 100644 index 0000000000..249380b9fe --- /dev/null +++ b/state/execution_test.go @@ -0,0 +1,312 @@ +package state + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + abci "github.com/tendermint/abci/types" + "github.com/tendermint/basecoin/types" +) + +//-------------------------------------------------------- +// test environment is a bunch of lists of accountns + +type execTest struct { + chainID string + store types.KVStore + state *State + accIn types.PrivAccount + accOut types.PrivAccount +} + +func newExecTest() *execTest { + et := &execTest{ + chainID: "test_chain_id", + } + et.reset() + return et +} + +func (et *execTest) signTx(tx *types.SendTx, accsIn ...types.PrivAccount) { + types.SignTx(et.chainID, tx, accsIn...) +} + +// make tx from accsIn to et.accOut +func (et *execTest) getTx(seq int, accOut types.PrivAccount, accsIn ...types.PrivAccount) *types.SendTx { + return types.GetTx(seq, accOut, accsIn...) +} + +// returns the final balance and expected balance for input and output accounts +func (et *execTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, inGot, inExp, outGot, outExp types.Coins) { + initBalIn := et.state.GetAccount(et.accIn.Account.PubKey.Address()).Balance + initBalOut := et.state.GetAccount(et.accOut.Account.PubKey.Address()).Balance + + res = ExecTx(et.state, nil, tx, checkTx, nil) + + endBalIn := et.state.GetAccount(et.accIn.Account.PubKey.Address()).Balance + endBalOut := et.state.GetAccount(et.accOut.Account.PubKey.Address()).Balance + decrBalInExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) //expected decrease in balance In + return res, endBalIn, initBalIn.Minus(decrBalInExp), endBalOut, initBalOut.Plus(tx.Outputs[0].Coins) +} + +func (et *execTest) acc2State(accs ...types.PrivAccount) { + for _, acc := range accs { + et.state.SetAccount(acc.Account.PubKey.Address(), &acc.Account) + } +} + +//reset everything. state is empty +func (et *execTest) reset() { + et.accIn = types.MakeAcc("foo") + et.accOut = types.MakeAcc("bar") + + et.store = types.NewMemKVStore() + et.state = NewState(et.store) + et.state.SetChainID(et.chainID) + + // NOTE we dont run acc2State here + // so we can test non-existing accounts + +} + +//-------------------------------------------------------- + +func TestGetInputs(t *testing.T) { + assert := assert.New(t) + et := newExecTest() + + //nil submissions + acc, res := getInputs(nil, nil) + assert.True(res.IsOK(), "getInputs: error on nil submission") + assert.Zero(len(acc), "getInputs: accounts returned on nil submission") + + //test getInputs for registered, non-registered account + et.reset() + txs := types.Accs2TxInputs(1, et.accIn) + acc, res = getInputs(et.state, txs) + assert.True(res.IsErr(), "getInputs: expected error when using getInput with non-registered Input") + + et.acc2State(et.accIn) + acc, res = getInputs(et.state, txs) + assert.True(res.IsOK(), "getInputs: expected to getInput from registered Input") + + //test sending duplicate accounts + et.reset() + et.acc2State(et.accIn, et.accIn, et.accIn) + txs = types.Accs2TxInputs(1, et.accIn, et.accIn, et.accIn) + acc, res = getInputs(et.state, txs) + assert.True(res.IsErr(), "getInputs: expected error when sending duplicate accounts") +} + +func TestGetOrMakeOutputs(t *testing.T) { + assert := assert.New(t) + et := newExecTest() + + //nil submissions + acc, res := getOrMakeOutputs(nil, nil, nil) + assert.True(res.IsOK(), "getOrMakeOutputs: error on nil submission") + assert.Zero(len(acc), "getOrMakeOutputs: accounts returned on nil submission") + + //test sending duplicate accounts + et.reset() + txs := types.Accs2TxOutputs(et.accIn, et.accIn, et.accIn) + _, res = getOrMakeOutputs(et.state, nil, txs) + assert.True(res.IsErr(), "getOrMakeOutputs: expected error when sending duplicate accounts") + + //test sending to existing/new account + et.reset() + txs1 := types.Accs2TxOutputs(et.accIn) + txs2 := types.Accs2TxOutputs(et.accOut) + + et.acc2State(et.accIn) + _, res = getOrMakeOutputs(et.state, nil, txs1) + assert.True(res.IsOK(), "getOrMakeOutputs: error when sending to existing account") + + mapRes2, res := getOrMakeOutputs(et.state, nil, txs2) + assert.True(res.IsOK(), "getOrMakeOutputs: error when sending to new account") + + //test the map results + _, map2ok := mapRes2[string(txs2[0].Address)] + assert.True(map2ok, "getOrMakeOutputs: account output does not contain new account map item") + +} + +func TestValidateInputsBasic(t *testing.T) { + assert := assert.New(t) + et := newExecTest() + + //validate input basic + txs := types.Accs2TxInputs(1, et.accIn) + res := validateInputsBasic(txs) + assert.True(res.IsOK(), "validateInputsBasic: expected no error on good tx input. Error: %v", res.Error()) + + txs[0].Coins[0].Amount = 0 + res = validateInputsBasic(txs) + assert.True(res.IsErr(), "validateInputsBasic: expected error on bad tx input") + +} + +func TestValidateInputsAdvanced(t *testing.T) { + assert := assert.New(t) + et := newExecTest() + + //create three temp accounts for the test + accIn1 := types.MakeAcc("foox") + accIn2 := types.MakeAcc("fooy") + accIn3 := types.MakeAcc("fooz") + + //validate inputs advanced + txs := et.getTx(1, et.accOut, accIn1, accIn2, accIn3) + + et.acc2State(accIn1, accIn2, accIn3, et.accOut) + accMap, res := getInputs(et.state, txs.Inputs) + assert.True(res.IsOK(), "validateInputsAdvanced: error retrieving accMap. Error: %v", res.Error()) + signBytes := txs.SignBytes(et.chainID) + + //test bad case, unsigned + totalCoins, res := validateInputsAdvanced(accMap, signBytes, txs.Inputs) + assert.True(res.IsErr(), "validateInputsAdvanced: expected an error on an unsigned tx input") + + //test good case sgined + et.signTx(txs, accIn1, accIn2, accIn3, et.accOut) + totalCoins, res = validateInputsAdvanced(accMap, signBytes, txs.Inputs) + assert.True(res.IsOK(), "validateInputsAdvanced: expected no error on good tx input. Error: %v", res.Error()) + + txsTotalCoins := txs.Inputs[0].Coins. + Plus(txs.Inputs[1].Coins). + Plus(txs.Inputs[2].Coins) + + assert.True(totalCoins.IsEqual(txsTotalCoins), + "ValidateInputsAdvanced: transaction total coins are not equal: got %v, expected %v", txsTotalCoins, totalCoins) +} + +func TestValidateInputAdvanced(t *testing.T) { + assert := assert.New(t) + et := newExecTest() + + //validate input advanced + txs := et.getTx(1, et.accOut, et.accIn) + + et.acc2State(et.accIn, et.accOut) + signBytes := txs.SignBytes(et.chainID) + + //unsigned case + res := validateInputAdvanced(&et.accIn.Account, signBytes, txs.Inputs[0]) + assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input without signature") + + //good signed case + et.signTx(txs, et.accIn, et.accOut) + res = validateInputAdvanced(&et.accIn.Account, signBytes, txs.Inputs[0]) + assert.True(res.IsOK(), "validateInputAdvanced: expected no error on good tx input. Error: %v", res.Error()) + + //bad sequence case + et.accIn.Sequence = 1 + et.signTx(txs, et.accIn, et.accOut) + res = validateInputAdvanced(&et.accIn.Account, signBytes, txs.Inputs[0]) + assert.Equal(abci.CodeType_BaseInvalidSequence, res.Code, "validateInputAdvanced: expected error on tx input with bad sequence") + et.accIn.Sequence = 0 //restore sequence + + //bad balance case + et.accIn.Balance = types.Coins{{"mycoin", 2}} + et.signTx(txs, et.accIn, et.accOut) + res = validateInputAdvanced(&et.accIn.Account, signBytes, txs.Inputs[0]) + assert.Equal(abci.CodeType_BaseInsufficientFunds, res.Code, + "validateInputAdvanced: expected error on tx input with insufficient funds %v", et.accIn.Sequence) +} + +func TestValidateOutputsAdvanced(t *testing.T) { + assert := assert.New(t) + et := newExecTest() + + //validateOutputsBasic + txs := types.Accs2TxOutputs(et.accIn) + res := validateOutputsBasic(txs) + assert.True(res.IsOK(), "validateOutputsBasic: expected no error on good tx output. Error: %v", res.Error()) + + txs[0].Coins[0].Amount = 0 + res = validateOutputsBasic(txs) + assert.True(res.IsErr(), "validateInputBasic: expected error on bad tx output. Error: %v", res.Error()) +} + +func TestSumOutput(t *testing.T) { + assert := assert.New(t) + et := newExecTest() + + //SumOutput + txs := types.Accs2TxOutputs(et.accIn, et.accOut) + total := sumOutputs(txs) + assert.True(total.IsEqual(txs[0].Coins.Plus(txs[1].Coins)), "sumOutputs: total coins are not equal") +} + +func TestAdjustBy(t *testing.T) { + assert := assert.New(t) + et := newExecTest() + + //adjustByInputs/adjustByOutputs + //sending transaction from accIn to accOut + initBalIn := et.accIn.Account.Balance + initBalOut := et.accOut.Account.Balance + et.acc2State(et.accIn, et.accOut) + + txIn := types.Accs2TxInputs(1, et.accIn) + txOut := types.Accs2TxOutputs(et.accOut) + accMap, _ := getInputs(et.state, txIn) + accMap, _ = getOrMakeOutputs(et.state, accMap, txOut) + + adjustByInputs(et.state, accMap, txIn) + adjustByOutputs(et.state, accMap, txOut, false) + + endBalIn := accMap[string(et.accIn.Account.PubKey.Address())].Balance + endBalOut := accMap[string(et.accOut.Account.PubKey.Address())].Balance + decrBalIn := initBalIn.Minus(endBalIn) + incrBalOut := endBalOut.Minus(initBalOut) + + assert.True(decrBalIn.IsEqual(txIn[0].Coins), + "adjustByInputs: total coins are not equal. diff: %v, tx: %v", decrBalIn.String(), txIn[0].Coins.String()) + assert.True(incrBalOut.IsEqual(txOut[0].Coins), + "adjustByInputs: total coins are not equal. diff: %v, tx: %v", incrBalOut.String(), txOut[0].Coins.String()) + +} + +func TestExecTx(t *testing.T) { + assert := assert.New(t) + et := newExecTest() + + //ExecTx + txs := et.getTx(1, et.accOut, et.accIn) + et.acc2State(et.accIn) + et.acc2State(et.accOut) + et.signTx(txs, et.accIn) + + //Bad Balance + et.accIn.Balance = types.Coins{{"mycoin", 2}} + et.acc2State(et.accIn) + res, _, _, _, _ := et.exec(txs, true) + assert.True(res.IsErr(), "ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res) + + res, balIn, balInExp, balOut, balOutExp := et.exec(txs, false) + assert.True(res.IsErr(), "ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res) + assert.False(balIn.IsEqual(balInExp), + "ExecTx/Bad DeliverTx: balance shouldn't be equal for accIn: got %v, expected: %v", balIn, balInExp) + assert.False(balOut.IsEqual(balOutExp), + "ExecTx/Bad DeliverTx: balance shouldn't be equal for accOut: got %v, expected: %v", balOut, balOutExp) + + //Regular CheckTx + et.reset() + et.acc2State(et.accIn) + et.acc2State(et.accOut) + res, _, _, _, _ = et.exec(txs, true) + assert.True(res.IsOK(), "ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res) + + //Regular DeliverTx + et.reset() + et.acc2State(et.accIn) + et.acc2State(et.accOut) + res, balIn, balInExp, balOut, balOutExp = et.exec(txs, false) + assert.True(res.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res) + assert.True(balIn.IsEqual(balInExp), + "ExecTx/good DeliverTx: unexpected change in input balance, got: %v, expected: %v", balIn, balInExp) + assert.True(balOut.IsEqual(balOutExp), + "ExecTx/good DeliverTx: unexpected change in output balance, got: %v, expected: %v", balOut, balOutExp) +} diff --git a/state/state_test.go b/state/state_test.go index 8c74162195..1d35f2c4f6 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -11,6 +11,7 @@ import ( ) func TestState(t *testing.T) { + assert := assert.New(t) //States and Stores for tests store := types.NewMemKVStore() @@ -63,44 +64,33 @@ func TestState(t *testing.T) { return true } - //define the test list - testList := []struct { - testPass func() bool - errMsg string - }{ - //test chainID - {func() bool { state.SetChainID("testchain"); return state.GetChainID() == "testchain" }, - "ChainID is improperly stored"}, + //test chainID + state.SetChainID("testchain") + assert.Equal(state.GetChainID(), "testchain", "ChainID is improperly stored") - //test basic retrieve - {func() bool { setRecords(state); return storeHasAll(state) }, - "state doesn't retrieve after Set"}, + //test basic retrieve + setRecords(state) + assert.True(storeHasAll(state), "state doesn't retrieve after Set") - // Test account retrieve - {func() bool { state.SetAccount(dumAddr, acc); return state.GetAccount(dumAddr).Sequence == 1 }, - "GetAccount not retrieving"}, + // Test account retrieve + state.SetAccount(dumAddr, acc) + assert.Equal(state.GetAccount(dumAddr).Sequence, 1, "GetAccount not retrieving") - //Test CacheWrap with local mem store - {func() bool { reset(); setRecords(cache); return !storeHasAll(store) }, - "store retrieving before CacheSync"}, - {func() bool { cache.CacheSync(); return storeHasAll(store) }, - "store doesn't retrieve after CacheSync"}, + //Test CacheWrap with local mem store + reset() + setRecords(cache) + assert.False(storeHasAll(store), "store retrieving before CacheSync") + cache.CacheSync() + assert.True(storeHasAll(store), "store doesn't retrieve after CacheSync") - //Test Commit on state with non-merkle store - {func() bool { return !state.Commit().IsOK() }, - "Commit shouldn't work with non-merkle store"}, + //Test Commit on state with non-merkle store + assert.True(state.Commit().IsErr(), "Commit shouldn't work with non-merkle store") - //Test CacheWrap with merkleeyes client store - {func() bool { useEyesCli(); setRecords(cache); return !storeHasAll(eyesCli) }, - "eyesCli retrieving before Commit"}, - {func() bool { cache.CacheSync(); return state.Commit().IsOK() }, - "Bad Commit"}, - {func() bool { return storeHasAll(eyesCli) }, - "eyesCli doesn't retrieve after Commit"}, - } - - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass(), tl.errMsg) - } + //Test CacheWrap with merkleeyes client store + useEyesCli() + setRecords(cache) + assert.False(storeHasAll(eyesCli), "eyesCli retrieving before Commit") + cache.CacheSync() + assert.True(state.Commit().IsOK(), "Bad Commit") + assert.True(storeHasAll(eyesCli), "eyesCli doesn't retrieve after Commit") } diff --git a/tests/tmsp/tmsp_test.go b/tests/tmsp/tmsp_test.go index eec105deda..86b4bfbf24 100644 --- a/tests/tmsp/tmsp_test.go +++ b/tests/tmsp/tmsp_test.go @@ -57,7 +57,7 @@ func TestSendTx(t *testing.T) { txBytes := wire.BinaryBytes(types.TxS{tx}) res := bcApp.DeliverTx(txBytes) // t.Log(res) - assert.False(t, res.IsErr(), "Failed: %v", res.Error()) + assert.True(t, res.IsOK(), "Failed: %v", res.Error()) } func TestSequence(t *testing.T) { @@ -108,11 +108,11 @@ func TestSequence(t *testing.T) { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) res := bcApp.DeliverTx(txBytes) - assert.False(t, res.IsErr(), "DeliverTx error: %v", res.Error()) + assert.True(t, res.IsOK(), "DeliverTx error: %v", res.Error()) } res := bcApp.Commit() - assert.False(t, res.IsErr(), "Failed Commit: %v", res.Error()) + assert.True(t, res.IsOK(), "Failed Commit: %v", res.Error()) t.Log("-------------------- RANDOM SENDS --------------------") @@ -152,6 +152,6 @@ func TestSequence(t *testing.T) { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) res := bcApp.DeliverTx(txBytes) - assert.False(t, res.IsErr(), "DeliverTx error: %v", res.Error()) + assert.True(t, res.IsOK(), "DeliverTx error: %v", res.Error()) } } diff --git a/types/account_test.go b/types/account_test.go index 5a9118f1df..6bcb997d87 100644 --- a/types/account_test.go +++ b/types/account_test.go @@ -12,8 +12,9 @@ func TestNilAccount(t *testing.T) { //test Copy accCopy := acc.Copy() - assert.True(t, &acc != accCopy, "Account Copy Error") - assert.True(t, acc.Sequence == accCopy.Sequence) + //note that the assert.True is used instead of assert.Equal because looking at pointers + assert.True(t, &acc != accCopy, "Account Copy Error, acc1: %v, acc2: %v", &acc, accCopy) + assert.Equal(t, acc.Sequence, accCopy.Sequence) //test sending nils for panic var nilAcc *Account diff --git a/types/coin.go b/types/coin.go index 90b2f30c0f..e34f7d1bdb 100644 --- a/types/coin.go +++ b/types/coin.go @@ -2,6 +2,8 @@ package types import ( "fmt" + "regexp" + "strconv" "strings" ) @@ -11,14 +13,63 @@ type Coin struct { } func (coin Coin) String() string { - return fmt.Sprintf("(%v %v)", - coin.Denom, coin.Amount) + return fmt.Sprintf("%v%v", coin.Amount, coin.Denom) +} + +//regex codes for extracting coins from string +var reDenom = regexp.MustCompile("([^\\d\\W]+)") +var reAmt = regexp.MustCompile("(\\d+)") + +func ParseCoin(str string) (Coin, error) { + + var coin Coin + + if len(str) > 0 { + amt, err := strconv.Atoi(reAmt.FindString(str)) + if err != nil { + return coin, err + } + denom := reDenom.FindString(str) + coin = Coin{denom, int64(amt)} + } + + return coin, nil } //---------------------------------------- type Coins []Coin +func (coins Coins) String() string { + if len(coins) == 0 { + return "" + } + + out := "" + for _, coin := range coins { + out += fmt.Sprintf("%v,", coin.String()) + } + return out[:len(out)-1] +} + +func ParseCoins(str string) (Coins, error) { + + split := strings.Split(str, ",") + var coins []Coin + + for _, el := range split { + if len(el) > 0 { + coin, err := ParseCoin(el) + if err != nil { + return coins, err + } + coins = append(coins, coin) + } + } + + return coins, nil +} + // Must be sorted, and not have 0 amounts func (coins Coins) IsValid() bool { switch len(coins) { diff --git a/types/coin_test.go b/types/coin_test.go index 36767ae6b9..8cbc708a49 100644 --- a/types/coin_test.go +++ b/types/coin_test.go @@ -3,12 +3,12 @@ package types import ( "testing" - cmn "github.com/tendermint/go-common" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestCoins(t *testing.T) { + assert := assert.New(t) //Define the coins to be used in tests good := Coins{ @@ -42,24 +42,44 @@ func TestCoins(t *testing.T) { Coin{"MINERAL", 1}, } - //define the list of coin tests - var testList = []struct { - testPass bool - errMsg string - }{ - {good.IsValid(), "Coins are valid"}, - {good.IsPositive(), cmn.Fmt("Expected coins to be positive: %v", good)}, - {good.IsGTE(empty), cmn.Fmt("Expected %v to be >= %v", good, empty)}, - {!neg.IsPositive(), cmn.Fmt("Expected neg coins to not be positive: %v", neg)}, - {len(sum) == 0, "Expected 0 coins"}, - {!badSort1.IsValid(), "Coins are not sorted"}, - {!badSort2.IsValid(), "Coins are not sorted"}, - {!badAmt.IsValid(), "Coins cannot include 0 amounts"}, - {!dup.IsValid(), "Duplicate coin"}, + assert.True(good.IsValid(), "Coins are valid") + assert.True(good.IsPositive(), "Expected coins to be positive: %v", good) + assert.True(good.IsGTE(empty), "Expected %v to be >= %v", good, empty) + assert.False(neg.IsPositive(), "Expected neg coins to not be positive: %v", neg) + assert.Zero(len(sum), "Expected 0 coins") + assert.False(badSort1.IsValid(), "Coins are not sorted") + assert.False(badSort2.IsValid(), "Coins are not sorted") + assert.False(badAmt.IsValid(), "Coins cannot include 0 amounts") + assert.False(dup.IsValid(), "Duplicate coin") + +} + +//Test the parse coin and parse coins functionality +func TestParse(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + makeCoin := func(str string) Coin { + coin, err := ParseCoin(str) + require.Nil(err) + return coin } - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass, tl.errMsg) + makeCoins := func(str string) Coins { + coin, err := ParseCoins(str) + require.Nil(err) + return coin } + + //testing ParseCoin Function + assert.Equal(Coin{}, makeCoin(""), "ParseCoin makes bad empty coin") + assert.Equal(Coin{"fooCoin", 1}, makeCoin("1fooCoin"), "ParseCoin makes bad coins") + assert.Equal(Coin{"barCoin", 10}, makeCoin("10 barCoin"), "ParseCoin makes bad coins") + + //testing ParseCoins Function + assert.True(Coins{{"fooCoin", 1}}.IsEqual(makeCoins("1fooCoin")), + "ParseCoins doesn't parse a single coin") + assert.True(Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99barCoin,1fooCoin")), + "ParseCoins doesn't properly parse two coins") + assert.True(Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99 barCoin, 1 fooCoin")), + "ParseCoins doesn't properly parse two coins which use spaces") } diff --git a/types/kvstore_test.go b/types/kvstore_test.go index 76ba009f30..0b4afc7328 100644 --- a/types/kvstore_test.go +++ b/types/kvstore_test.go @@ -8,6 +8,7 @@ import ( ) func TestKVStore(t *testing.T) { + assert := assert.New(t) //stores to be tested ms := NewMemKVStore() @@ -40,40 +41,30 @@ func TestKVStore(t *testing.T) { return true } - //define the test list - var testList = []struct { - testPass func() bool - errMsg string - }{ - //test read/write for MemKVStore - {func() bool { setRecords(ms); return storeHasAll(ms) }, - "MemKVStore doesn't retrieve after Set"}, + //test read/write for MemKVStore + setRecords(ms) + assert.True(storeHasAll(ms), "MemKVStore doesn't retrieve after Set") - //test read/write for KVCache - {func() bool { setRecords(kvc); return storeHasAll(kvc) }, - "KVCache doesn't retrieve after Set"}, + //test read/write for KVCache + setRecords(kvc) + assert.True(storeHasAll(kvc), "KVCache doesn't retrieve after Set") - //test reset - {func() bool { kvc.Reset(); return !storeHasAll(kvc) }, - "KVCache retrieving after reset"}, + //test reset + kvc.Reset() + assert.False(storeHasAll(kvc), "KVCache retrieving after reset") - //test sync - {func() bool { setRecords(kvc); return !storeHasAll(store) }, - "store retrieving before synced"}, - {func() bool { kvc.Sync(); return storeHasAll(store) }, - "store isn't retrieving after synced"}, + //test sync + setRecords(kvc) + assert.False(storeHasAll(store), "store retrieving before synced") + kvc.Sync() + assert.True(storeHasAll(store), "store isn't retrieving after synced") - //test logging - {func() bool { return len(kvc.GetLogLines()) == 0 }, - "logging events existed before using SetLogging"}, - {func() bool { kvc.SetLogging(); setRecords(kvc); return len(kvc.GetLogLines()) == 2 }, - "incorrect number of logging events recorded"}, - {func() bool { kvc.ClearLogLines(); return len(kvc.GetLogLines()) == 0 }, - "logging events still exists after ClearLogLines"}, - } + //test logging + assert.Zero(len(kvc.GetLogLines()), "logging events existed before using SetLogging") + kvc.SetLogging() + setRecords(kvc) + assert.Equal(len(kvc.GetLogLines()), 2, "incorrect number of logging events recorded") + kvc.ClearLogLines() + assert.Zero(len(kvc.GetLogLines()), "logging events still exists after ClearLogLines") - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass(), tl.errMsg) - } } diff --git a/types/plugin_test.go b/types/plugin_test.go index 9f4b332d0c..071ed29741 100644 --- a/types/plugin_test.go +++ b/types/plugin_test.go @@ -32,25 +32,10 @@ func (d *Dummy) EndBlock(store KVStore, height uint64) (res abci.ResponseEndBloc //---------------------------------- func TestPlugin(t *testing.T) { - + assert := assert.New(t) plugins := NewPlugins() - - //define the test list - var testList = []struct { - testPass func() bool - errMsg string - }{ - {func() bool { return (len(plugins.GetList()) == 0) }, - "plugins object init with a objects"}, - {func() bool { plugins.RegisterPlugin(&Dummy{}); return (len(plugins.GetList()) == 1) }, - "plugin wasn't added to plist after registered"}, - {func() bool { return (plugins.GetByName("dummy").Name() == "dummy") }, - "plugin wasn't retrieved properly with GetByName"}, - } - - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass(), tl.errMsg) - } - + assert.Zero(len(plugins.GetList()), "plugins object init with a objects") + plugins.RegisterPlugin(&Dummy{}) + assert.Equal(len(plugins.GetList()), 1, "plugin wasn't added to plist after registered") + assert.Equal(plugins.GetByName("dummy").Name(), "dummy", "plugin wasn't retrieved properly with GetByName") } diff --git a/types/test_helpers.go b/types/test_helpers.go index c7ce21ff0f..81e639ee10 100644 --- a/types/test_helpers.go +++ b/types/test_helpers.go @@ -43,3 +43,62 @@ func RandAccounts(num int, minAmount int64, maxAmount int64) []PrivAccount { return privAccs } + +///////////////////////////////////////////////////////////////// + +//func MakeAccs(secrets ...string) (accs []PrivAccount) { +// for _, secret := range secrets { +// privAcc := PrivAccountFromSecret(secret) +// privAcc.Account.Balance = Coins{{"mycoin", 7}} +// accs = append(accs, privAcc) +// } +// return +//} + +func MakeAcc(secret string) PrivAccount { + privAcc := PrivAccountFromSecret(secret) + privAcc.Account.Balance = Coins{{"mycoin", 7}} + return privAcc +} + +func Accs2TxInputs(seq int, accs ...PrivAccount) []TxInput { + var txs []TxInput + for _, acc := range accs { + tx := NewTxInput( + acc.Account.PubKey, + Coins{{"mycoin", 5}}, + seq) + txs = append(txs, tx) + } + return txs +} + +//turn a list of accounts into basic list of transaction outputs +func Accs2TxOutputs(accs ...PrivAccount) []TxOutput { + var txs []TxOutput + for _, acc := range accs { + tx := TxOutput{ + acc.Account.PubKey.Address(), + Coins{{"mycoin", 4}}} + txs = append(txs, tx) + } + return txs +} + +func GetTx(seq int, accOut PrivAccount, accsIn ...PrivAccount) *SendTx { + txs := &SendTx{ + Gas: 0, + Fee: Coin{"mycoin", 1}, + Inputs: Accs2TxInputs(seq, accsIn...), + Outputs: Accs2TxOutputs(accOut), + } + + return txs +} + +func SignTx(chainID string, tx *SendTx, accs ...PrivAccount) { + signBytes := tx.SignBytes(chainID) + for i, _ := range tx.Inputs { + tx.Inputs[i].Signature = crypto.SignatureS{accs[i].Sign(signBytes)} + } +} diff --git a/types/tx_test.go b/types/tx_test.go index 5bfb3bc4c0..71033cc9e7 100644 --- a/types/tx_test.go +++ b/types/tx_test.go @@ -1,11 +1,11 @@ package types import ( + "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - cmn "github.com/tendermint/go-common" crypto "github.com/tendermint/go-crypto" data "github.com/tendermint/go-data" ) @@ -40,11 +40,11 @@ func TestSendTxSignable(t *testing.T) { }, } signBytes := sendTx.SignBytes(chainID) - signBytesHex := cmn.Fmt("%X", signBytes) + signBytesHex := fmt.Sprintf("%X", signBytes) expected := "010A746573745F636861696E0100000000000000DE00000000000000006F01020106696E7075743101010000000000000030390301093200000106696E70757432010100000000000000006F01DE0000010201076F757470757431010100000000000000014D01076F75747075743201010000000000000001BC" - assert.True(t, signBytesHex == expected, - cmn.Fmt("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)) + assert.Equal(t, signBytesHex, expected, + "Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex) } func TestAppTxSignable(t *testing.T) { @@ -60,14 +60,16 @@ func TestAppTxSignable(t *testing.T) { Data: []byte("data1"), } signBytes := callTx.SignBytes(chainID) - signBytesHex := cmn.Fmt("%X", signBytes) + signBytesHex := fmt.Sprintf("%X", signBytes) expected := "010A746573745F636861696E0100000000000000DE00000000000000006F0101580106696E70757431010100000000000000303903010932000001056461746131" - assert.True(t, signBytesHex == expected, - cmn.Fmt("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)) + assert.Equal(t, signBytesHex, expected, + "Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex) } func TestSendTxJSON(t *testing.T) { + assert, require := assert.New(t), require.New(t) + chainID := "test_chain_id" test1PrivAcc := PrivAccountFromSecret("sendtx1") test2PrivAcc := PrivAccountFromSecret("sendtx2") @@ -89,37 +91,37 @@ func TestSendTxJSON(t *testing.T) { // serialize this as json and back js, err := data.ToJSON(TxS{tx}) - require.Nil(t, err) + require.Nil(err) // fmt.Println(string(js)) txs := TxS{} err = data.FromJSON(js, &txs) - require.Nil(t, err) + require.Nil(err) tx2, ok := txs.Tx.(*SendTx) - require.True(t, ok) + require.True(ok) // make sure they are the same! signBytes := tx.SignBytes(chainID) signBytes2 := tx2.SignBytes(chainID) - assert.Equal(t, signBytes, signBytes2) - assert.Equal(t, tx, tx2) + assert.Equal(signBytes, signBytes2) + assert.Equal(tx, tx2) // sign this thing sig := test1PrivAcc.Sign(signBytes) // we handle both raw sig and wrapped sig the same tx.SetSignature(test1PrivAcc.PubKey.Address(), sig) tx2.SetSignature(test1PrivAcc.PubKey.Address(), crypto.SignatureS{sig}) - assert.Equal(t, tx, tx2) + assert.Equal(tx, tx2) // let's marshal / unmarshal this with signature js, err = data.ToJSON(TxS{tx}) - require.Nil(t, err) + require.Nil(err) // fmt.Println(string(js)) err = data.FromJSON(js, &txs) - require.Nil(t, err) + require.Nil(err) tx2, ok = txs.Tx.(*SendTx) - require.True(t, ok) + require.True(ok) // and make sure the sig is preserved - assert.Equal(t, tx, tx2) - assert.False(t, tx2.Inputs[0].Signature.Empty()) + assert.Equal(tx, tx2) + assert.False(tx2.Inputs[0].Signature.Empty()) }