Contract test [GET] (#19)

Closes: #17
Depends on: cosmos/cosmos-sdk#4470
This commit is contained in:
Karoly Albert Szabo 2019-06-08 16:04:45 +02:00 committed by Alessio Treglia
parent 3d5780c343
commit 2945a0510e
13 changed files with 765 additions and 467 deletions

View File

@ -391,6 +391,24 @@ jobs:
- store_artifacts:
path: /go/src/github.com/cosmos/gaia/gaia-windows-res.yml
contract_tests:
<<: *linux_defaults
steps:
- attach_workspace:
at: /tmp/workspace
- checkout
- setup_remote_docker:
docker_layer_caching: true
- run:
name: Get Node.js and test REST implementation against swagger documentation at https://cosmos.network/rpc/
command: |
go get github.com/snikch/goodman/cmd/goodman
make build
make build-contract-tests-hooks
make setup-contract-tests-data
export PATH=~/.local/bin:$PATH
./contrib/get_node.sh && make contract-tests
workflows:
version: 2
test-suite:
@ -469,4 +487,7 @@ workflows:
- master
requires:
- setup_dependencies
- contract_tests:
requires:
- setup_dependencies

1
.gitignore vendored
View File

@ -45,3 +45,4 @@ dependency-graph.png
*.aux
*.out
*.synctex.gz
contract_tests/*

View File

@ -4,6 +4,7 @@ PACKAGES_SIMTEST=$(shell go list ./... | grep '/simulation')
VERSION := $(shell echo $(shell git describe --tags) | sed 's/^v//')
COMMIT := $(shell git log -1 --format='%H')
LEDGER_ENABLED ?= true
SDK_PACK := $(shell go list -m github.com/cosmos/cosmos-sdk | sed 's/ /\@/g')
export GO111MODULE = on
@ -78,6 +79,13 @@ endif
build-linux: go.sum
LEDGER_ENABLED=false GOOS=linux GOARCH=amd64 $(MAKE) build
build-contract-tests-hooks:
ifeq ($(OS),Windows_NT)
go build -mod=readonly $(BUILD_FLAGS) -o build/contract_tests.exe ./cmd/contract_tests
else
go build -mod=readonly $(BUILD_FLAGS) -o build/contract_tests ./cmd/contract_tests
endif
install: go.sum check-ledger
go install -mod=readonly $(BUILD_FLAGS) ./cmd/gaiad
go install -mod=readonly $(BUILD_FLAGS) ./cmd/gaiacli
@ -86,6 +94,7 @@ install-debug: go.sum
go install -mod=readonly $(BUILD_FLAGS) ./cmd/gaiadebug
########################################
### Tools & dependencies
@ -158,10 +167,34 @@ localnet-start: localnet-stop
localnet-stop:
docker-compose down
setup-contract-tests-data:
echo 'Prepare data for the contract tests'
rm -rf /tmp/contract_tests ; \
mkdir /tmp/contract_tests ; \
cp "${GOPATH}/pkg/mod/${SDK_PACK}/client/lcd/swagger-ui/swagger.yaml" /tmp/contract_tests/swagger.yaml ; \
./build/gaiad init --home /tmp/contract_tests/.gaiad --chain-id lcd contract-tests ; \
tar -xzf lcd_test/testdata/state.tar.gz -C /tmp/contract_tests/
start-gaia: setup-contract-tests-data
./build/gaiad --home /tmp/contract_tests/.gaiad start &
@sleep 2s
setup-transactions: start-gaia
@bash ./lcd_test/testdata/setup.sh
run-lcd-contract-tests:
@echo "Running Gaia LCD for contract tests"
./build/gaiacli rest-server --laddr tcp://0.0.0.0:8080 --home /tmp/contract_tests/.gaiacli --node http://localhost:26657 --chain-id lcd --trust-node true
contract-tests: setup-transactions
@echo "Running Gaia LCD for contract tests"
dredd && pkill gaiad
# include simulations
include sims.mk
.PHONY: all build-linux install install-debug \
go-mod-cache draw-deps clean \
go-mod-cache draw-deps clean build \
setup-transactions setup-contract-tests-data start-gaia run-lcd-contract-tests contract-tests \
check check-all check-build check-cover check-ledger check-unit check-race

View File

@ -0,0 +1,43 @@
package main
import (
"fmt"
"github.com/snikch/goodman/hooks"
"github.com/snikch/goodman/transaction"
)
func main() {
// This must be compiled beforehand and given to dredd as parameter, in the meantime the server should be running
h := hooks.NewHooks()
server := hooks.NewServer(hooks.NewHooksRunner(h))
h.BeforeAll(func(t []*transaction.Transaction) {
fmt.Println("Sleep 5 seconds before all modification")
})
h.BeforeEach(func(t *transaction.Transaction) {
fmt.Println("before each modification")
})
h.Before("/version > GET", func(t *transaction.Transaction) {
fmt.Println("before version TEST")
})
h.Before("/node_version > GET", func(t *transaction.Transaction) {
fmt.Println("before node_version TEST")
})
h.BeforeEachValidation(func(t *transaction.Transaction) {
fmt.Println("before each validation modification")
})
h.BeforeValidation("/node_version > GET", func(t *transaction.Transaction) {
fmt.Println("before validation node_version TEST")
})
h.After("/node_version > GET", func(t *transaction.Transaction) {
fmt.Println("after node_version TEST")
})
h.AfterEach(func(t *transaction.Transaction) {
fmt.Println("after each modification")
})
h.AfterAll(func(t []*transaction.Transaction) {
fmt.Println("after all modification")
})
server.Serve()
defer server.Listener.Close()
fmt.Print(h)
}

14
contrib/get_node.sh Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
VERSION=v11.15.0
NODE_FULL=node-${VERSION}-linux-x64
mkdir -p ~/.local/bin
mkdir -p ~/.local/node
wget http://nodejs.org/dist/${VERSION}/${NODE_FULL}.tar.gz -O ~/.local/node/${NODE_FULL}.tar.gz
tar -xzf ~/.local/node/${NODE_FULL}.tar.gz -C ~/.local/node/
ln -s ~/.local/node/${NODE_FULL}/bin/node ~/.local/bin/node
ln -s ~/.local/node/${NODE_FULL}/bin/npm ~/.local/bin/npm
export PATH=~/.local/bin:$PATH
npm i -g dredd@11.0.1
ln -s ~/.local/node/${NODE_FULL}/bin/dredd ~/.local/bin/dredd

33
dredd.yml Normal file
View File

@ -0,0 +1,33 @@
color: true
dry-run: null
hookfiles: build/contract_tests
language: go
require: null
server: make run-lcd-contract-tests
server-wait: 5
init: false
custom: {}
names: false
only: []
reporter: []
output: []
header: []
sorted: false
user: null
inline-errors: false
details: false
method: [GET]
loglevel: warning
path: []
hooks-worker-timeout: 5000
hooks-worker-connect-timeout: 1500
hooks-worker-connect-retry: 500
hooks-worker-after-connect-wait: 100
hooks-worker-term-timeout: 5000
hooks-worker-term-retry: 500
hooks-worker-handler-host: 127.0.0.1
hooks-worker-handler-port: 61321
config: ./dredd.yml
# This path accepts no variables
blueprint: /tmp/contract_tests/swagger.yaml
endpoint: 'http://127.0.0.1:8080'

4
go.mod
View File

@ -15,10 +15,12 @@ require (
github.com/otiai10/copy v1.0.1
github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776 // indirect
github.com/pelletier/go-toml v1.4.0 // indirect
github.com/pkg/errors v0.8.1
github.com/prometheus/common v0.4.1 // indirect
github.com/prometheus/procfs v0.0.0-20190523193104-a7aeb8df3389 // indirect
github.com/rakyll/statik v0.1.6 // indirect
github.com/rakyll/statik v0.1.6
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a // indirect
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/cobra v0.0.4
github.com/spf13/viper v1.4.0

2
go.sum
View File

@ -182,6 +182,8 @@ github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa h1:YJfZp12Z3AFhSBeXOlv4BO55RMwPn2NoQeDsrdWnBtY=
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=

478
lcd_test/helpers.go Normal file
View File

@ -0,0 +1,478 @@
package lcdtest
import (
"bytes"
"fmt"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/lcd"
"github.com/cosmos/cosmos-sdk/codec"
crkeys "github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/tests"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/genaccounts"
"github.com/cosmos/cosmos-sdk/x/crisis"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/genutil"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/staking"
gapp "github.com/cosmos/gaia/app"
"github.com/pkg/errors"
"github.com/spf13/viper"
"github.com/tendermint/go-amino"
tmcfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/libs/cli"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
"io/ioutil"
"net"
"os"
"path/filepath"
"sort"
"strings"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
nm "github.com/tendermint/tendermint/node"
"github.com/tendermint/tendermint/p2p"
pvm "github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/proxy"
tmrpc "github.com/tendermint/tendermint/rpc/lib/server"
tmtypes "github.com/tendermint/tendermint/types"
)
// TODO: Make InitializeTestLCD safe to call in multiple tests at the same time
// InitializeLCD starts Tendermint and the LCD in process, listening on
// their respective sockets where nValidators is the total number of validators
// and initAddrs are the accounts to initialize with some stake tokens. It
// returns a cleanup function, a set of validator public keys, and a port.
func InitializeLCD(nValidators int, initAddrs []sdk.AccAddress, minting bool, portExt ...string) (
cleanup func(), valConsPubKeys []crypto.PubKey, valOperAddrs []sdk.ValAddress, port string, err error) {
config, err := GetConfig()
if err != nil {
return
}
config.Consensus.TimeoutCommit = 100
config.Consensus.SkipTimeoutCommit = false
config.TxIndex.IndexAllTags = true
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
logger = log.NewFilter(logger, log.AllowError())
db := dbm.NewMemDB()
app := gapp.NewGaiaApp(logger, db, nil, true, 0)
cdc = gapp.MakeCodec()
genDoc, valConsPubKeys, valOperAddrs, privVal, err := defaultGenesis(config, nValidators, initAddrs, minting)
if err != nil {
return
}
var listenAddr string
if len(portExt) == 0 {
listenAddr, port, err = server.FreeTCPAddr()
if err != nil {
return
}
} else {
listenAddr = fmt.Sprintf("tcp://0.0.0.0:%s", portExt[0])
port = portExt[0]
}
// XXX: Need to set this so LCD knows the tendermint node address!
viper.Set(client.FlagNode, config.RPC.ListenAddress)
viper.Set(client.FlagChainID, genDoc.ChainID)
// TODO Set to false once the upstream Tendermint proof verification issue is fixed.
viper.Set(client.FlagTrustNode, true)
node, err := startTM(config, logger, genDoc, privVal, app)
if err != nil {
return
}
tests.WaitForNextHeightTM(tests.ExtractPortFromAddress(config.RPC.ListenAddress))
lcdInstance, err := startLCD(logger, listenAddr, cdc)
if err != nil {
return
}
tests.WaitForLCDStart(port)
tests.WaitForHeight(1, port)
cleanup = func() {
logger.Debug("cleaning up LCD initialization")
err = node.Stop()
if err != nil {
logger.Error(err.Error())
}
node.Wait()
err = lcdInstance.Close()
if err != nil {
logger.Error(err.Error())
}
}
return cleanup, valConsPubKeys, valOperAddrs, port, err
}
func defaultGenesis(config *tmcfg.Config, nValidators int, initAddrs []sdk.AccAddress, minting bool) (
genDoc *tmtypes.GenesisDoc, valConsPubKeys []crypto.PubKey, valOperAddrs []sdk.ValAddress, privVal *pvm.FilePV, err error) {
privVal = pvm.LoadOrGenFilePV(config.PrivValidatorKeyFile(),
config.PrivValidatorStateFile())
privVal.Reset()
if nValidators < 1 {
err = errors.New("InitializeLCD must use at least one validator")
return
}
genesisFile := config.GenesisFile()
genDoc, err = tmtypes.GenesisDocFromFile(genesisFile)
if err != nil {
return
}
genDoc.Validators = nil
err = genDoc.SaveAs(genesisFile)
if err != nil {
return
}
// append any additional (non-proposing) validators
var genTxs []auth.StdTx
var accs []genaccounts.GenesisAccount
for i := 0; i < nValidators; i++ {
operPrivKey := secp256k1.GenPrivKey()
operAddr := operPrivKey.PubKey().Address()
pubKey := privVal.GetPubKey()
power := int64(100)
if i > 0 {
pubKey = ed25519.GenPrivKey().PubKey()
power = 1
}
startTokens := sdk.TokensFromTendermintPower(power)
msg := staking.NewMsgCreateValidator(
sdk.ValAddress(operAddr),
pubKey,
sdk.NewCoin(sdk.DefaultBondDenom, startTokens),
staking.NewDescription(fmt.Sprintf("validator-%d", i+1), "", "", ""),
staking.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
sdk.OneInt(),
)
stdSignMsg := auth.StdSignMsg{
ChainID: genDoc.ChainID,
Msgs: []sdk.Msg{msg},
}
var sig []byte
sig, err = operPrivKey.Sign(stdSignMsg.Bytes())
if err != nil {
return
}
transaction := auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, []auth.StdSignature{{Signature: sig, PubKey: operPrivKey.PubKey()}}, "")
genTxs = append(genTxs, transaction)
valConsPubKeys = append(valConsPubKeys, pubKey)
valOperAddrs = append(valOperAddrs, sdk.ValAddress(operAddr))
accAuth := auth.NewBaseAccountWithAddress(sdk.AccAddress(operAddr))
accTokens := sdk.TokensFromTendermintPower(150)
accAuth.Coins = sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, accTokens)}
accs = append(accs, genaccounts.NewGenesisAccount(&accAuth))
}
genesisState := gapp.NewDefaultGenesisState()
genDoc.AppState, err = cdc.MarshalJSON(genesisState)
if err != nil {
return
}
genesisState, err = genutil.SetGenTxsInAppGenesisState(cdc, genesisState, genTxs)
if err != nil {
return
}
// add some tokens to init accounts
stakingDataBz := genesisState[staking.ModuleName]
var stakingData staking.GenesisState
cdc.MustUnmarshalJSON(stakingDataBz, &stakingData)
// add some tokens to init accounts
for _, addr := range initAddrs {
accAuth := auth.NewBaseAccountWithAddress(addr)
accTokens := sdk.TokensFromTendermintPower(100)
accAuth.Coins = sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, accTokens)}
acc := genaccounts.NewGenesisAccount(&accAuth)
accs = append(accs, acc)
}
// distr data
distrDataBz := genesisState[distr.ModuleName]
var distrData distr.GenesisState
cdc.MustUnmarshalJSON(distrDataBz, &distrData)
distrData.FeePool.CommunityPool = sdk.DecCoins{sdk.DecCoin{Denom: "test", Amount: sdk.NewDecFromInt(sdk.NewInt(10))}}
distrDataBz = cdc.MustMarshalJSON(distrData)
genesisState[distr.ModuleName] = distrDataBz
// now add the account tokens to the non-bonded pool
for _, acc := range accs {
accTokens := acc.Coins.AmountOf(sdk.DefaultBondDenom)
stakingData.Pool.NotBondedTokens = stakingData.Pool.NotBondedTokens.Add(accTokens)
}
genesisState[staking.ModuleName] = cdc.MustMarshalJSON(stakingData)
genesisState[genaccounts.ModuleName] = cdc.MustMarshalJSON(accs)
// mint genesis (none set within genesisState)
mintData := mint.DefaultGenesisState()
inflationMin := sdk.ZeroDec()
if minting {
inflationMin = sdk.MustNewDecFromStr("10000.0")
mintData.Params.InflationMax = sdk.MustNewDecFromStr("15000.0")
} else {
mintData.Params.InflationMax = inflationMin
}
mintData.Minter.Inflation = inflationMin
mintData.Params.InflationMin = inflationMin
mintDataBz := cdc.MustMarshalJSON(mintData)
genesisState[mint.ModuleName] = mintDataBz
// initialize crisis data
crisisDataBz := genesisState[crisis.ModuleName]
var crisisData crisis.GenesisState
cdc.MustUnmarshalJSON(crisisDataBz, &crisisData)
crisisData.ConstantFee = sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000)
crisisDataBz = cdc.MustMarshalJSON(crisisData)
genesisState[crisis.ModuleName] = crisisDataBz
//// double check inflation is set according to the minting boolean flag
if minting {
if !(mintData.Params.InflationMax.Equal(sdk.MustNewDecFromStr("15000.0")) &&
mintData.Minter.Inflation.Equal(sdk.MustNewDecFromStr("10000.0")) &&
mintData.Params.InflationMin.Equal(sdk.MustNewDecFromStr("10000.0"))) {
err = errors.New("Mint parameters does not correspond to their defaults")
return
}
} else {
if !(mintData.Params.InflationMax.Equal(sdk.ZeroDec()) &&
mintData.Minter.Inflation.Equal(sdk.ZeroDec()) &&
mintData.Params.InflationMin.Equal(sdk.ZeroDec())) {
err = errors.New("Mint parameters not equal to decimal 0")
return
}
}
appState, err := codec.MarshalJSONIndent(cdc, genesisState)
if err != nil {
return
}
genDoc.AppState = appState
return
}
// startTM creates and starts an in-process Tendermint node with memDB and
// in-process ABCI application. It returns the new node or any error that
// occurred.
//
// TODO: Clean up the WAL dir or enable it to be not persistent!
func startTM(
tmcfg *tmcfg.Config, logger log.Logger, genDoc *tmtypes.GenesisDoc,
privVal tmtypes.PrivValidator, app *gapp.GaiaApp,
) (*nm.Node, error) {
genDocProvider := func() (*tmtypes.GenesisDoc, error) { return genDoc, nil }
dbProvider := func(*nm.DBContext) (dbm.DB, error) { return dbm.NewMemDB(), nil }
nodeKey, err := p2p.LoadOrGenNodeKey(tmcfg.NodeKeyFile())
if err != nil {
return nil, err
}
node, err := nm.NewNode(
tmcfg,
privVal,
nodeKey,
proxy.NewLocalClientCreator(app),
genDocProvider,
dbProvider,
nm.DefaultMetricsProvider(tmcfg.Instrumentation),
logger.With("module", "node"),
)
if err != nil {
return nil, err
}
err = node.Start()
if err != nil {
return nil, err
}
tests.WaitForRPC(tmcfg.RPC.ListenAddress)
logger.Info("Tendermint running!")
return node, err
}
// startLCD starts the LCD.
func startLCD(logger log.Logger, listenAddr string, cdc *codec.Codec) (net.Listener, error) {
rs := lcd.NewRestServer(cdc)
registerRoutes(rs)
listener, err := tmrpc.Listen(listenAddr, tmrpc.DefaultConfig())
if err != nil {
return nil, err
}
go tmrpc.StartHTTPServer(listener, rs.Mux, logger, tmrpc.DefaultConfig()) //nolint:errcheck
return listener, nil
}
// NOTE: If making updates here also update cmd/gaia/cmd/gaiacli/main.go
func registerRoutes(rs *lcd.RestServer) {
client.RegisterRoutes(rs.CliCtx, rs.Mux)
gapp.ModuleBasics.RegisterRESTRoutes(rs.CliCtx, rs.Mux)
}
var cdc = amino.NewCodec()
func init() {
ctypes.RegisterAmino(cdc)
}
// CreateAddr adds an address to the key store and returns an address and seed.
// It also requires that the key could be created.
func CreateAddr(name, password string, kb crkeys.Keybase) (sdk.AccAddress, string, error) {
var (
err error
info crkeys.Info
seed string
)
info, seed, err = kb.CreateMnemonic(name, crkeys.English, password, crkeys.Secp256k1)
return sdk.AccAddress(info.GetPubKey().Address()), seed, err
}
// CreateAddr adds multiple address to the key store and returns the addresses and associated seeds in lexographical order by address.
// It also requires that the keys could be created.
func CreateAddrs(kb crkeys.Keybase, numAddrs int) (addrs []sdk.AccAddress, seeds, names, passwords []string, errs []error) {
var (
err error
info crkeys.Info
seed string
)
addrSeeds := AddrSeedSlice{}
for i := 0; i < numAddrs; i++ {
name := fmt.Sprintf("test%d", i)
password := "1234567890"
info, seed, err = kb.CreateMnemonic(name, crkeys.English, password, crkeys.Secp256k1)
if err != nil {
errs = append(errs, err)
}
addrSeeds = append(addrSeeds, AddrSeed{Address: sdk.AccAddress(info.GetPubKey().Address()), Seed: seed, Name: name, Password: password})
}
if len(errs) > 0 {
return
}
sort.Sort(addrSeeds)
for i := range addrSeeds {
addrs = append(addrs, addrSeeds[i].Address)
seeds = append(seeds, addrSeeds[i].Seed)
names = append(names, addrSeeds[i].Name)
passwords = append(passwords, addrSeeds[i].Password)
}
return
}
// AddrSeed combines an Address with the mnemonic of the private key to that address
type AddrSeed struct {
Address sdk.AccAddress
Seed string
Name string
Password string
}
// AddrSeedSlice implements `Interface` in sort package.
type AddrSeedSlice []AddrSeed
func (b AddrSeedSlice) Len() int {
return len(b)
}
// Less sorts lexicographically by Address
func (b AddrSeedSlice) Less(i, j int) bool {
// bytes package already implements Comparable for []byte.
switch bytes.Compare(b[i].Address.Bytes(), b[j].Address.Bytes()) {
case -1:
return true
case 0, 1:
return false
default:
panic("not fail-able with `bytes.Comparable` bounded [-1, 1].")
}
}
func (b AddrSeedSlice) Swap(i, j int) {
b[j], b[i] = b[i], b[j]
}
// InitClientHome initialises client home dir.
func InitClientHome(dir string) string {
var err error
if dir == "" {
dir, err = ioutil.TempDir("", "lcd_test")
if err != nil {
panic(err)
}
}
// TODO: this should be set in NewRestServer
// and pass down the CLIContext to achieve
// parallelism.
viper.Set(cli.HomeFlag, dir)
return dir
}
// makePathname creates a unique pathname for each test.
func makePathname() (string, error) {
p, err := os.Getwd()
if err != nil {
return "", err
}
sep := string(filepath.Separator)
return strings.Replace(p, sep, "_", -1), nil
}
// GetConfig returns a Tendermint config for the test cases.
func GetConfig() (*tmcfg.Config, error) {
pathname, err := makePathname()
if err != nil {
return nil, err
}
config := tmcfg.ResetTestRoot(pathname)
tmAddr, _, err := server.FreeTCPAddr()
if err != nil {
return nil, err
}
rcpAddr, _, err := server.FreeTCPAddr()
if err != nil {
return nil, err
}
grpcAddr, _, err := server.FreeTCPAddr()
if err != nil {
return nil, err
}
config.P2P.ListenAddress = tmAddr
config.RPC.ListenAddress = rcpAddr
config.RPC.GRPCListenAddress = grpcAddr
return config, nil
}

View File

@ -1,442 +1,43 @@
package lcd_test
package lcdtest
import (
"bytes"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
gapp "github.com/cosmos/gaia/app"
"github.com/cosmos/cosmos-sdk/client"
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/lcd"
"github.com/cosmos/cosmos-sdk/client/rpc"
clienttx "github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/client/utils"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys"
crkeys "github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/tests"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/rest"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/genaccounts"
bankrest "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
"github.com/cosmos/cosmos-sdk/x/crisis"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
distrrest "github.com/cosmos/cosmos-sdk/x/distribution/client/rest"
"github.com/cosmos/cosmos-sdk/x/genutil"
"github.com/cosmos/cosmos-sdk/x/gov"
govrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
gcutils "github.com/cosmos/cosmos-sdk/x/gov/client/utils"
"github.com/cosmos/cosmos-sdk/x/mint"
paramscutils "github.com/cosmos/cosmos-sdk/x/params/client/utils"
"github.com/cosmos/cosmos-sdk/x/slashing"
slashingrest "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingrest "github.com/cosmos/cosmos-sdk/x/staking/client/rest"
abci "github.com/tendermint/tendermint/abci/types"
tmcfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/tendermint/tendermint/libs/cli"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
nm "github.com/tendermint/tendermint/node"
"github.com/tendermint/tendermint/p2p"
pvm "github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/proxy"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
tmrpc "github.com/tendermint/tendermint/rpc/lib/server"
tmtypes "github.com/tendermint/tendermint/types"
)
var cdc = codec.New()
func init() {
codec.RegisterCrypto(cdc)
}
// makePathname creates a unique pathname for each test. It will panic if it
// cannot get the current working directory.
func makePathname() string {
p, err := os.Getwd()
if err != nil {
panic(err)
}
sep := string(filepath.Separator)
return strings.Replace(p, sep, "_", -1)
}
// GetConfig returns a Tendermint config for the test cases.
func GetConfig() *tmcfg.Config {
pathname := makePathname()
config := tmcfg.ResetTestRoot(pathname)
tmAddr, _, err := server.FreeTCPAddr()
if err != nil {
panic(err)
}
rcpAddr, _, err := server.FreeTCPAddr()
if err != nil {
panic(err)
}
grpcAddr, _, err := server.FreeTCPAddr()
if err != nil {
panic(err)
}
config.P2P.ListenAddress = tmAddr
config.RPC.ListenAddress = rcpAddr
config.RPC.GRPCListenAddress = grpcAddr
return config
}
// CreateAddr adds an address to the key store and returns an address and seed.
// It also requires that the key could be created.
func CreateAddr(t *testing.T, name, password string, kb crkeys.Keybase) (sdk.AccAddress, string) {
var (
err error
info crkeys.Info
seed string
)
info, seed, err = kb.CreateMnemonic(name, crkeys.English, password, crkeys.Secp256k1)
require.NoError(t, err)
return sdk.AccAddress(info.GetPubKey().Address()), seed
}
// CreateAddr adds multiple address to the key store and returns the addresses and associated seeds in lexographical order by address.
// It also requires that the keys could be created.
func CreateAddrs(t *testing.T, kb crkeys.Keybase, numAddrs int) (addrs []sdk.AccAddress, seeds, names, passwords []string) {
var (
err error
info crkeys.Info
seed string
)
addrSeeds := AddrSeedSlice{}
for i := 0; i < numAddrs; i++ {
name := fmt.Sprintf("test%d", i)
password := "1234567890"
info, seed, err = kb.CreateMnemonic(name, crkeys.English, password, crkeys.Secp256k1)
require.NoError(t, err)
addrSeeds = append(addrSeeds, AddrSeed{Address: sdk.AccAddress(info.GetPubKey().Address()), Seed: seed, Name: name, Password: password})
}
sort.Sort(addrSeeds)
for i := range addrSeeds {
addrs = append(addrs, addrSeeds[i].Address)
seeds = append(seeds, addrSeeds[i].Seed)
names = append(names, addrSeeds[i].Name)
passwords = append(passwords, addrSeeds[i].Password)
}
return addrs, seeds, names, passwords
}
// AddrSeed combines an Address with the mnemonic of the private key to that address
type AddrSeed struct {
Address sdk.AccAddress
Seed string
Name string
Password string
}
// AddrSeedSlice implements `Interface` in sort package.
type AddrSeedSlice []AddrSeed
func (b AddrSeedSlice) Len() int {
return len(b)
}
// Less sorts lexicographically by Address
func (b AddrSeedSlice) Less(i, j int) bool {
// bytes package already implements Comparable for []byte.
switch bytes.Compare(b[i].Address.Bytes(), b[j].Address.Bytes()) {
case -1:
return true
case 0, 1:
return false
default:
panic("not fail-able with `bytes.Comparable` bounded [-1, 1].")
}
}
func (b AddrSeedSlice) Swap(i, j int) {
b[j], b[i] = b[i], b[j]
}
// InitClientHome initialises client home dir.
func InitClientHome(t *testing.T, dir string) string {
var err error
if dir == "" {
dir, err = ioutil.TempDir("", "lcd_test")
require.NoError(t, err)
}
// TODO: this should be set in NewRestServer
// and pass down the CLIContext to achieve
// parallelism.
viper.Set(cli.HomeFlag, dir)
return dir
}
// TODO: Make InitializeTestLCD safe to call in multiple tests at the same time
// InitializeTestLCD starts Tendermint and the LCD in process, listening on
// their respective sockets where nValidators is the total number of validators
// and initAddrs are the accounts to initialize with some stake tokens. It
// returns a cleanup function, a set of validator public keys, and a port.
func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress, minting bool) (
cleanup func(), valConsPubKeys []crypto.PubKey, valOperAddrs []sdk.ValAddress, port string) {
if nValidators < 1 {
panic("InitializeTestLCD must use at least one validator")
}
config := GetConfig()
config.Consensus.TimeoutCommit = 100
config.Consensus.SkipTimeoutCommit = false
config.TxIndex.IndexAllTags = true
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
logger = log.NewFilter(logger, log.AllowError())
privVal := pvm.LoadOrGenFilePV(config.PrivValidatorKeyFile(),
config.PrivValidatorStateFile())
privVal.Reset()
db := dbm.NewMemDB()
app := gapp.NewGaiaApp(logger, db, nil, true, 0)
cdc = gapp.MakeCodec()
genesisFile := config.GenesisFile()
genDoc, err := tmtypes.GenesisDocFromFile(genesisFile)
require.Nil(t, err)
genDoc.Validators = nil
require.NoError(t, genDoc.SaveAs(genesisFile))
// append any additional (non-proposing) validators
var genTxs []auth.StdTx
var accs []genaccounts.GenesisAccount
for i := 0; i < nValidators; i++ {
operPrivKey := secp256k1.GenPrivKey()
operAddr := operPrivKey.PubKey().Address()
pubKey := privVal.GetPubKey()
power := int64(100)
if i > 0 {
pubKey = ed25519.GenPrivKey().PubKey()
power = 1
}
startTokens := sdk.TokensFromTendermintPower(power)
msg := staking.NewMsgCreateValidator(
sdk.ValAddress(operAddr),
pubKey,
sdk.NewCoin(sdk.DefaultBondDenom, startTokens),
staking.NewDescription(fmt.Sprintf("validator-%d", i+1), "", "", ""),
staking.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
sdk.OneInt(),
)
stdSignMsg := auth.StdSignMsg{
ChainID: genDoc.ChainID,
Msgs: []sdk.Msg{msg},
}
sig, err := operPrivKey.Sign(stdSignMsg.Bytes())
require.Nil(t, err)
tx := auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, []auth.StdSignature{{Signature: sig, PubKey: operPrivKey.PubKey()}}, "")
genTxs = append(genTxs, tx)
valConsPubKeys = append(valConsPubKeys, pubKey)
valOperAddrs = append(valOperAddrs, sdk.ValAddress(operAddr))
accAuth := auth.NewBaseAccountWithAddress(sdk.AccAddress(operAddr))
accTokens := sdk.TokensFromTendermintPower(150)
accAuth.Coins = sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, accTokens)}
accs = append(accs, genaccounts.NewGenesisAccount(&accAuth))
}
genesisState := gapp.NewDefaultGenesisState()
genDoc.AppState, err = cdc.MarshalJSON(genesisState)
require.NoError(t, err)
genesisState, err = genutil.SetGenTxsInAppGenesisState(cdc, genesisState, genTxs)
require.NoError(t, err)
// add some tokens to init accounts
stakingDataBz := genesisState[staking.ModuleName]
var stakingData staking.GenesisState
cdc.MustUnmarshalJSON(stakingDataBz, &stakingData)
for _, addr := range initAddrs {
accAuth := auth.NewBaseAccountWithAddress(addr)
accTokens := sdk.TokensFromTendermintPower(100)
accAuth.Coins = sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, accTokens)}
acc := genaccounts.NewGenesisAccount(&accAuth)
accs = append(accs, acc)
}
// distr data
distrDataBz := genesisState[distr.ModuleName]
var distrData distr.GenesisState
cdc.MustUnmarshalJSON(distrDataBz, &distrData)
distrData.FeePool.CommunityPool = sdk.DecCoins{sdk.DecCoin{"test", sdk.NewDecFromInt(sdk.NewInt(10))}}
distrDataBz = cdc.MustMarshalJSON(distrData)
genesisState[distr.ModuleName] = distrDataBz
// now add the account tokens to the non-bonded pool
for _, acc := range accs {
accTokens := acc.Coins.AmountOf(sdk.DefaultBondDenom)
stakingData.Pool.NotBondedTokens = stakingData.Pool.NotBondedTokens.Add(accTokens)
}
stakingDataBz = cdc.MustMarshalJSON(stakingData)
genesisState[staking.ModuleName] = stakingDataBz
genaccountsData := genaccounts.GenesisState(accs)
genaccountsDataBz := cdc.MustMarshalJSON(genaccountsData)
genesisState[genaccounts.ModuleName] = genaccountsDataBz
// mint genesis (none set within genesisState)
mintData := mint.DefaultGenesisState()
inflationMin := sdk.ZeroDec()
if minting {
inflationMin = sdk.MustNewDecFromStr("10000.0")
mintData.Params.InflationMax = sdk.MustNewDecFromStr("15000.0")
} else {
mintData.Params.InflationMax = inflationMin
}
mintData.Minter.Inflation = inflationMin
mintData.Params.InflationMin = inflationMin
mintDataBz := cdc.MustMarshalJSON(mintData)
genesisState[mint.ModuleName] = mintDataBz
// initialize crisis data
crisisDataBz := genesisState[crisis.ModuleName]
var crisisData crisis.GenesisState
cdc.MustUnmarshalJSON(crisisDataBz, &crisisData)
crisisData.ConstantFee = sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000)
crisisDataBz = cdc.MustMarshalJSON(crisisData)
genesisState[crisis.ModuleName] = crisisDataBz
// double check inflation is set according to the minting boolean flag
if minting {
require.Equal(t, sdk.MustNewDecFromStr("15000.0"), mintData.Params.InflationMax)
require.Equal(t, sdk.MustNewDecFromStr("10000.0"), mintData.Minter.Inflation)
require.Equal(t, sdk.MustNewDecFromStr("10000.0"), mintData.Params.InflationMin)
} else {
require.Equal(t, sdk.ZeroDec(), mintData.Params.InflationMax)
require.Equal(t, sdk.ZeroDec(), mintData.Minter.Inflation)
require.Equal(t, sdk.ZeroDec(), mintData.Params.InflationMin)
}
appState, err := codec.MarshalJSONIndent(cdc, genesisState)
require.NoError(t, err)
genDoc.AppState = appState
listenAddr, port, err := server.FreeTCPAddr()
require.NoError(t, err)
// NOTE: Need to set this so LCD knows the tendermint node address!
viper.Set(client.FlagNode, config.RPC.ListenAddress)
viper.Set(client.FlagChainID, genDoc.ChainID)
// TODO Set to false once the upstream Tendermint proof verification issue is fixed.
viper.Set(client.FlagTrustNode, true)
node := startTM(t, config, logger, genDoc, privVal, app)
require.NoError(t, err)
tests.WaitForNextHeightTM(tests.ExtractPortFromAddress(config.RPC.ListenAddress))
lcd, err := startLCD(logger, listenAddr, cdc, t)
require.NoError(t, err)
tests.WaitForLCDStart(port)
tests.WaitForHeight(1, port)
cleanup = func() {
logger.Debug("cleaning up LCD initialization")
node.Stop() //nolint:errcheck
node.Wait()
lcd.Close()
os.RemoveAll(config.RootDir)
}
return cleanup, valConsPubKeys, valOperAddrs, port
}
// startTM creates and starts an in-process Tendermint node with memDB and
// in-process ABCI application. It returns the new node or any error that
// occurred.
//
// TODO: Clean up the WAL dir or enable it to be not persistent!
func startTM(
t *testing.T, tmcfg *tmcfg.Config, logger log.Logger, genDoc *tmtypes.GenesisDoc,
privVal tmtypes.PrivValidator, app abci.Application,
) *nm.Node {
genDocProvider := func() (*tmtypes.GenesisDoc, error) { return genDoc, nil }
dbProvider := func(*nm.DBContext) (dbm.DB, error) { return dbm.NewMemDB(), nil }
nodeKey, err := p2p.LoadOrGenNodeKey(tmcfg.NodeKeyFile())
require.NoError(t, err)
node, err := nm.NewNode(
tmcfg,
privVal,
nodeKey,
proxy.NewLocalClientCreator(app),
genDocProvider,
dbProvider,
nm.DefaultMetricsProvider(tmcfg.Instrumentation),
logger.With("module", "node"),
)
require.NoError(t, err)
err = node.Start()
require.NoError(t, err)
tests.WaitForRPC(tmcfg.RPC.ListenAddress)
logger.Info("Tendermint running!")
return node
}
// startLCD starts the LCD.
func startLCD(logger log.Logger, listenAddr string, cdc *codec.Codec, t *testing.T) (net.Listener, error) {
rs := lcd.NewRestServer(cdc)
registerRoutes(rs)
listener, err := tmrpc.Listen(listenAddr, tmrpc.DefaultConfig())
if err != nil {
return nil, err
}
go tmrpc.StartHTTPServer(listener, rs.Mux, logger, tmrpc.DefaultConfig()) //nolint:errcheck
return listener, nil
}
// NOTE: If making updates here also update cmd/gaia/cmd/gaiacli/main.go
func registerRoutes(rs *lcd.RestServer) {
client.RegisterRoutes(rs.CliCtx, rs.Mux)
gapp.ModuleBasics.RegisterRESTRoutes(rs.CliCtx, rs.Mux)
}
// Request makes a test LCD test request. It returns a response object and a
// stringified response body.
func Request(t *testing.T, port, method, path string, payload []byte) (*http.Response, string) {

View File

@ -1,4 +1,4 @@
package lcd_test
package lcdtest
import (
"encoding/base64"
@ -52,7 +52,8 @@ func TestVersion(t *testing.T) {
t.SkipNow()
}
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{}, true)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{}, true)
require.NoError(t, err)
defer cleanup()
// node info
@ -75,14 +76,16 @@ func TestVersion(t *testing.T) {
}
func TestNodeStatus(t *testing.T) {
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{}, true)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{}, true)
require.NoError(t, err)
defer cleanup()
getNodeInfo(t, port)
getSyncStatus(t, port, false)
}
func TestBlock(t *testing.T) {
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{}, true)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{}, true)
require.NoError(t, err)
defer cleanup()
getBlock(t, port, -1, false)
getBlock(t, port, 2, false)
@ -90,7 +93,8 @@ func TestBlock(t *testing.T) {
}
func TestValidators(t *testing.T) {
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{}, true)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{}, true)
require.NoError(t, err)
defer cleanup()
resultVals := getValidatorSets(t, port, -1, false)
require.Contains(t, resultVals.Validators[0].Address.String(), "cosmosvalcons")
@ -100,10 +104,12 @@ func TestValidators(t *testing.T) {
}
func TestCoinSend(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
bz, err := hex.DecodeString("8FA6AB57AD6870F6B5B2E57735F38F2F30E73CB6")
@ -191,10 +197,12 @@ func TestCoinSend(t *testing.T) {
}
func TestCoinSendAccAuto(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
acc := getAccount(t, port, addr)
@ -216,10 +224,12 @@ func TestCoinSendAccAuto(t *testing.T) {
}
func TestCoinMultiSendGenerateOnly(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
// generate only
@ -239,11 +249,12 @@ func TestCoinMultiSendGenerateOnly(t *testing.T) {
}
func TestCoinSendGenerateSignAndBroadcast(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
acc := getAccount(t, port, addr)
@ -282,10 +293,12 @@ func TestCoinSendGenerateSignAndBroadcast(t *testing.T) {
}
func TestEncodeTx(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
res, body, _ := doTransferWithGas(t, port, seed, name1, memo, "", addr, "2", 1, false, false, fees)
@ -315,10 +328,12 @@ func TestEncodeTx(t *testing.T) {
}
func TestTxs(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
var emptyTxs []sdk.TxResponse
@ -367,10 +382,12 @@ func TestTxs(t *testing.T) {
}
func TestPoolParamsQuery(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, _, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, _ := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
defaultParams := staking.DefaultParams()
@ -395,7 +412,8 @@ func TestPoolParamsQuery(t *testing.T) {
}
func TestValidatorsQuery(t *testing.T) {
cleanup, valPubKeys, operAddrs, port := InitializeTestLCD(t, 1, []sdk.AccAddress{}, true)
cleanup, valPubKeys, operAddrs, port, err := InitializeLCD(1, []sdk.AccAddress{}, true)
require.NoError(t, err)
defer cleanup()
require.Equal(t, 1, len(valPubKeys))
@ -415,7 +433,8 @@ func TestValidatorsQuery(t *testing.T) {
}
func TestValidatorQuery(t *testing.T) {
cleanup, valPubKeys, operAddrs, port := InitializeTestLCD(t, 1, []sdk.AccAddress{}, true)
cleanup, valPubKeys, operAddrs, port, err := InitializeLCD(1, []sdk.AccAddress{}, true)
require.NoError(t, err)
defer cleanup()
require.Equal(t, 1, len(valPubKeys))
require.Equal(t, 1, len(operAddrs))
@ -425,11 +444,13 @@ func TestValidatorQuery(t *testing.T) {
}
func TestBonding(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, _, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
addr, _ := CreateAddr(t, name1, pw, kb)
cleanup, valPubKeys, operAddrs, port := InitializeTestLCD(t, 2, []sdk.AccAddress{addr}, false)
cleanup, valPubKeys, operAddrs, port, err := InitializeLCD(2, []sdk.AccAddress{addr}, false)
require.NoError(t, err)
tests.WaitForHeight(1, port)
defer cleanup()
@ -589,10 +610,12 @@ func TestBonding(t *testing.T) {
}
func TestSubmitProposal(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
acc := getAccount(t, port, addr)
@ -626,10 +649,12 @@ func TestSubmitProposal(t *testing.T) {
}
func TestSubmitCommunityPoolSpendProposal(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
acc := getAccount(t, port, addr)
@ -663,10 +688,12 @@ func TestSubmitCommunityPoolSpendProposal(t *testing.T) {
}
func TestSubmitParamChangeProposal(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
acc := getAccount(t, port, addr)
@ -700,10 +727,12 @@ func TestSubmitParamChangeProposal(t *testing.T) {
}
func TestDeposit(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
acc := getAccount(t, port, addr)
@ -759,10 +788,12 @@ func TestDeposit(t *testing.T) {
}
func TestVote(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, operAddrs, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, operAddrs, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
acc := getAccount(t, port, addr)
@ -846,10 +877,12 @@ func TestVote(t *testing.T) {
}
func TestUnjail(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, _, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, valPubKeys, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, _ := CreateAddr(t, name1, pw, kb)
cleanup, valPubKeys, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
// NOTE: any less than this and it fails
@ -865,11 +898,13 @@ func TestUnjail(t *testing.T) {
}
func TestProposalsQuery(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addrs, seeds, names, passwords := CreateAddrs(t, kb, 2)
addrs, seeds, names, passwords, errors := CreateAddrs(kb, 2)
require.Empty(t, errors)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addrs[0], addrs[1]}, true)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addrs[0], addrs[1]}, true)
require.NoError(t, err)
defer cleanup()
depositParam := getDepositParam(t, port)
@ -995,19 +1030,21 @@ func TestProposalsQuery(t *testing.T) {
}
func TestSlashingGetParams(t *testing.T) {
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{}, true)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{}, true)
require.NoError(t, err)
defer cleanup()
res, body := Request(t, port, "GET", "/slashing/parameters", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var params slashing.Params
err := cdc.UnmarshalJSON([]byte(body), &params)
err = cdc.UnmarshalJSON([]byte(body), &params)
require.NoError(t, err)
}
func TestDistributionGetParams(t *testing.T) {
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{}, true)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{}, true)
require.NoError(t, err)
defer cleanup()
res, body := Request(t, port, "GET", "/distribution/parameters", nil)
@ -1016,10 +1053,12 @@ func TestDistributionGetParams(t *testing.T) {
}
func TestDistributionFlow(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, seed, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, valAddrs, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, seed := CreateAddr(t, name1, pw, kb)
cleanup, _, valAddrs, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
valAddr := valAddrs[0]
@ -1092,10 +1131,12 @@ func TestDistributionFlow(t *testing.T) {
}
func TestMintingQueries(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, _, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, _ := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
res, body := Request(t, port, "GET", "/minting/parameters", nil)
@ -1118,10 +1159,12 @@ func TestMintingQueries(t *testing.T) {
}
func TestAccountBalanceQuery(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
kb, err := keys.NewKeyBaseFromDir(InitClientHome(""))
require.NoError(t, err)
addr, _, err := CreateAddr(name1, pw, kb)
require.NoError(t, err)
cleanup, _, _, port, err := InitializeLCD(1, []sdk.AccAddress{addr}, true)
require.NoError(t, err)
addr, _ := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
bz, err := hex.DecodeString("8FA6AB57AD6870F6B5B2E57735F38F2F30E73CB6")

27
lcd_test/testdata/setup.sh vendored Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env bash
PASSWORD="1234567890"
ADDR="cosmos16xyempempp92x9hyzz9wrgf94r6j9h5f06pxxv"
RECEIVER="cosmos17gx5vwpm0y2k59tw0x00ccug234n56cgltx2w2"
VALIDATOR="cosmosvaloper16xyempempp92x9hyzz9wrgf94r6j9h5f2w4n2l"
AMOUNT="1000000stake"
CHAIN="lcd"
PROPOSALID="2"
HOME="/tmp/contract_tests/.gaiacli"
SWAGGER='/tmp/contract_tests/swagger.yaml'
# sleeping a whole second between each step is a conservative precaution
# check lcd_test/testdata/state.tar.gz -> .gaiad/config/config.toml precommit_timeout = 500ms
sleep 1s
echo ${PASSWORD} | ./build/gaiacli tx gov submit-proposal --home ${HOME} --from ${ADDR} --chain-id ${CHAIN} --type text --title test --description test_description --deposit 10000stake --yes
sleep 1s
echo ${PASSWORD} | ./build/gaiacli tx gov deposit --home ${HOME} --from ${ADDR} --chain-id ${CHAIN} ${PROPOSALID} 1000000000stake --yes
sleep 1s
echo ${PASSWORD} | ./build/gaiacli tx gov vote --home ${HOME} --from ${ADDR} --yes --chain-id ${CHAIN} ${PROPOSALID} Yes
sleep 1s
HASH=$(echo ${PASSWORD} | ./build/gaiacli tx send --home ${HOME} ${ADDR} ${RECEIVER} ${AMOUNT} --yes --chain-id ${CHAIN} | awk '/txhash.*/{print $2}')
sed -i.bak -e "s/BCBE20E8D46758B96AE5883B792858296AC06E51435490FBDCAE25A72B3CC76B/${HASH}/g" "${SWAGGER}"
echo "Replaced dummy with actual transaction hash ${HASH}"
sleep 1s
echo ${PASSWORD} | ./build/gaiacli tx staking unbond --home ${HOME} --from ${ADDR} ${VALIDATOR} 100stake --yes --chain-id ${CHAIN}

BIN
lcd_test/testdata/state.tar.gz vendored Normal file

Binary file not shown.