feat(testnet): allow a single active Comet RPC service (#15711)
Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>
This commit is contained in:
co-authored by
Aleksandr Bezobchuk
parent
401d0d72c9
commit
06892b9bc4
@@ -0,0 +1,165 @@
|
||||
package testnet_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/simapp"
|
||||
cmtcfg "github.com/cometbft/cometbft/config"
|
||||
"github.com/cometbft/cometbft/rpc/client/http"
|
||||
dbm "github.com/cosmos/cosmos-db"
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testnet"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// A single comet server in a network runs an RPC server successfully.
|
||||
func TestCometRPC_SingleRPCServer(t *testing.T) {
|
||||
const nVals = 2
|
||||
|
||||
valPKs := testnet.NewValidatorPrivKeys(nVals)
|
||||
cmtVals := valPKs.CometGenesisValidators()
|
||||
stakingVals := cmtVals.StakingValidators()
|
||||
|
||||
const chainID = "comet-rpc-singleton"
|
||||
|
||||
b := testnet.DefaultGenesisBuilderOnlyValidators(
|
||||
chainID,
|
||||
stakingVals,
|
||||
sdk.NewCoin(sdk.DefaultBondDenom, sdk.DefaultPowerReduction),
|
||||
)
|
||||
|
||||
jGenesis := b.Encode()
|
||||
|
||||
// Logs shouldn't be necessary here because we are exercising CometStarter,
|
||||
// and only doing a very basic check that the RPC talks to the app.
|
||||
logger := log.NewNopLogger()
|
||||
|
||||
nodes, err := testnet.NewNetwork(nVals, func(idx int) *testnet.CometStarter {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
app := simapp.NewSimApp(
|
||||
logger,
|
||||
dbm.NewMemDB(),
|
||||
nil,
|
||||
true,
|
||||
simtestutil.NewAppOptionsWithFlagHome(rootDir),
|
||||
baseapp.SetChainID(chainID),
|
||||
)
|
||||
|
||||
cfg := cmtcfg.DefaultConfig()
|
||||
cfg.BaseConfig.DBBackend = "memdb"
|
||||
|
||||
cs := testnet.NewCometStarter(
|
||||
app,
|
||||
cfg,
|
||||
valPKs[idx].Val,
|
||||
jGenesis,
|
||||
rootDir,
|
||||
)
|
||||
|
||||
// Only enable the RPC on the first service.
|
||||
if idx == 0 {
|
||||
cs = cs.RPCListen()
|
||||
}
|
||||
|
||||
return cs
|
||||
})
|
||||
defer nodes.StopAndWait()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Once HTTP client to be shared across the following subtests.
|
||||
c, err := http.New(nodes[0].Config().RPC.ListenAddress, "/websocket")
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("status query", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
st, err := c.Status(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Simple assertion to ensure we have a functioning RPC.
|
||||
require.Equal(t, chainID, st.NodeInfo.Network)
|
||||
})
|
||||
|
||||
// Block until reported height is at least 1,
|
||||
// otherwise we can't make transactions.
|
||||
require.NoError(t, testnet.WaitForNodeHeight(nodes[0], 1, 10*time.Second))
|
||||
|
||||
t.Run("simple abci query", func(t *testing.T) {
|
||||
res, err := c.ABCIQuery(
|
||||
context.Background(),
|
||||
"/cosmos.bank.v1beta1.Query/TotalSupply",
|
||||
nil,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
registry := codectypes.NewInterfaceRegistry()
|
||||
cdc := codec.NewProtoCodec(registry)
|
||||
|
||||
var tsResp banktypes.QueryTotalSupplyResponse
|
||||
require.NoError(t, cdc.Unmarshal(res.Response.Value, &tsResp))
|
||||
|
||||
// Just check that something is reported in the supply.
|
||||
require.NotEmpty(t, tsResp.Supply)
|
||||
})
|
||||
}
|
||||
|
||||
// Starting two comet instances with an RPC server,
|
||||
// fails with a predictable error.
|
||||
func TestCometRPC_MultipleRPCError(t *testing.T) {
|
||||
const nVals = 2
|
||||
|
||||
valPKs := testnet.NewValidatorPrivKeys(nVals)
|
||||
cmtVals := valPKs.CometGenesisValidators()
|
||||
stakingVals := cmtVals.StakingValidators()
|
||||
|
||||
const chainID = "comet-rpc-multiple"
|
||||
|
||||
b := testnet.DefaultGenesisBuilderOnlyValidators(
|
||||
chainID,
|
||||
stakingVals,
|
||||
sdk.NewCoin(sdk.DefaultBondDenom, sdk.DefaultPowerReduction),
|
||||
)
|
||||
|
||||
jGenesis := b.Encode()
|
||||
|
||||
// Logs shouldn't be necessary here because we are exercising CometStarter.
|
||||
logger := log.NewNopLogger()
|
||||
|
||||
nodes, err := testnet.NewNetwork(nVals, func(idx int) *testnet.CometStarter {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
app := simapp.NewSimApp(
|
||||
logger,
|
||||
dbm.NewMemDB(),
|
||||
nil,
|
||||
true,
|
||||
simtestutil.NewAppOptionsWithFlagHome(rootDir),
|
||||
baseapp.SetChainID(chainID),
|
||||
)
|
||||
|
||||
cfg := cmtcfg.DefaultConfig()
|
||||
cfg.BaseConfig.DBBackend = "memdb"
|
||||
|
||||
return testnet.NewCometStarter(
|
||||
app,
|
||||
cfg,
|
||||
valPKs[idx].Val,
|
||||
jGenesis,
|
||||
rootDir,
|
||||
).RPCListen() // Every node has RPCListen enabled, which will cause a failure.
|
||||
})
|
||||
defer nodes.StopAndWait()
|
||||
|
||||
// Returned error is convertible to CometRPCInUseError.
|
||||
// We can't test the exact value because it includes a stack trace.
|
||||
require.Error(t, err)
|
||||
require.ErrorAs(t, err, new(testnet.CometRPCInUseError))
|
||||
}
|
||||
@@ -120,25 +120,15 @@ func TestCometStarter_PortContention(t *testing.T) {
|
||||
return reuseAddrs[rand.Intn(len(reuseAddrs))]
|
||||
})
|
||||
})
|
||||
|
||||
// Ensure nodes are stopped completely,
|
||||
// so that we don't get t.Cleanup errors around directories not being empty.
|
||||
defer nodes.StopAndWait()
|
||||
require.NoError(t, err)
|
||||
|
||||
heightAdvanced := false
|
||||
for j := 0; j < 40; j++ {
|
||||
cs := nodes[0].ConsensusState()
|
||||
if cs.GetLastHeight() < 2 {
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
|
||||
// Saw height advance.
|
||||
heightAdvanced = true
|
||||
break
|
||||
}
|
||||
|
||||
if !heightAdvanced {
|
||||
t.Fatalf("consensus height did not advance in approximately 10 seconds")
|
||||
}
|
||||
// Ensure that the height advances.
|
||||
// Looking for height 2 seems more meaningful than 1.
|
||||
require.NoError(t, testnet.WaitForNodeHeight(nodes[0], 2, 10*time.Second))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user