Merge pull request #145 from tendermint/feature/99-autotest-tutorials

Feature/99 autotest tutorials
This commit is contained in:
Ethan Frey 2017-06-29 14:59:40 +02:00 committed by GitHub
commit d3b66492f7
12 changed files with 622 additions and 423 deletions

View File

@ -1,5 +1,7 @@
GOTOOLS = github.com/mitchellh/gox \
github.com/Masterminds/glide
github.com/Masterminds/glide \
github.com/rigelrozanski/shelldown/cmd/shelldown
TUTORIALS=$(shell find docs/guide -name "*md" -type f)
all: get_vendor_deps install test
@ -14,7 +16,7 @@ dist:
@bash scripts/dist.sh
@bash scripts/publish.sh
test: test_unit test_cli
test: test_unit test_cli test_tutorial
test_unit:
go test `glide novendor`
@ -27,6 +29,20 @@ test_cli: tests/cli/shunit2
@./tests/cli/restart.sh
@./tests/cli/ibc.sh
test_tutorial: docs/guide/shunit2
shelldown ${TUTORIALS}
for script in docs/guide/*.sh ; do \
bash $$script ; \
done
tests/cli/shunit2:
wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \
-q -O tests/cli/shunit2
docs/guide/shunit2:
wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \
-q -O docs/guide/shunit2
get_vendor_deps: tools
glide install
@ -35,10 +51,6 @@ build-docker:
"/go/src/github.com/tendermint/basecoin" -e "CGO_ENABLED=0" golang:alpine go build ./cmd/basecoin
docker build -t "tendermint/basecoin" .
tests/cli/shunit2:
wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \
-q -O tests/cli/shunit2
tools:
@go get $(GOTOOLS)

View File

@ -12,6 +12,7 @@ dependencies:
override:
- go get github.com/Masterminds/glide
- go version
- go get -u github.com/tendermint/tendermint/cmd/tendermint
- glide --version
- mkdir -p "$PROJECT_PARENT_PATH"
- ln -sf "$HOME/$CIRCLE_PROJECT_REPONAME/" "$REPO"

View File

@ -14,7 +14,7 @@ import (
//commands
var (
InitCmd = &cobra.Command{
Use: "init",
Use: "init [address]",
Short: "Initialize a basecoin blockchain",
RunE: initCmd,
}

View File

@ -1,3 +1,65 @@
<!--- shelldown script template, see github.com/rigelrozanski/shelldown
#!/bin/bash
testTutorial_BasecoinBasics() {
#shelldown[1][3] >/dev/null
#shelldown[1][4] >/dev/null
KEYPASS=qwertyuiop
RES=$((echo $KEYPASS; echo $KEYPASS) | #shelldown[1][6])
assertTrue "Line $LINENO: Expected to contain safe, got $RES" '[[ $RES == *safe* ]]'
RES=$((echo $KEYPASS; echo $KEYPASS) | #shelldown[1][7])
assertTrue "Line $LINENO: Expected to contain safe, got $RES" '[[ $RES == *safe* ]]'
#shelldown[3][-1]
assertTrue "Expected true for line $LINENO" $?
#shelldown[4][-1] >>/dev/null 2>&1 &
sleep 5
PID_SERVER=$!
disown
RES=$((echo y) | #shelldown[5][-1] $1)
assertTrue "Line $LINENO: Expected to contain validator, got $RES" '[[ $RES == *validator* ]]'
#shelldown[6][0]
#shelldown[6][1]
RES=$(#shelldown[6][2] | jq '.data.coins[0].denom' | tr -d '"')
assertTrue "Line $LINENO: Expected to have mycoins, got $RES" '[[ $RES == mycoin ]]'
RES="$(#shelldown[6][3] 2>&1)"
assertTrue "Line $LINENO: Expected to contain ERROR, got $RES" '[[ $RES == *ERROR* ]]'
RES=$((echo $KEYPASS) | #shelldown[7][-1] | jq '.deliver_tx.code')
assertTrue "Line $LINENO: Expected 0 code deliver_tx, got $RES" '[[ $RES == 0 ]]'
RES=$(#shelldown[8][-1] | jq '.data.coins[0].amount')
assertTrue "Line $LINENO: Expected to contain 1000 mycoin, got $RES" '[[ $RES == 1000 ]]'
RES=$((echo $KEYPASS) | #shelldown[9][-1] | jq '.deliver_tx.code')
assertTrue "Line $LINENO: Expected 0 code deliver_tx, got $RES" '[[ $RES == 0 ]]'
RES=$((echo $KEYPASS) | #shelldown[10][-1])
assertTrue "Line $LINENO: Expected to contain insufficient funds error, got $RES" \
'[[ $RES == *"insufficient funds"* ]]'
#perform a substitution within the final tests
HASH=$((echo $KEYPASS) | #shelldown[11][-1] | jq '.hash' | tr -d '"')
PRESUB="#shelldown[12][-1]"
RES=$(eval ${PRESUB/<HASH>/$HASH})
assertTrue "Line $LINENO: Expected to not contain Error, got $RES" '[[ $RES != *Error* ]]'
}
oneTimeTearDown() {
kill -9 $PID_SERVER >/dev/null 2>&1
sleep 1
}
# load and run these tests with shunit2!
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
. $DIR/shunit2
-->
# Basecoin Basics
Here we explain how to get started with a simple Basecoin blockchain,
@ -8,7 +70,7 @@ and what is happening under the hood.
Installing Basecoin is simple:
```
```shelldown[0]
go get -u github.com/tendermint/basecoin/cmd/...
```
@ -22,23 +84,27 @@ The former is the running node. The latter is a command-line light-client.
Let's generate two keys, one to receive an initial allocation of coins,
and one to send some coins to later:
```
```shelldown[1]
# WARNING: this will wipe out any existing info in the ~/.basecli dir
# including private keys, don't run if you have lots of local state already
# while we're at it let's remove the working directory for the full node too
basecli reset_all
rm -rf ~/.basecoin
basecli keys new cool
basecli keys new friend
```
You'll need to enter passwords. You can view your key names and addresses with `basecli keys list`,
or see a particular key's address with `basecli keys get <NAME>`.
You'll need to enter passwords. You can view your key names and addresses with
`basecli keys list`, or see a particular key's address with `basecli keys get
<NAME>`.
## Initialize Basecoin
To initialize a new Basecoin blockchain, run:
```
```shelldown[2]
# WARNING: this will wipe out any existing info in the ~/.basecoin dir
# don't run if you have lots of local state already
rm -rf ~/.basecoin
@ -47,21 +113,23 @@ basecoin init <ADDRESS>
If you prefer not to copy-paste, you can provide the address programatically:
```
```shelldown[3]
basecoin init $(basecli keys get cool | awk '{print $2}')
```
This will create the necessary files for a Basecoin blockchain with one
validator and one account (corresponding to your key) in `~/.basecoin`. For more options on setup, see the
[guide to using the Basecoin tool](/docs/guide/basecoin-tool.md).
validator and one account (corresponding to your key) in `~/.basecoin`. For
more options on setup, see the [guide to using the Basecoin
tool](/docs/guide/basecoin-tool.md).
If you like, you can manually add some more accounts to the blockchain by generating keys and editing the `~/.basecoin/genesis.json`.
If you like, you can manually add some more accounts to the blockchain by
generating keys and editing the `~/.basecoin/genesis.json`.
## Start
Now we can start Basecoin:
```
```shelldown[4]
basecoin start
```
@ -69,11 +137,11 @@ You should see blocks start streaming in!
## Initialize Light-Client
Now that Basecoin is running we can initialize `basecli`, the light-client utility.
Basecli is used for sending transactions and querying the state.
Now that Basecoin is running we can initialize `basecli`, the light-client
utility. Basecli is used for sending transactions and querying the state.
Leave Basecoin running and open a new terminal window. Here run:
```
```shelldown[5]
basecli init --node=tcp://localhost:46657 --genesis=$HOME/.basecoin/genesis.json
```
@ -91,7 +159,7 @@ set through some other method.
Now we are ready to send some transactions. First Let's check the balance of
the two accounts we setup earlier:
```
```shelldown[6]
ME=$(basecli keys get cool | awk '{print $2}')
YOU=$(basecli keys get friend | awk '{print $2}')
basecli query account $ME
@ -101,19 +169,19 @@ basecli query account $YOU
The first account is flush with cash, while the second account doesn't exist.
Let's send funds from the first account to the second:
```
```shelldown[7]
basecli tx send --name=cool --amount=1000mycoin --to=$YOU --sequence=1
```
Now if we check the second account, it should have `1000` 'mycoin' coins!
```
```shelldown[8]
basecli query account $YOU
```
We can send some of these coins back like so:
```
```shelldown[9]
basecli tx send --name=friend --amount=500mycoin --to=$ME --sequence=1
```
@ -121,20 +189,20 @@ Note how we use the `--name` flag to select a different account to send from.
If we try to send too much, we'll get an error:
```
basecli tx send --name=friend --amount=500000mycoin --to=$ME --sequence=1
```shelldown[10]
basecli tx send --name=friend --amount=500000mycoin --to=$ME --sequence=2
```
Let's send another transaction:
```
```shelldown[11]
basecli tx send --name=cool --amount=2345mycoin --to=$YOU --sequence=2
```
Note the `hash` value in the response - this is the hash of the transaction.
We can query for the transaction by this hash:
```
```shelldown[12]
basecli query tx <HASH>
```
@ -142,23 +210,23 @@ See `basecli tx send --help` for additional details.
## Proof
Even if you don't see it in the UI, the result of every query comes with a proof.
This is a Merkle proof that the result of the query is actually contained in the state.
and the state's Merkle root is contained in a recent block header.
Behind the scenes, `countercli` will not only verify that this state matches the header,
but also that the header is properly signed by the known validator set.
It will even update the validator set as needed, so long
as there have not been major changes and it is secure to do so. So, if you wonder
why the query may take a second... there is a lot of work going on in the
background to make sure even a lying full node can't trick your client.
Even if you don't see it in the UI, the result of every query comes with a
proof. This is a Merkle proof that the result of the query is actually
contained in the state. and the state's Merkle root is contained in a recent
block header. Behind the scenes, `countercli` will not only verify that this
state matches the header, but also that the header is properly signed by the
known validator set. It will even update the validator set as needed, so long
as there have not been major changes and it is secure to do so. So, if you
wonder why the query may take a second... there is a lot of work going on in
the background to make sure even a lying full node can't trick your client.
In a latter [guide on InterBlockchainCommunication](ibc.md), we'll use these
proofs to post transactions to other chains.
## Accounts and Transactions
For a better understanding of how to further use the tools, it helps to understand the
underlying data structures.
For a better understanding of how to further use the tools, it helps to
understand the underlying data structures.
### Accounts
@ -184,8 +252,8 @@ type Coin struct {
}
```
If you want to add more coins to a blockchain, you can do so manually in the `~/.basecoin/genesis.json` before
you start the blockchain for the first time.
If you want to add more coins to a blockchain, you can do so manually in the
`~/.basecoin/genesis.json` before you start the blockchain for the first time.
Accounts are serialized and stored in a Merkle tree under the key
`base/a/<address>`, where `<address>` is the address of the account.
@ -254,9 +322,10 @@ transaction.
## Conclusion
In this guide, we introduced the `basecoin` and `basecli` tools,
demonstrated how to start a new basecoin blockchain and how to send tokens between accounts,
and discussed the underlying data types for accounts and transactions, specifically the `Account` and the `SendTx`.
In the [next guide](basecoin-plugins.md), we introduce the Basecoin plugin system,
which uses a new transaction type, the `AppTx`, to extend the functionality of
the Basecoin system with arbitrary logic.
In this guide, we introduced the `basecoin` and `basecli` tools, demonstrated
how to start a new basecoin blockchain and how to send tokens between accounts,
and discussed the underlying data types for accounts and transactions,
specifically the `Account` and the `SendTx`. In the [next
guide](basecoin-plugins.md), we introduce the Basecoin plugin system, which
uses a new transaction type, the `AppTx`, to extend the functionality of the
Basecoin system with arbitrary logic.

View File

@ -1,11 +1,72 @@
<!--- shelldown script template, see github.com/rigelrozanski/shelldown
#!/bin/bash
testTutorial_BasecoinPlugins() {
#Initialization
#shelldown[0][1]
#shelldown[0][2]
KEYPASS=qwertyuiop
#Making Keys
RES=$((echo $KEYPASS; echo $KEYPASS) | #shelldown[0][4])
assertTrue "Line $LINENO: Expected to contain safe, got $RES" '[[ $RES == *safe* ]]'
RES=$((echo $KEYPASS; echo $KEYPASS) | #shelldown[0][5])
assertTrue "Line $LINENO: Expected to contain safe, got $RES" '[[ $RES == *safe* ]]'
#shelldown[0][7] >/dev/null
assertTrue "Expected true for line $LINENO" $?
#shelldown[0][9] >>/dev/null 2>&1 &
sleep 5
PID_SERVER=$!
disown
RES=$((echo y) | #shelldown[1][0] $1)
assertTrue "Line $LINENO: Expected to contain validator, got $RES" '[[ $RES == *validator* ]]'
#shelldown[1][2]
assertTrue "Expected true for line $LINENO" $?
RES=$((echo $KEYPASS) | #shelldown[1][3] | jq '.deliver_tx.code')
assertTrue "Line $LINENO: Expected 0 code deliver_tx, got $RES" '[[ $RES == 0 ]]'
RES=$((echo $KEYPASS) | #shelldown[2][0])
assertTrue "Line $LINENO: Expected to contain Valid error, got $RES" \
'[[ $RES == *"Valid must be true"* ]]'
RES=$((echo $KEYPASS) | #shelldown[2][1] | jq '.deliver_tx.code')
assertTrue "Line $LINENO: Expected 0 code deliver_tx, got $RES" '[[ $RES == 0 ]]'
RES=$(#shelldown[3][-1] | jq '.data.Counter')
assertTrue "Line $LINENO: Expected Counter of 1, got $RES" '[[ $RES == 1 ]]'
RES=$((echo $KEYPASS) | #shelldown[4][0] | jq '.deliver_tx.code')
assertTrue "Line $LINENO: Expected 0 code deliver_tx, got $RES" '[[ $RES == 0 ]]'
RES=$(#shelldown[4][1])
RESCOUNT=$(printf "$RES" | jq '.data.Counter')
RESFEE=$(printf "$RES" | jq '.data.TotalFees[0].amount')
assertTrue "Line $LINENO: Expected Counter of 2, got $RES" '[[ $RESCOUNT == 2 ]]'
assertTrue "Line $LINENO: Expected TotalFees of 2, got $RES" '[[ $RESFEE == 2 ]]'
}
oneTimeTearDown() {
kill -9 $PID_SERVER >/dev/null 2>&1
sleep 1
}
# load and run these tests with shunit2!
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
. $DIR/shunit2
-->
# Basecoin Plugins
In the [previous guide](basecoin-basics.md), we saw how to use the `basecoin`
tool to start a blockchain and the `basecli` tools to send transactions. We also learned about
`Account` and `SendTx`, the basic data types giving us a multi-asset
cryptocurrency. Here, we will demonstrate how to extend the tools to
use another transaction type, the `AppTx`, so we can send data to a custom plugin. In
this example we explore a simple plugin named `counter`.
tool to start a blockchain and the `basecli` tools to send transactions. We
also learned about `Account` and `SendTx`, the basic data types giving us a
multi-asset cryptocurrency. Here, we will demonstrate how to extend the tools
to use another transaction type, the `AppTx`, so we can send data to a custom
plugin. In this example we explore a simple plugin named `counter`.
## Example Plugin
@ -25,7 +86,7 @@ and a coin amount named `countfee`. The transaction is only accepted if both
A new blockchain can be initialized and started just like in the [previous
guide](basecoin-basics.md):
```
```shelldown[0]
# WARNING: this wipes out data - but counter is only for demos...
rm -rf ~/.counter
countercli reset_all
@ -41,7 +102,7 @@ counter start
The default files are stored in `~/.counter`. In another window we can
initialize the light-client and send a transaction:
```
```shelldown[1]
countercli init --node=tcp://localhost:46657 --genesis=$HOME/.counter/genesis.json
YOU=$(countercli keys get friend | awk '{print $2}')
@ -51,7 +112,7 @@ countercli tx send --name=cool --amount=1000mycoin --to=$YOU --sequence=1
But the Counter has an additional command, `countercli tx counter`, which
crafts an `AppTx` specifically for this plugin:
```
```shelldown[2]
countercli tx counter --name cool --amount=1mycoin --sequence=2
countercli tx counter --name cool --amount=1mycoin --sequence=3 --valid
```
@ -61,7 +122,7 @@ valid, while the second transaction passes. We can build plugins that take
many arguments of different types, and easily extend the tool to accomodate
them. Of course, we can also expose queries on our plugin:
```
```shelldown[3]
countercli query counter
```
@ -70,7 +131,7 @@ should see a Counter value of 1 representing the number of valid transactions.
If we send another transaction, and then query again, we will see the value
increment:
```
```shelldown[4]
countercli tx counter --name cool --amount=2mycoin --sequence=4 --valid --countfee=2mycoin
countercli query counter
```

View File

@ -1,3 +1,57 @@
<!--- shelldown script template, see github.com/rigelrozanski/shelldown
#!/bin/bash
testTutorial_BasecoinTool() {
rm -rf ~/.basecoin
rm -rf ~/.basecli
rm -rf example-data
KEYPASS=qwertyuiop
(echo $KEYPASS; echo $KEYPASS) | #shelldown[0][0] >/dev/null ; assertTrue "Expected true for line $LINENO" $?
#shelldown[0][1] >/dev/null ; assertTrue "Expected true for line $LINENO" $?
#shelldown[1][0] ; assertTrue "Expected true for line $LINENO" $?
#shelldown[1][1] ; assertTrue "Expected true for line $LINENO" $?
#shelldown[1][2] >>/dev/null 2>&1 &
sleep 5 ; PID_SERVER=$! ; disown ; assertTrue "Expected true for line $LINENO" $?
kill -9 $PID_SERVER >/dev/null 2>&1 ; sleep 1
#shelldown[2][0] ; assertTrue "Expected true for line $LINENO" $?
#shelldown[2][1] >>/dev/null 2>&1 &
sleep 5 ; PID_SERVER=$! ; disown ; assertTrue "Expected true for line $LINENO" $?
kill -9 $PID_SERVER >/dev/null 2>&1 ; sleep 1
#shelldown[3][-1] >/dev/null ; assertTrue "Expected true for line $LINENO" $?
#shelldown[4][-1] >>/dev/null 2>&1 &
sleep 5 ; PID_SERVER=$! ; disown ; assertTrue "Expected true for line $LINENO" $?
#shelldown[5][-1] >>/dev/null 2>&1 &
sleep 5 ; PID_SERVER2=$! ; disown ; assertTrue "Expected true for line $LINENO" $?
kill -9 $PID_SERVER $PID_SERVER2 >/dev/null 2>&1 ; sleep 1
#shelldown[4][-1] >>/dev/null 2>&1 &
sleep 5 ; PID_SERVER=$! ; disown ; assertTrue "Expected true for line $LINENO" $?
#shelldown[6][0] ; assertTrue "Expected true for line $LINENO" $?
#shelldown[6][1] >>/dev/null 2>&1 &
sleep 5 ; PID_SERVER2=$! ; disown ; assertTrue "Expected true for line $LINENO" $?
kill -9 $PID_SERVER $PID_SERVER2 >/dev/null 2>&1 ; sleep 1
#shelldown[7][-1] >/dev/null ; assertTrue "Expected true for line $LINENO" $?
#shelldown[8][-1] >/dev/null ; assertTrue "Expected true for line $LINENO" $?
(echo $KEYPASS; echo $KEYPASS) | #shelldown[9][-1] >/dev/null ; assertTrue "Expected true for line $LINENO" $?
#shelldown[10][-1] >/dev/null ; assertTrue "Expected true for line $LINENO" $?
#shelldown[11][-1] >/dev/null ; assertTrue "Expected true for line $LINENO" $?
#cleanup
rm -rf example-data
}
# load and run these tests with shunit2!
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
. $DIR/shunit2
-->
# The Basecoin Tool
In previous tutorials we learned the [basics of the Basecoin
@ -9,7 +63,7 @@ details on using the Basecoin tool.
Generate a key using the `basecli` tool:
```
```shelldown[0]
basecli keys new mykey
ME=$(basecli keys get mykey | awk '{print $2}')
```
@ -19,7 +73,7 @@ ME=$(basecli keys get mykey | awk '{print $2}')
By default, `basecoin` works out of `~/.basecoin`. To change this, set the
`BCHOME` environment variable:
```
```shelldown[1]
export BCHOME=~/.my_basecoin_data
basecoin init $ME
basecoin start
@ -27,7 +81,7 @@ basecoin start
or
```
```shelldown[2]
BCHOME=~/.my_basecoin_data basecoin init $ME
BCHOME=~/.my_basecoin_data basecoin start
```
@ -38,7 +92,7 @@ So far we have run Basecoin and Tendermint in a single process. However, since
we use ABCI, we can actually run them in different processes. First,
initialize them:
```
```shelldown[3]
basecoin init $ME
```
@ -47,13 +101,13 @@ information for both Basecoin and Tendermint.
Now, In one window, run
```
```shelldown[4]
basecoin start --without-tendermint
```
and in another,
```
```shelldown[5]
TMROOT=~/.basecoin tendermint node
```
@ -62,7 +116,7 @@ You should see Tendermint start making blocks!
Alternatively, you could ignore the Tendermint details in
`~/.basecoin/genesis.json` and use a separate directory by running:
```
```shelldown[6]
tendermint init
tendermint node
```
@ -81,14 +135,14 @@ Now let's make our own custom Basecoin data.
First, create a new directory:
```
```shelldown[7]
mkdir example-data
```
We can tell `basecoin` to use this directory by exporting the `BCHOME`
environment variable:
```
```shelldown[8]
export BCHOME=$(pwd)/example-data
```
@ -97,13 +151,13 @@ variable to your shell startup scripts (eg. `~/.bashrc`).
Now, let's create a new key:
```
```shelldown[9]
basecli keys new foobar
```
The key's info can be retrieved with
```
```shelldown[10]
basecli keys get foobar -o=json
```
@ -173,13 +227,13 @@ guide](https://tendermint.com/docs/guides/using-tendermint).
You can reset all blockchain data by running:
```
```shelldown[11]
basecoin unsafe_reset_all
```
Similarly, you can reset client data by running:
```
```shelldown[12]
basecli reset_all
```

View File

@ -2,8 +2,8 @@
One of the most exciting elements of the Cosmos Network is the InterBlockchain
Communication (IBC) protocol, which enables interoperability across different
blockchains. We implemented IBC as a basecoin plugin, and we'll show you
how to use it to send tokens across blockchains!
blockchains. We implemented IBC as a basecoin plugin, and we'll show you how to
use it to send tokens across blockchains!
Please note, this tutorial assumes you are familiar with [Basecoin
plugins](/docs/guide/basecoin-plugins.md), but we'll explain how IBC works. You
@ -175,15 +175,15 @@ The results of a query can thus be used as proof in an `IBCPacketPostTx`.
## Relay
While we need all these packet types internally to keep track of all the
proofs on both chains in a secure manner, for the normal work-flow,
we can run a relay node that handles the cross-chain interaction.
While we need all these packet types internally to keep track of all the proofs
on both chains in a secure manner, for the normal work-flow, we can run a relay
node that handles the cross-chain interaction.
In this case, there are only two steps. First `basecoin relay init`,
which must be run once to register each chain with the other one,
and make sure they are ready to send and recieve. And then
`basecoin relay start`, which is a long-running process polling the queue
on each side, and relaying all new message to the other block.
In this case, there are only two steps. First `basecoin relay init`, which
must be run once to register each chain with the other one, and make sure they
are ready to send and recieve. And then `basecoin relay start`, which is a
long-running process polling the queue on each side, and relaying all new
message to the other block.
This requires that the relay has access to accounts with some funds on both
chains to pay for all the ibc packets it will be forwarding.
@ -195,14 +195,14 @@ tutorial.
Make sure you have installed [basecoin and basecli](/docs/guide/install.md).
Basecoin is a framework for creating new cryptocurrency applications. It
comes with an `IBC` plugin enabled by default.
Basecoin is a framework for creating new cryptocurrency applications. It comes
with an `IBC` plugin enabled by default.
You will also want to install the [jq](https://stedolan.github.io/jq/) for
handling JSON at the command line.
If you have any trouble with this, you can also look at the
[test scripts](/tests/cli/ibc.sh) or just run `make test_cli` in basecoin repo.
If you have any trouble with this, you can also look at the [test
scripts](/tests/cli/ibc.sh) or just run `make test_cli` in basecoin repo.
Otherwise, open up 5 (yes 5!) terminal tabs....
### Preliminaries
@ -225,7 +225,9 @@ alias basecoin1="basecoin --home $BCHOME1_SERVER"
alias basecoin2="basecoin --home $BCHOME2_SERVER"
```
This will give us some new commands to use instead of raw `basecli` and `basecoin` to ensure we're using the right configuration for the chain we want to talk to.
This will give us some new commands to use instead of raw `basecli` and
`basecoin` to ensure we're using the right configuration for the chain we want
to talk to.
We also want to set some chain IDs:
@ -234,7 +236,8 @@ export CHAINID1="test-chain-1"
export CHAINID2="test-chain-2"
```
And since we will run two different chains on one machine, we need to maintain different sets of ports:
And since we will run two different chains on one machine, we need to maintain
different sets of ports:
```
export PORT_PREFIX1=1234
@ -282,8 +285,9 @@ basecli1 query account $GOTNONE
### Setup Chain 2
This is the same as above, except with `basecli2`, `basecoin2`, and `$CHAINID2`.
We will also need to change the ports, since we're running another chain on the same local machine.
This is the same as above, except with `basecli2`, `basecoin2`, and
`$CHAINID2`. We will also need to change the ports, since we're running
another chain on the same local machine.
Let's create new keys for test-chain-2:
@ -315,13 +319,13 @@ basecli2 query account $BROKE
### Connect these chains
OK! So we have two chains running on your local machine, with different
keys on each. Let's hook them up together by starting a relay process to
forward messages from one chain to the other.
OK! So we have two chains running on your local machine, with different keys on
each. Let's hook them up together by starting a relay process to forward
messages from one chain to the other.
The relay account needs some money in it to pay for the ibc messages, so
for now, we have to transfer some cash from the rich accounts before we start
the actual relay.
The relay account needs some money in it to pay for the ibc messages, so for
now, we have to transfer some cash from the rich accounts before we start the
actual relay.
```
# note that this key.json file is a hardcoded demo for all chains, this will

View File

@ -8,43 +8,43 @@ RICH=${ACCOUNTS[0]}
POOR=${ACCOUNTS[4]}
oneTimeSetUp() {
quickSetup .basecoin_test_basictx basictx-chain
quickSetup .basecoin_test_basictx basictx-chain
}
oneTimeTearDown() {
quickTearDown
quickTearDown
}
test00GetAccount() {
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
assertFalse "requires arg" "${CLIENT_EXE} query account"
assertFalse "requires arg" "${CLIENT_EXE} query account"
checkAccount $SENDER "0" "9007199254740992"
checkAccount $SENDER "0" "9007199254740992"
ACCT2=$(${CLIENT_EXE} query account $RECV 2>/dev/null)
assertFalse "has no genesis account" $?
ACCT2=$(${CLIENT_EXE} query account $RECV 2>/dev/null)
assertFalse "has no genesis account" $?
}
test01SendTx() {
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
assertFalse "missing dest" "${CLIENT_EXE} tx send --amount=992mycoin --sequence=1"
assertFalse "bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH"
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH)
txSucceeded $? "$TX"
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
assertFalse "missing dest" "${CLIENT_EXE} tx send --amount=992mycoin --sequence=1"
assertFalse "bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH"
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH)
txSucceeded $? "$TX"
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
checkAccount $SENDER "1" "9007199254740000"
# make sure 0x prefix also works
checkAccount "0x$SENDER" "1" "9007199254740000"
checkAccount $RECV "0" "992"
checkAccount $SENDER "1" "9007199254740000"
# make sure 0x prefix also works
checkAccount "0x$SENDER" "1" "9007199254740000"
checkAccount $RECV "0" "992"
# Make sure tx is indexed
checkSendTx $HASH $TX_HEIGHT $SENDER "992"
# Make sure tx is indexed
checkSendTx $HASH $TX_HEIGHT $SENDER "992"
}
# Load common then run these tests with shunit2!

View File

@ -7,49 +7,50 @@
# ACCOUNTS=(foo bar) # List of accounts for initialization
# RICH=${ACCOUNTS[0]} # Account to assign genesis balance
# XXX Ex Usage: quickSetup $WORK_NAME $CHAIN_ID
# Desc: Start the program, use with shunit2 OneTimeSetUp()
quickSetup() {
# These are passed in as args
BASE_DIR=$HOME/$1
CHAIN_ID=$2
# These are passed in as args
BASE_DIR=$HOME/$1
CHAIN_ID=$2
rm -rf $BASE_DIR 2>/dev/null
mkdir -p $BASE_DIR
rm -rf $BASE_DIR 2>/dev/null
mkdir -p $BASE_DIR
# Set up client - make sure you use the proper prefix if you set
# a custom CLIENT_EXE
export BC_HOME=${BASE_DIR}/client
prepareClient
# Set up client - make sure you use the proper prefix if you set
# a custom CLIENT_EXE
export BC_HOME=${BASE_DIR}/client
prepareClient
# start basecoin server (with counter)
initServer $BASE_DIR $CHAIN_ID
if [ $? != 0 ]; then return 1; fi
# start basecoin server (with counter)
initServer $BASE_DIR $CHAIN_ID
if [ $? != 0 ]; then return 1; fi
initClient $CHAIN_ID
if [ $? != 0 ]; then return 1; fi
initClient $CHAIN_ID
if [ $? != 0 ]; then return 1; fi
printf "...Testing may begin!\n\n\n"
printf "...Testing may begin!\n\n\n"
}
# XXX Ex Usage: quickTearDown
# Desc: close the test server, use with shunit2 OneTimeTearDown()
quickTearDown() {
printf "\n\nstopping $SERVER_EXE test server..."
kill -9 $PID_SERVER >/dev/null 2>&1
sleep 1
printf "\n\nstopping $SERVER_EXE test server..."
kill -9 $PID_SERVER >/dev/null 2>&1
sleep 1
}
############################################################
prepareClient() {
echo "Preparing client keys..."
${CLIENT_EXE} reset_all
assertTrue $?
echo "Preparing client keys..."
${CLIENT_EXE} reset_all
assertTrue $?
for i in "${!ACCOUNTS[@]}"; do
newKey ${ACCOUNTS[$i]}
done
for i in "${!ACCOUNTS[@]}"; do
newKey ${ACCOUNTS[$i]}
done
}
# XXX Ex Usage1: initServer $ROOTDIR $CHAINID
@ -57,37 +58,37 @@ prepareClient() {
# Desc: Grabs the Rich account and gives it all genesis money
# port-prefix default is 4665{6,7,8}
initServer() {
echo "Setting up genesis..."
SERVE_DIR=$1/server
assertNotNull "no chain" $2
CHAIN=$2
SERVER_LOG=$1/${SERVER_EXE}.log
echo "Setting up genesis..."
SERVE_DIR=$1/server
assertNotNull "no chain" $2
CHAIN=$2
SERVER_LOG=$1/${SERVER_EXE}.log
GENKEY=$(${CLIENT_EXE} keys get ${RICH} | awk '{print $2}')
${SERVER_EXE} init --chain-id $CHAIN $GENKEY --home=$SERVE_DIR >>$SERVER_LOG
GENKEY=$(${CLIENT_EXE} keys get ${RICH} | awk '{print $2}')
${SERVER_EXE} init --chain-id $CHAIN $GENKEY --home=$SERVE_DIR >>$SERVER_LOG
# optionally set the port
if [ -n "$3" ]; then
echo "setting port $3"
sed -ie "s/4665/$3/" $SERVE_DIR/config.toml
fi
# optionally set the port
if [ -n "$3" ]; then
echo "setting port $3"
sed -ie "s/4665/$3/" $SERVE_DIR/config.toml
fi
echo "Starting ${SERVER_EXE} server..."
startServer $SERVE_DIR $SERVER_LOG
return $?
echo "Starting ${SERVER_EXE} server..."
startServer $SERVE_DIR $SERVER_LOG
return $?
}
# XXX Ex Usage: startServer $SERVE_DIR $SERVER_LOG
startServer() {
${SERVER_EXE} start --home=$1 >>$2 2>&1 &
sleep 5
PID_SERVER=$!
disown
if ! ps $PID_SERVER >/dev/null; then
echo "**FAILED**"
cat $SERVER_LOG
return 1
fi
${SERVER_EXE} start --home=$1 >>$2 2>&1 &
sleep 5
PID_SERVER=$!
disown
if ! ps $PID_SERVER >/dev/null; then
echo "**FAILED**"
cat $SERVER_LOG
return 1
fi
}
# XXX Ex Usage1: initClient $CHAINID
@ -95,86 +96,86 @@ startServer() {
# Desc: Initialize the client program
# port-prefix default is 46657
initClient() {
echo "Attaching ${CLIENT_EXE} client..."
PORT=${2:-46657}
# hard-code the expected validator hash
${CLIENT_EXE} init --chain-id=$1 --node=tcp://localhost:${PORT} --valhash=EB168E17E45BAEB194D4C79067FFECF345C64DE6
assertTrue "initialized light-client" $?
echo "Attaching ${CLIENT_EXE} client..."
PORT=${2:-46657}
# hard-code the expected validator hash
${CLIENT_EXE} init --chain-id=$1 --node=tcp://localhost:${PORT} --valhash=EB168E17E45BAEB194D4C79067FFECF345C64DE6
assertTrue "initialized light-client" $?
}
# XXX Ex Usage1: newKey $NAME
# XXX Ex Usage2: newKey $NAME $PASSWORD
# Desc: Generates key for given username and password
newKey(){
assertNotNull "keyname required" "$1"
KEYPASS=${2:-qwertyuiop}
(echo $KEYPASS; echo $KEYPASS) | ${CLIENT_EXE} keys new $1 >/dev/null 2>/dev/null
assertTrue "created $1" $?
assertTrue "$1 doesn't exist" "${CLIENT_EXE} keys get $1"
assertNotNull "keyname required" "$1"
KEYPASS=${2:-qwertyuiop}
(echo $KEYPASS; echo $KEYPASS) | ${CLIENT_EXE} keys new $1 >/dev/null 2>/dev/null
assertTrue "created $1" $?
assertTrue "$1 doesn't exist" "${CLIENT_EXE} keys get $1"
}
# XXX Ex Usage: getAddr $NAME
# Desc: Gets the address for a key name
getAddr() {
assertNotNull "keyname required" "$1"
RAW=$(${CLIENT_EXE} keys get $1)
assertTrue "no key for $1" $?
# print the addr
echo $RAW | cut -d' ' -f2
assertNotNull "keyname required" "$1"
RAW=$(${CLIENT_EXE} keys get $1)
assertTrue "no key for $1" $?
# print the addr
echo $RAW | cut -d' ' -f2
}
# Desc: Assumes just one coin, checks the balance of first coin in any case
checkAccount() {
# make sure sender goes down
ACCT=$(${CLIENT_EXE} query account $1)
if ! assertTrue "account must exist" $?; then
return 1
fi
# make sure sender goes down
ACCT=$(${CLIENT_EXE} query account $1)
if ! assertTrue "account must exist" $?; then
return 1
fi
if [ -n "$DEBUG" ]; then echo $ACCT; echo; fi
assertEquals "proper sequence" "$2" $(echo $ACCT | jq .data.sequence)
assertEquals "proper money" "$3" $(echo $ACCT | jq .data.coins[0].amount)
return $?
if [ -n "$DEBUG" ]; then echo $ACCT; echo; fi
assertEquals "proper sequence" "$2" $(echo $ACCT | jq .data.sequence)
assertEquals "proper money" "$3" $(echo $ACCT | jq .data.coins[0].amount)
return $?
}
# XXX Ex Usage: txSucceeded $? "$TX"
# Desc: Must be called right after the `tx` command, makes sure it got a success response
txSucceeded() {
if (assertTrue "sent tx: $2" $1); then
TX=$2
assertEquals "good check: $TX" "0" $(echo $TX | jq .check_tx.code)
assertEquals "good deliver: $TX" "0" $(echo $TX | jq .deliver_tx.code)
else
return 1
fi
if (assertTrue "sent tx: $2" $1); then
TX=$2
assertEquals "good check: $TX" "0" $(echo $TX | jq .check_tx.code)
assertEquals "good deliver: $TX" "0" $(echo $TX | jq .deliver_tx.code)
else
return 1
fi
}
# XXX Ex Usage: checkSendTx $HASH $HEIGHT $SENDER $AMOUNT
# Desc: This looks up the tx by hash, and makes sure the height and type match
# and that the first input was from this sender for this amount
checkSendTx() {
TX=$(${CLIENT_EXE} query tx $1)
assertTrue "found tx" $?
if [ -n "$DEBUG" ]; then echo $TX; echo; fi
TX=$(${CLIENT_EXE} query tx $1)
assertTrue "found tx" $?
if [ -n "$DEBUG" ]; then echo $TX; echo; fi
assertEquals "proper height" $2 $(echo $TX | jq .height)
assertEquals "type=send" '"send"' $(echo $TX | jq .data.type)
assertEquals "proper sender" "\"$3\"" $(echo $TX | jq .data.data.inputs[0].address)
assertEquals "proper out amount" "$4" $(echo $TX | jq .data.data.outputs[0].coins[0].amount)
return $?
assertEquals "proper height" $2 $(echo $TX | jq .height)
assertEquals "type=send" '"send"' $(echo $TX | jq .data.type)
assertEquals "proper sender" "\"$3\"" $(echo $TX | jq .data.data.inputs[0].address)
assertEquals "proper out amount" "$4" $(echo $TX | jq .data.data.outputs[0].coins[0].amount)
return $?
}
# XXX Ex Usage: waitForBlock $port
# Desc: Waits until the block height on that node increases by one
waitForBlock() {
addr=http://localhost:$1
b1=`curl -s $addr/status | jq .result.latest_block_height`
b2=$b1
while [ "$b2" == "$b1" ]; do
echo "Waiting for node $addr to commit a block ..."
sleep 1
b2=`curl -s $addr/status | jq .result.latest_block_height`
done
addr=http://localhost:$1
b1=`curl -s $addr/status | jq .result.latest_block_height`
b2=$b1
while [ "$b2" == "$b1" ]; do
echo "Waiting for node $addr to commit a block ..."
sleep 1
b2=`curl -s $addr/status | jq .result.latest_block_height`
done
}

View File

@ -8,84 +8,84 @@ RICH=${ACCOUNTS[0]}
POOR=${ACCOUNTS[4]}
oneTimeSetUp() {
quickSetup .basecoin_test_counter counter-chain
quickSetup .basecoin_test_counter counter-chain
}
oneTimeTearDown() {
quickTearDown
quickTearDown
}
test00GetAccount() {
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
assertFalse "requires arg" "${CLIENT_EXE} query account"
assertFalse "requires arg" "${CLIENT_EXE} query account"
checkAccount $SENDER "0" "9007199254740992"
checkAccount $SENDER "0" "9007199254740992"
ACCT2=$(${CLIENT_EXE} query account $RECV 2>/dev/null)
assertFalse "has no genesis account" $?
ACCT2=$(${CLIENT_EXE} query account $RECV 2>/dev/null)
assertFalse "has no genesis account" $?
}
test01SendTx() {
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
assertFalse "missing dest" "${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 2>/dev/null"
assertFalse "bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null"
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null)
txSucceeded $? "$TX"
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
assertFalse "missing dest" "${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 2>/dev/null"
assertFalse "bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null"
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null)
txSucceeded $? "$TX"
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
checkAccount $SENDER "1" "9007199254740000"
checkAccount $RECV "0" "992"
checkAccount $SENDER "1" "9007199254740000"
checkAccount $RECV "0" "992"
# make sure tx is indexed
checkSendTx $HASH $TX_HEIGHT $SENDER "992"
# make sure tx is indexed
checkSendTx $HASH $TX_HEIGHT $SENDER "992"
}
test02GetCounter() {
COUNT=$(${CLIENT_EXE} query counter 2>/dev/null)
assertFalse "no default count" $?
COUNT=$(${CLIENT_EXE} query counter 2>/dev/null)
assertFalse "no default count" $?
}
# checkCounter $COUNT $BALANCE
# Assumes just one coin, checks the balance of first coin in any case
checkCounter() {
# make sure sender goes down
ACCT=$(${CLIENT_EXE} query counter)
assertTrue "count is set" $?
assertEquals "proper count" "$1" $(echo $ACCT | jq .data.Counter)
assertEquals "proper money" "$2" $(echo $ACCT | jq .data.TotalFees[0].amount)
# make sure sender goes down
ACCT=$(${CLIENT_EXE} query counter)
assertTrue "count is set" $?
assertEquals "proper count" "$1" $(echo $ACCT | jq .data.Counter)
assertEquals "proper money" "$2" $(echo $ACCT | jq .data.TotalFees[0].amount)
}
test03AddCount() {
SENDER=$(getAddr $RICH)
assertFalse "bad password" "echo hi | ${CLIENT_EXE} tx counter --amount=1000mycoin --sequence=2 --name=${RICH} 2>/dev/null"
SENDER=$(getAddr $RICH)
assertFalse "bad password" "echo hi | ${CLIENT_EXE} tx counter --amount=1000mycoin --sequence=2 --name=${RICH} 2>/dev/null"
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --amount=10mycoin --sequence=2 --name=${RICH} --valid --countfee=5mycoin)
txSucceeded $? "$TX"
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --amount=10mycoin --sequence=2 --name=${RICH} --valid --countfee=5mycoin)
txSucceeded $? "$TX"
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
checkCounter "1" "5"
checkCounter "1" "5"
# FIXME: cannot load apptx properly.
# Look at the stack trace
# This cannot be fixed with the current ugly apptx structure...
# Leave for refactoring
# FIXME: cannot load apptx properly.
# Look at the stack trace
# This cannot be fixed with the current ugly apptx structure...
# Leave for refactoring
# make sure tx is indexed
# echo hash $HASH
# TX=$(${CLIENT_EXE} query tx $HASH --trace)
# echo tx $TX
# if [-z assertTrue "found tx" $?]; then
# assertEquals "proper height" $TX_HEIGHT $(echo $TX | jq .height)
# assertEquals "type=app" '"app"' $(echo $TX | jq .data.type)
# assertEquals "proper sender" "\"$SENDER\"" $(echo $TX | jq .data.data.input.address)
# fi
# echo $TX
# make sure tx is indexed
# echo hash $HASH
# TX=$(${CLIENT_EXE} query tx $HASH --trace)
# echo tx $TX
# if [-z assertTrue "found tx" $?]; then
# assertEquals "proper height" $TX_HEIGHT $(echo $TX | jq .height)
# assertEquals "type=app" '"app"' $(echo $TX | jq .data.type)
# assertEquals "proper sender" "\"$SENDER\"" $(echo $TX | jq .data.data.input.address)
# fi
# echo $TX
}
# Load common then run these tests with shunit2!

View File

@ -13,163 +13,163 @@ POOR=${ACCOUNTS[4]}
# CLIENT_EXE="basecli --trace"
oneTimeSetUp() {
# These are passed in as args
BASE_DIR_1=$HOME/.basecoin_test_ibc/chain1
CHAIN_ID_1=test-chain-1
CLIENT_1=${BASE_DIR_1}/client
PREFIX_1=1234
PORT_1=${PREFIX_1}7
# These are passed in as args
BASE_DIR_1=$HOME/.basecoin_test_ibc/chain1
CHAIN_ID_1=test-chain-1
CLIENT_1=${BASE_DIR_1}/client
PREFIX_1=1234
PORT_1=${PREFIX_1}7
BASE_DIR_2=$HOME/.basecoin_test_ibc/chain2
CHAIN_ID_2=test-chain-2
CLIENT_2=${BASE_DIR_2}/client
PREFIX_2=2345
PORT_2=${PREFIX_2}7
BASE_DIR_2=$HOME/.basecoin_test_ibc/chain2
CHAIN_ID_2=test-chain-2
CLIENT_2=${BASE_DIR_2}/client
PREFIX_2=2345
PORT_2=${PREFIX_2}7
# Clean up and create the test dirs
rm -rf $BASE_DIR_1 $BASE_DIR_2 2>/dev/null
mkdir -p $BASE_DIR_1 $BASE_DIR_2
# Clean up and create the test dirs
rm -rf $BASE_DIR_1 $BASE_DIR_2 2>/dev/null
mkdir -p $BASE_DIR_1 $BASE_DIR_2
# Set up client for chain 1- make sure you use the proper prefix if you set
# a custom CLIENT_EXE
BC_HOME=${CLIENT_1} prepareClient
BC_HOME=${CLIENT_2} prepareClient
# Set up client for chain 1- make sure you use the proper prefix if you set
# a custom CLIENT_EXE
BC_HOME=${CLIENT_1} prepareClient
BC_HOME=${CLIENT_2} prepareClient
# Start basecoin server, giving money to the key in the first client
BC_HOME=${CLIENT_1} initServer $BASE_DIR_1 $CHAIN_ID_1 $PREFIX_1
if [ $? != 0 ]; then return 1; fi
PID_SERVER_1=$PID_SERVER
# Start basecoin server, giving money to the key in the first client
BC_HOME=${CLIENT_1} initServer $BASE_DIR_1 $CHAIN_ID_1 $PREFIX_1
if [ $? != 0 ]; then return 1; fi
PID_SERVER_1=$PID_SERVER
# Start second basecoin server, giving money to the key in the second client
BC_HOME=${CLIENT_2} initServer $BASE_DIR_2 $CHAIN_ID_2 $PREFIX_2
if [ $? != 0 ]; then return 1; fi
PID_SERVER_2=$PID_SERVER
# Start second basecoin server, giving money to the key in the second client
BC_HOME=${CLIENT_2} initServer $BASE_DIR_2 $CHAIN_ID_2 $PREFIX_2
if [ $? != 0 ]; then return 1; fi
PID_SERVER_2=$PID_SERVER
# Connect both clients
BC_HOME=${CLIENT_1} initClient $CHAIN_ID_1 $PORT_1
if [ $? != 0 ]; then return 1; fi
BC_HOME=${CLIENT_2} initClient $CHAIN_ID_2 $PORT_2
if [ $? != 0 ]; then return 1; fi
# Connect both clients
BC_HOME=${CLIENT_1} initClient $CHAIN_ID_1 $PORT_1
if [ $? != 0 ]; then return 1; fi
BC_HOME=${CLIENT_2} initClient $CHAIN_ID_2 $PORT_2
if [ $? != 0 ]; then return 1; fi
printf "...Testing may begin!\n\n\n"
printf "...Testing may begin!\n\n\n"
}
oneTimeTearDown() {
printf "\n\nstopping both $SERVER_EXE test servers... $PID_SERVER_1 $PID_SERVER_2"
kill -9 $PID_SERVER_1
kill -9 $PID_SERVER_2
sleep 1
printf "\n\nstopping both $SERVER_EXE test servers... $PID_SERVER_1 $PID_SERVER_2"
kill -9 $PID_SERVER_1
kill -9 $PID_SERVER_2
sleep 1
}
test00GetAccount() {
SENDER_1=$(BC_HOME=${CLIENT_1} getAddr $RICH)
RECV_1=$(BC_HOME=${CLIENT_1} getAddr $POOR)
export BC_HOME=${CLIENT_1}
SENDER_1=$(BC_HOME=${CLIENT_1} getAddr $RICH)
RECV_1=$(BC_HOME=${CLIENT_1} getAddr $POOR)
export BC_HOME=${CLIENT_1}
assertFalse "requires arg" "${CLIENT_EXE} query account 2>/dev/null"
assertFalse "has no genesis account" "${CLIENT_EXE} query account $RECV_1 2>/dev/null"
checkAccount $SENDER_1 "0" "9007199254740992"
assertFalse "requires arg" "${CLIENT_EXE} query account 2>/dev/null"
assertFalse "has no genesis account" "${CLIENT_EXE} query account $RECV_1 2>/dev/null"
checkAccount $SENDER_1 "0" "9007199254740992"
export BC_HOME=${CLIENT_2}
SENDER_2=$(getAddr $RICH)
RECV_2=$(getAddr $POOR)
export BC_HOME=${CLIENT_2}
SENDER_2=$(getAddr $RICH)
RECV_2=$(getAddr $POOR)
assertFalse "requires arg" "${CLIENT_EXE} query account 2>/dev/null"
assertFalse "has no genesis account" "${CLIENT_EXE} query account $RECV_2 2>/dev/null"
checkAccount $SENDER_2 "0" "9007199254740992"
assertFalse "requires arg" "${CLIENT_EXE} query account 2>/dev/null"
assertFalse "has no genesis account" "${CLIENT_EXE} query account $RECV_2 2>/dev/null"
checkAccount $SENDER_2 "0" "9007199254740992"
# Make sure that they have different addresses on both chains (they are random keys)
assertNotEquals "sender keys must be different" "$SENDER_1" "$SENDER_2"
assertNotEquals "recipient keys must be different" "$RECV_1" "$RECV_2"
# Make sure that they have different addresses on both chains (they are random keys)
assertNotEquals "sender keys must be different" "$SENDER_1" "$SENDER_2"
assertNotEquals "recipient keys must be different" "$RECV_1" "$RECV_2"
}
test01SendIBCTx() {
# Trigger a cross-chain sendTx... from RICH on chain1 to POOR on chain2
# we make sure the money was reduced, but nothing arrived
SENDER=$(BC_HOME=${CLIENT_1} getAddr $RICH)
RECV=$(BC_HOME=${CLIENT_2} getAddr $POOR)
# Trigger a cross-chain sendTx... from RICH on chain1 to POOR on chain2
# we make sure the money was reduced, but nothing arrived
SENDER=$(BC_HOME=${CLIENT_1} getAddr $RICH)
RECV=$(BC_HOME=${CLIENT_2} getAddr $POOR)
export BC_HOME=${CLIENT_1}
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=20002mycoin \
--sequence=1 --to=${CHAIN_ID_2}/${RECV} --name=$RICH)
txSucceeded $? "$TX"
# an example to quit early if there is no point in more tests
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
export BC_HOME=${CLIENT_1}
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=20002mycoin \
--sequence=1 --to=${CHAIN_ID_2}/${RECV} --name=$RICH)
txSucceeded $? "$TX"
# an example to quit early if there is no point in more tests
if [ $? != 0 ]; then echo "aborting!"; return 1; fi
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
# Make sure balance went down and tx is indexed
checkAccount $SENDER "1" "9007199254720990"
checkSendTx $HASH $TX_HEIGHT $SENDER "20002"
# Make sure balance went down and tx is indexed
checkAccount $SENDER "1" "9007199254720990"
checkSendTx $HASH $TX_HEIGHT $SENDER "20002"
# Make sure nothing arrived - yet
waitForBlock ${PORT_1}
assertFalse "no relay running" "BC_HOME=${CLIENT_2} ${CLIENT_EXE} query account $RECV"
# Make sure nothing arrived - yet
waitForBlock ${PORT_1}
assertFalse "no relay running" "BC_HOME=${CLIENT_2} ${CLIENT_EXE} query account $RECV"
# Start the relay and wait a few blocks...
# (already sent a tx on chain1, so use higher sequence)
startRelay 2 1
if [ $? != 0 ]; then echo "can't start relay"; cat ${BASE_DIR_1}/../relay.log; return 1; fi
# Start the relay and wait a few blocks...
# (already sent a tx on chain1, so use higher sequence)
startRelay 2 1
if [ $? != 0 ]; then echo "can't start relay"; cat ${BASE_DIR_1}/../relay.log; return 1; fi
# Give it a little time, then make sure the money arrived
echo "waiting for relay..."
sleep 1
waitForBlock ${PORT_1}
waitForBlock ${PORT_2}
# Give it a little time, then make sure the money arrived
echo "waiting for relay..."
sleep 1
waitForBlock ${PORT_1}
waitForBlock ${PORT_2}
# Check the new account
echo "checking ibc recipient..."
BC_HOME=${CLIENT_2} checkAccount $RECV "0" "20002"
# Check the new account
echo "checking ibc recipient..."
BC_HOME=${CLIENT_2} checkAccount $RECV "0" "20002"
# Stop relay
printf "stoping relay\n"
kill -9 $PID_RELAY
# Stop relay
printf "stoping relay\n"
kill -9 $PID_RELAY
}
# StartRelay $seq1 $seq2
# startRelay hooks up a relay between chain1 and chain2
# it needs the proper sequence number for $RICH on chain1 and chain2 as args
startRelay() {
# Send some cash to the default key, so it can send messages
RELAY_KEY=${BASE_DIR_1}/server/key.json
RELAY_ADDR=$(cat $RELAY_KEY | jq .address | tr -d \")
echo starting relay $PID_RELAY ...
# Send some cash to the default key, so it can send messages
RELAY_KEY=${BASE_DIR_1}/server/key.json
RELAY_ADDR=$(cat $RELAY_KEY | jq .address | tr -d \")
echo starting relay $PID_RELAY ...
# Get paid on chain1
export BC_HOME=${CLIENT_1}
SENDER=$(getAddr $RICH)
RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=100000mycoin \
--sequence=$1 --to=$RELAY_ADDR --name=$RICH)
txSucceeded $? "$RES"
if [ $? != 0 ]; then echo "can't pay chain1!"; return 1; fi
# Get paid on chain1
export BC_HOME=${CLIENT_1}
SENDER=$(getAddr $RICH)
RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=100000mycoin \
--sequence=$1 --to=$RELAY_ADDR --name=$RICH)
txSucceeded $? "$RES"
if [ $? != 0 ]; then echo "can't pay chain1!"; return 1; fi
# Get paid on chain2
export BC_HOME=${CLIENT_2}
SENDER=$(getAddr $RICH)
RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=100000mycoin \
--sequence=$2 --to=$RELAY_ADDR --name=$RICH)
txSucceeded $? "$RES"
if [ $? != 0 ]; then echo "can't pay chain2!"; return 1; fi
# Get paid on chain2
export BC_HOME=${CLIENT_2}
SENDER=$(getAddr $RICH)
RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=100000mycoin \
--sequence=$2 --to=$RELAY_ADDR --name=$RICH)
txSucceeded $? "$RES"
if [ $? != 0 ]; then echo "can't pay chain2!"; return 1; fi
# Initialize the relay (register both chains)
${SERVER_EXE} relay init --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \
--chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \
--genesis1=${BASE_DIR_1}/server/genesis.json --genesis2=${BASE_DIR_2}/server/genesis.json \
--from=$RELAY_KEY > ${BASE_DIR_1}/../relay.log
if [ $? != 0 ]; then echo "can't initialize relays"; cat ${BASE_DIR_1}/../relay.log; return 1; fi
# Initialize the relay (register both chains)
${SERVER_EXE} relay init --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \
--chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \
--genesis1=${BASE_DIR_1}/server/genesis.json --genesis2=${BASE_DIR_2}/server/genesis.json \
--from=$RELAY_KEY > ${BASE_DIR_1}/../relay.log
if [ $? != 0 ]; then echo "can't initialize relays"; cat ${BASE_DIR_1}/../relay.log; return 1; fi
# Now start the relay (constantly send packets)
${SERVER_EXE} relay start --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \
--chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \
--from=$RELAY_KEY >> ${BASE_DIR_1}/../relay.log &
sleep 2
PID_RELAY=$!
disown
# Now start the relay (constantly send packets)
${SERVER_EXE} relay start --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \
--chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \
--from=$RELAY_KEY >> ${BASE_DIR_1}/../relay.log &
sleep 2
PID_RELAY=$!
disown
# Return an error if it dies in the first two seconds to make sure it is running
ps $PID_RELAY >/dev/null
return $?
# Return an error if it dies in the first two seconds to make sure it is running
ps $PID_RELAY >/dev/null
return $?
}
# Load common then run these tests with shunit2!

View File

@ -8,77 +8,74 @@ RICH=${ACCOUNTS[0]}
POOR=${ACCOUNTS[4]}
oneTimeSetUp() {
quickSetup .basecoin_test_restart restart-chain
quickSetup .basecoin_test_restart restart-chain
}
oneTimeTearDown() {
quickTearDown
quickTearDown
}
test00PreRestart() {
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH)
txSucceeded $? "$TX"
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH)
txSucceeded $? "$TX"
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
checkAccount $SENDER "1" "9007199254740000"
checkAccount $RECV "0" "992"
checkAccount $SENDER "1" "9007199254740000"
checkAccount $RECV "0" "992"
# make sure tx is indexed
checkSendTx $HASH $TX_HEIGHT $SENDER "992"
# make sure tx is indexed
checkSendTx $HASH $TX_HEIGHT $SENDER "992"
}
test01OnRestart() {
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
SENDER=$(getAddr $RICH)
RECV=$(getAddr $POOR)
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=10000mycoin --sequence=2 --to=$RECV --name=$RICH)
txSucceeded $? "$TX"
if [ $? != 0 ]; then echo "can't make tx!"; return 1; fi
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=10000mycoin --sequence=2 --to=$RECV --name=$RICH)
txSucceeded $? "$TX"
if [ $? != 0 ]; then echo "can't make tx!"; return 1; fi
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
HASH=$(echo $TX | jq .hash | tr -d \")
TX_HEIGHT=$(echo $TX | jq .height)
# wait til we have quite a few blocks... like at least 20,
# so the query command won't just wait for the next eg. 7 blocks to verify the result
echo "waiting to generate lots of blocks..."
sleep 5
echo "done waiting!"
# wait til we have quite a few blocks... like at least 20,
# so the query command won't just wait for the next eg. 7 blocks to verify the result
echo "waiting to generate lots of blocks..."
sleep 5
echo "done waiting!"
# last minute tx just at the block cut-off...
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=20000mycoin --sequence=3 --to=$RECV --name=$RICH)
txSucceeded $? "$TX"
if [ $? != 0 ]; then echo "can't make second tx!"; return 1; fi
# last minute tx just at the block cut-off...
TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=20000mycoin --sequence=3 --to=$RECV --name=$RICH)
txSucceeded $? "$TX"
if [ $? != 0 ]; then echo "can't make second tx!"; return 1; fi
# now we do a restart...
quickTearDown
startServer $BASE_DIR/server $BASE_DIR/${SERVER_EXE}.log
if [ $? != 0 ]; then echo "can't restart server!"; return 1; fi
# now we do a restart...
quickTearDown
startServer $BASE_DIR/server $BASE_DIR/${SERVER_EXE}.log
if [ $? != 0 ]; then echo "can't restart server!"; return 1; fi
# make sure queries still work properly, with all 3 tx now executed
echo "Checking state after restart..."
checkAccount $SENDER "3" "9007199254710000"
checkAccount $RECV "0" "30992"
# make sure queries still work properly, with all 3 tx now executed
echo "Checking state after restart..."
checkAccount $SENDER "3" "9007199254710000"
checkAccount $RECV "0" "30992"
# make sure tx is indexed
checkSendTx $HASH $TX_HEIGHT $SENDER "10000"
# make sure tx is indexed
checkSendTx $HASH $TX_HEIGHT $SENDER "10000"
# for double-check of logs
if [ -n "$DEBUG" ]; then
cat $BASE_DIR/${SERVER_EXE}.log;
fi
# for double-check of logs
if [ -n "$DEBUG" ]; then
cat $BASE_DIR/${SERVER_EXE}.log;
fi
}
# load and run these tests with shunit2!
# Load common then run these tests with shunit2!
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory
# load common helpers
. $DIR/common.sh
. $DIR/shunit2