package rpctest import ( "fmt" "testing" "github.com/tendermint/tendermint/account" _ "github.com/tendermint/tendermint/config/tendermint_test" "github.com/tendermint/tendermint/types" ) var wsTyp = "JSONRPC" //-------------------------------------------------------------------------------- // Test the websocket service // make a simple connection to the server func TestWSConnect(t *testing.T) { con := newWSCon(t) con.Close() } // receive a new block message func _TestWSNewBlock(t *testing.T) { con := newWSCon(t) eid := types.EventStringNewBlock() subscribe(t, con, eid) defer func() { unsubscribe(t, con, eid) con.Close() }() waitForEvent(t, con, eid, true, func() {}, func(eid string, b []byte) error { fmt.Println("Check:", string(b)) return nil }) } // receive a few new block messages in a row, with increasing height func TestWSBlockchainGrowth(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } con := newWSCon(t) eid := types.EventStringNewBlock() subscribe(t, con, eid) defer func() { unsubscribe(t, con, eid) con.Close() }() // listen for NewBlock, ensure height increases by 1 unmarshalValidateBlockchain(t, con, eid) } // send a transaction and validate the events from listening for both sender and receiver func TestWSSend(t *testing.T) { toAddr := user[1].Address amt := int64(100) con := newWSCon(t) eidInput := types.EventStringAccInput(user[0].Address) eidOutput := types.EventStringAccOutput(toAddr) subscribe(t, con, eidInput) subscribe(t, con, eidOutput) defer func() { unsubscribe(t, con, eidInput) unsubscribe(t, con, eidOutput) con.Close() }() waitForEvent(t, con, eidInput, true, func() { tx := makeDefaultSendTxSigned(t, wsTyp, toAddr, amt) broadcastTx(t, wsTyp, tx) }, unmarshalValidateSend(amt, toAddr)) waitForEvent(t, con, eidOutput, true, func() {}, unmarshalValidateSend(amt, toAddr)) } // ensure events are only fired once for a given transaction func TestWSDoubleFire(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } con := newWSCon(t) eid := types.EventStringAccInput(user[0].Address) subscribe(t, con, eid) defer func() { unsubscribe(t, con, eid) con.Close() }() amt := int64(100) toAddr := user[1].Address // broadcast the transaction, wait to hear about it waitForEvent(t, con, eid, true, func() { tx := makeDefaultSendTxSigned(t, wsTyp, toAddr, amt) broadcastTx(t, wsTyp, tx) }, func(eid string, b []byte) error { return nil }) // but make sure we don't hear about it twice waitForEvent(t, con, eid, false, func() { }, func(eid string, b []byte) error { return nil }) } // create a contract, wait for the event, and send it a msg, validate the return func TestWSCallWait(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } con := newWSCon(t) eid1 := types.EventStringAccInput(user[0].Address) subscribe(t, con, eid1) defer func() { unsubscribe(t, con, eid1) con.Close() }() amt, gasLim, fee := int64(10000), int64(1000), int64(1000) code, returnCode, returnVal := simpleContract() var contractAddr []byte // wait for the contract to be created waitForEvent(t, con, eid1, true, func() { tx := makeDefaultCallTx(t, wsTyp, nil, code, amt, gasLim, fee) receipt := broadcastTx(t, wsTyp, tx) contractAddr = receipt.ContractAddr }, unmarshalValidateCall(amt, returnCode)) // susbscribe to the new contract amt = int64(10001) eid2 := types.EventStringAccOutput(contractAddr) subscribe(t, con, eid2) defer func() { unsubscribe(t, con, eid2) }() // get the return value from a call data := []byte{0x1} waitForEvent(t, con, eid2, true, func() { tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee) receipt := broadcastTx(t, wsTyp, tx) contractAddr = receipt.ContractAddr }, unmarshalValidateCall(amt, returnVal)) } // create a contract and send it a msg without waiting. wait for contract event // and validate return func TestWSCallNoWait(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } con := newWSCon(t) amt, gasLim, fee := int64(10000), int64(1000), int64(1000) code, _, returnVal := simpleContract() tx := makeDefaultCallTx(t, wsTyp, nil, code, amt, gasLim, fee) receipt := broadcastTx(t, wsTyp, tx) contractAddr := receipt.ContractAddr // susbscribe to the new contract amt = int64(10001) eid := types.EventStringAccOutput(contractAddr) subscribe(t, con, eid) defer func() { unsubscribe(t, con, eid) con.Close() }() // get the return value from a call data := []byte{0x1} waitForEvent(t, con, eid, true, func() { tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee) broadcastTx(t, wsTyp, tx) }, unmarshalValidateCall(amt, returnVal)) } // create two contracts, one of which calls the other func TestWSCallCall(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } con := newWSCon(t) amt, gasLim, fee := int64(10000), int64(1000), int64(1000) code, _, returnVal := simpleContract() txid := new([]byte) // deploy the two contracts tx := makeDefaultCallTx(t, wsTyp, nil, code, amt, gasLim, fee) receipt := broadcastTx(t, wsTyp, tx) contractAddr1 := receipt.ContractAddr code, _, _ = simpleCallContract(contractAddr1) tx = makeDefaultCallTx(t, wsTyp, nil, code, amt, gasLim, fee) receipt = broadcastTx(t, wsTyp, tx) contractAddr2 := receipt.ContractAddr // susbscribe to the new contracts amt = int64(10001) eid1 := types.EventStringAccReceive(contractAddr1) subscribe(t, con, eid1) defer func() { unsubscribe(t, con, eid1) con.Close() }() // call contract2, which should call contract1, and wait for ev1 // let the contract get created first waitForEvent(t, con, eid1, true, func() { }, func(eid string, b []byte) error { return nil }) // call it waitForEvent(t, con, eid1, true, func() { tx := makeDefaultCallTx(t, wsTyp, contractAddr2, nil, amt, gasLim, fee) broadcastTx(t, wsTyp, tx) *txid = account.HashSignBytes(chainID, tx) }, unmarshalValidateCallCall(user[0].Address, returnVal, txid)) }