diff --git a/app/app_test.go b/app/app_test.go index 1be563ed8b..31c300b6e6 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -14,6 +14,80 @@ import ( 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 + accsIn []types.PrivAccount + accsOut []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 accsIn to accsOut +func (ap *appTest) getTx(seq int) *types.SendTx { + tx := types.GetTx(seq, ap.accsIn, ap.accsOut) + types.SignTx(ap.chainID, tx, ap.accsIn) + 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.accsIn = types.MakeAccs("input0") + at.accsOut = types.MakeAccs("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.accsIn[0].Account) + at.acc2app(at.accsOut[0].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) { + + initBalFoo := at.app.GetState().GetAccount(at.accsIn[0].Account.PubKey.Address()).Balance + initBalBar := at.app.GetState().GetAccount(at.accsOut[0].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) + } + + endBalFoo := at.app.GetState().GetAccount(at.accsIn[0].Account.PubKey.Address()).Balance + endBalBar := at.app.GetState().GetAccount(at.accsOut[0].Account.PubKey.Address()).Balance + decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) + return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) +} + +//-------------------------------------------------------- + func TestSplitKey(t *testing.T) { assert := assert.New(t) prefix, suffix := splitKey("foo/bar") @@ -37,10 +111,10 @@ func TestSetOption(t *testing.T) { assert.EqualValues(app.GetState().GetChainID(), chainID) assert.EqualValues(res, "Success") - accsFoo := types.MakeAccs("foo") - accsFooBytes, err := json.Marshal(accsFoo[0].Account) + accsIn := types.MakeAccs("input0") + accsInBytes, err := json.Marshal(accsIn[0].Account) assert.Nil(err) - res = app.SetOption("base/account", string(accsFooBytes)) + res = app.SetOption("base/account", string(accsInBytes)) assert.EqualValues(res, "Success") res = app.SetOption("base/dslfkgjdas", "") @@ -53,21 +127,20 @@ func TestSetOption(t *testing.T) { assert.NotEqual(res, "Success") } -//CheckTx - bad bytes, bad tx, good tx. -//DeliverTx - bad bytes, bad tx, good tx. +// Test CheckTx and DeliverTx with insufficient and sufficient balance func TestTx(t *testing.T) { assert := assert.New(t) at := newAppTest(t) //Bad Balance - at.accsFoo[0].Balance = types.Coins{{"mycoin", 2}} - at.acc2app(at.accsFoo[0].Account) + at.accsIn[0].Balance = types.Coins{{"mycoin", 2}} + at.acc2app(at.accsIn[0].Account) res, _, _, _, _ := at.exec(at.getTx(1), true) assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) - res, foo, fooexp, bar, barexp := at.exec(at.getTx(1), false) + res, inGot, inExp, outGot, outExp := at.exec(at.getTx(1), false) assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res)) - assert.True(!foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, foo: %v, fooExp: %v", foo, fooexp)) - assert.True(!bar.IsEqual(barexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, bar: %v, barExp: %v", bar, barexp)) + assert.False(inGot.IsEqual(inExp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, inGot: %v, inExp: %v", inGot, inExp)) + assert.False(outGot.IsEqual(outExp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, outGot: %v, outExp: %v", outGot, outExp)) //Regular CheckTx at.reset() @@ -76,10 +149,10 @@ func TestTx(t *testing.T) { //Regular DeliverTx at.reset() - res, foo, fooexp, bar, barexp = at.exec(at.getTx(1), false) + res, inGot, inExp, outGot, outExp = at.exec(at.getTx(1), false) assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res)) - assert.True(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo, fooexp)) - assert.True(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar, barexp)) + assert.True(inGot.IsEqual(inExp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, inGot: %v, inExp: %v", inGot, inExp)) + assert.True(outGot.IsEqual(outExp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, outGot: %v, outExp: %v", outGot, outExp)) } func TestQuery(t *testing.T) { @@ -87,11 +160,11 @@ func TestQuery(t *testing.T) { at := newAppTest(t) res, _, _, _, _ := at.exec(at.getTx(1), false) - assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) + assert.True(res.IsOK(), fmt.Sprintf("Commit, DeliverTx: Expected OK return from DeliverTx, Error: %v", res)) resQueryPreCommit := at.app.Query(abci.RequestQuery{ Path: "/account", - Data: at.accsFoo[0].Account.PubKey.Address(), + Data: at.accsIn[0].Account.PubKey.Address(), }) res = at.app.Commit() @@ -99,76 +172,9 @@ func TestQuery(t *testing.T) { resQueryPostCommit := at.app.Query(abci.RequestQuery{ Path: "/account", - Data: at.accsFoo[0].Account.PubKey.Address(), + Data: at.accsIn[0].Account.PubKey.Address(), }) fmt.Println(resQueryPreCommit) fmt.Println(resQueryPostCommit) assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit") } - -///////////////////////////////////////////////////////////////// - -type appTest struct { - t *testing.T - chainID string - app *Basecoin - accsFoo []types.PrivAccount - accsBar []types.PrivAccount -} - -func newAppTest(t *testing.T) *appTest { - at := &appTest{ - t: t, - chainID: "test_chain_id", - } - at.reset() - return at -} - -func (ap *appTest) getTx(seq int) *types.SendTx { - tx := types.GetTx(seq, ap.accsFoo, ap.accsBar) - types.SignTx(ap.chainID, tx, ap.accsFoo) - return tx -} - -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") -} - -func (at *appTest) reset() { - at.accsFoo = types.MakeAccs("foo") - at.accsBar = types.MakeAccs("bar") - - 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.accsFoo[0].Account) - at.acc2app(at.accsBar[0].Account) - - resabci := at.app.Commit() - require.True(at.t, resabci.IsOK(), resabci) -} - -func (at *appTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, foo, fooExp, bar, barExp types.Coins) { - - initBalFoo := at.app.GetState().GetAccount(at.accsFoo[0].Account.PubKey.Address()).Balance - initBalBar := at.app.GetState().GetAccount(at.accsBar[0].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) - } - - endBalFoo := at.app.GetState().GetAccount(at.accsFoo[0].Account.PubKey.Address()).Balance - endBalBar := at.app.GetState().GetAccount(at.accsBar[0].Account.PubKey.Address()).Balance - decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) - return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) -} diff --git a/state/execution_test.go b/state/execution_test.go index b3daa068c0..210ff4e2b5 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -10,6 +10,69 @@ import ( "github.com/tendermint/basecoin/types" ) +//-------------------------------------------------------- +// test environment is a bunch of lists of accountns + +type execTest struct { + chainID string + store types.KVStore + state *State + accsFoo []types.PrivAccount + accsBar []types.PrivAccount + accsFooBar []types.PrivAccount + accsDup []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.accsBar +func (et *execTest) getTx(seq int, accsIn []types.PrivAccount) *types.SendTx { + return types.GetTx(seq, accsIn, et.accsBar) +} + +// 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) { + initBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance + initBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance + + res = ExecTx(et.state, nil, tx, checkTx, nil) + + endBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance + endBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance + decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) + return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.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.accsFoo = types.MakeAccs("foo") + et.accsBar = types.MakeAccs("bar") + et.accsFooBar = types.MakeAccs("foo", "bar") + et.accsDup = types.MakeAccs("foo", "foo", "foo") + + et.store = types.NewMemKVStore() + et.state = NewState(et.store) + et.state.SetChainID(et.chainID) +} + +//-------------------------------------------------------- + func TestGetInputs(t *testing.T) { assert := assert.New(t) et := newExecTest() @@ -231,61 +294,3 @@ func TestExecTx(t *testing.T) { assert.True(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo, fooexp)) assert.True(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar, barexp)) } - -/////////////////////////////////////////////////////////////////// - -type execTest struct { - chainID string - store types.KVStore - state *State - accsFoo []types.PrivAccount - accsBar []types.PrivAccount - accsFooBar []types.PrivAccount - accsDup []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) -} - -func (et *execTest) getTx(seq int, accsIn []types.PrivAccount) *types.SendTx { - return types.GetTx(seq, accsIn, et.accsBar) -} - -func (et *execTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, foo, fooExp, bar, barExp types.Coins) { - initBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance - initBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance - - res = ExecTx(et.state, nil, tx, checkTx, nil) - - endBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance - endBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance - decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) - return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.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 the store/et.state/Inputs -func (et *execTest) reset() { - et.accsFoo = types.MakeAccs("foo") - et.accsBar = types.MakeAccs("bar") - et.accsFooBar = types.MakeAccs("foo", "bar") - et.accsDup = types.MakeAccs("foo", "foo", "foo") - - et.store = types.NewMemKVStore() - et.state = NewState(et.store) - et.state.SetChainID(et.chainID) -} diff --git a/types/coin.go b/types/coin.go index 1af65edcac..05c3111aa6 100644 --- a/types/coin.go +++ b/types/coin.go @@ -45,7 +45,7 @@ func (coins Coins) String() string { for _, coin := range coins { out += fmt.Sprintf("%v,", coin.String()) } - return out + return out[:len(out)-1] } func ParseCoins(str string) (Coins, error) {