Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration tests infrastructure refactoring. Separation of creation … #1492

Merged
merged 48 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f3fb43f
Integration tests infrastructure refactoring. Separation of creation …
alexeykiselev Sep 10, 2024
f2281c2
Merge branch 'master' into itest-infra-refactoring
alexeykiselev Sep 10, 2024
e1dfe34
Merge branch 'master' into itest-infra-refactoring
alexeykiselev Sep 10, 2024
b5a2fe1
Update GolangCI-Lint to version 1.60.3.
alexeykiselev Sep 10, 2024
88280f6
Handle linter issue.
alexeykiselev Sep 10, 2024
47e161c
Fixed logging of diverged state hashes.
alexeykiselev Sep 11, 2024
8235936
Merge branch 'master' into itest-infra-refactoring
alexeykiselev Sep 12, 2024
548e3cb
Better error handling and other requested changes implemented.
alexeykiselev Sep 13, 2024
5382770
Fix error handling by adding named return parameter.
alexeykiselev Sep 13, 2024
3fbb2a3
Activation of feature "Fee Sponsorship" added to some negative tests.
alexeykiselev Sep 13, 2024
4ce1485
Replaced waiting for activation of sponsorship by waiting for the cer…
alexeykiselev Sep 13, 2024
b6d3533
Merge branch 'master' into itest-infra-refactoring
alexeykiselev Sep 13, 2024
e21ee4a
Introduce constant for default sponsorship activation height. Comment…
alexeykiselev Sep 13, 2024
c3a7ce2
Merge branch 'itest-infra-refactoring' of github.com:wavesplatform/go…
alexeykiselev Sep 13, 2024
12ef74e
Few itests fixed by using height to build expected data.
alexeykiselev Sep 16, 2024
f12e92d
Merge branch 'master' into itest-infra-refactoring
alexeykiselev Sep 16, 2024
4c4b314
Default XTN buyback period increased to 4 blocks.
alexeykiselev Sep 18, 2024
cae47a7
New utility function to wait for new height if it lower than given ad…
alexeykiselev Sep 18, 2024
f037586
Merge branch 'master' into itest-infra-refactoring
alexeykiselev Sep 18, 2024
7588ded
Waiting for height added to one more blinking test.
alexeykiselev Sep 18, 2024
e03bbb9
More blinking tests fixed by adding waiting for new height.
alexeykiselev Sep 18, 2024
2aba685
Two more blinking tests fixed.
alexeykiselev Sep 18, 2024
a31e3ce
Waiting for height 3 added to all related test.
alexeykiselev Sep 19, 2024
65073e7
Merge branch 'master' into itest-infra-refactoring
nickeskov Sep 19, 2024
42e70d0
Waiting for certain height removed from all blinking tests.
alexeykiselev Sep 20, 2024
e5dc67d
Implemented function to request balances by list of addresses in a sy…
alexeykiselev Sep 24, 2024
bc4782c
Merge branch 'master' into itest-infra-refactoring
alexeykiselev Sep 24, 2024
b0602e6
Merge branch 'itest-infra-refactoring' into remove-waiting
alexeykiselev Sep 24, 2024
8bf75e8
Merge branch 'itest-infra-refactoring' of github.com:wavesplatform/go…
alexeykiselev Sep 24, 2024
7eeac68
Merge branch 'master' into itest-infra-refactoring
alexeykiselev Sep 24, 2024
0da968f
Remove incorrect file.
alexeykiselev Sep 24, 2024
38d2836
Merge branch 'master' into itest-infra-refactoring
alexeykiselev Sep 25, 2024
8552b45
Merge branch 'master' into itest-infra-refactoring
nickeskov Sep 25, 2024
61d41e1
Reduce file permisions on test directories.
alexeykiselev Sep 26, 2024
dd86d8f
Add writing to itest logs directories.
alexeykiselev Sep 26, 2024
417f872
Add write permission to logs folders of itests.
alexeykiselev Sep 26, 2024
e81e4fc
Restored full permissions to itests folders.
alexeykiselev Sep 26, 2024
b6d6c1a
Run in parallel internals of some wait methods of 'NodesClients'.
nickeskov Sep 27, 2024
18ff648
Fix data race and refactor 'NodesClients.requestAvailableBalancesForA…
nickeskov Sep 27, 2024
9b17a38
Fix typo in 'getSynchronizedBalances'.
nickeskov Sep 27, 2024
779b049
Merge branch 'master' into itest-infra-refactoring
alexeykiselev Sep 27, 2024
af6aa8b
Fix bug with deadlock in 'NodesClients.WaitForConnectedPeers'.
nickeskov Sep 27, 2024
469b642
Refactor 'NodesClients.WaitForConnectedPeers'
nickeskov Sep 27, 2024
72e6a24
Move API key string to the constant.
alexeykiselev Sep 27, 2024
b7bdc83
Removed unnecessary context cancelling.
nickeskov Sep 27, 2024
e4e9d73
Merge branch 'itest-infra-refactoring.errgroup' into itest-infra-refa…
alexeykiselev Sep 27, 2024
d6f0f04
Handle error.
alexeykiselev Sep 27, 2024
62a5ca6
Merge branch 'master' into itest-infra-refactoring
nickeskov Sep 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions itests/alias_tx_api_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"testing"

"github.com/stretchr/testify/suite"

f "github.com/wavesplatform/gowaves/itests/fixtures"
"github.com/wavesplatform/gowaves/itests/testdata"
utl "github.com/wavesplatform/gowaves/itests/utilities"
Expand Down
142 changes: 142 additions & 0 deletions itests/clients/grpc_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package clients

import (
"context"
"math"
"testing"
"time"

"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/wrapperspb"

"github.com/wavesplatform/gowaves/itests/config"
"github.com/wavesplatform/gowaves/pkg/client"
"github.com/wavesplatform/gowaves/pkg/grpc/generated/waves"
g "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves/node/grpc"
"github.com/wavesplatform/gowaves/pkg/proto"
)

const defaultTimeout = 30 * time.Second

type balanceAtHeight struct {
impl Implementation
balance int64
height uint64
}

type GRPCClient struct {
impl Implementation
conn *grpc.ClientConn
timeout time.Duration
}

func NewGRPCClient(t *testing.T, impl Implementation, port string) *GRPCClient {
conn, err := grpc.NewClient(config.DefaultIP+":"+port, grpc.WithTransportCredentials(insecure.NewCredentials()))
assert.NoError(t, err, "failed to dial GRPC to %s", impl.String())
return &GRPCClient{impl: impl, conn: conn, timeout: defaultTimeout}
}

func (c *GRPCClient) GetFeatureActivationStatusInfo(t *testing.T, h int32) *g.ActivationStatusResponse {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
response, err := g.NewBlockchainApiClient(c.conn).GetActivationStatus(ctx, &g.ActivationStatusRequest{Height: h})
require.NoError(t, err, "[GRPC] failed to get feature activation status from %s node", c.impl.String())
return response
}

func (c *GRPCClient) GetHeight(t *testing.T) *client.BlocksHeight {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
h, err := g.NewBlocksApiClient(c.conn).GetCurrentHeight(ctx, &emptypb.Empty{}, grpc.EmptyCallOption{})
assert.NoError(t, err, "[GRPC] failed to get height from %s node", c.impl.String())
return &client.BlocksHeight{Height: uint64(h.Value)}
}

func (c *GRPCClient) GetBlock(t *testing.T, height uint64) *g.BlockWithHeight {
if height > math.MaxInt32 {
require.FailNow(t, "height is too large to be casted to int32")
}
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
block, err := g.NewBlocksApiClient(c.conn).GetBlock(ctx,
&g.BlockRequest{Request: &g.BlockRequest_Height{Height: int32(height)}, IncludeTransactions: true})
assert.NoError(t, err, "[GRPC] failed to get block from %s node", c.impl.String())
return block
}

func (c *GRPCClient) GetWavesBalance(t *testing.T, address proto.WavesAddress) *g.BalanceResponse_WavesBalances {
return c.getBalance(t, &g.BalancesRequest{Address: address.Bytes(), Assets: [][]byte{nil}}).GetWaves()
}

func (c *GRPCClient) GetAssetBalance(t *testing.T, address proto.WavesAddress, id []byte) *waves.Amount {
require.NotEmpty(t, id, "asset bytes must not be empty than calling %s node", c.impl.String())
return c.getBalance(t, &g.BalancesRequest{Address: address.Bytes(), Assets: [][]byte{id}}).GetAsset()
}

func (c *GRPCClient) GetAddressByAlias(t *testing.T, alias string) []byte {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
addr, err := g.NewAccountsApiClient(c.conn).ResolveAlias(ctx, &wrapperspb.StringValue{Value: alias})
assert.NoError(t, err, "failed to get address by alias from %s node", c.impl.String())
return addr.GetValue()
}

func (c *GRPCClient) GetAssetsInfo(t *testing.T, id []byte) *g.AssetInfoResponse {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
assetInfo, err := g.NewAssetsApiClient(c.conn).GetInfo(ctx, &g.AssetRequest{AssetId: id})
assert.NoError(t, err, "failed to get asset info from %s node", c.impl.String())
return assetInfo
}

func (c *GRPCClient) getBalance(t *testing.T, req *g.BalancesRequest) *g.BalanceResponse {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
stream, err := g.NewAccountsApiClient(c.conn).GetBalances(ctx, req, grpc.EmptyCallOption{})
assert.NoError(t, err, "[GRPC] failed to get stream from %s node", c.impl.String())
b, err := stream.Recv()
assert.NoError(t, err, "[GRPC] failed to get balance from %s node", c.impl.String())
return b
}

func (c *GRPCClient) syncedWavesAvailableBalance(
ctx context.Context, address proto.WavesAddress,
) (balanceAtHeight, error) {
beforeRsp, err := g.NewBlocksApiClient(c.conn).GetCurrentHeight(ctx, &emptypb.Empty{}, grpc.EmptyCallOption{})
if err != nil {
return balanceAtHeight{}, errors.Wrapf(err,
"syncedWavesAvailableBalance: failed to get initial height from %s node", c.impl.String())
}
before := uint64(beforeRsp.Value)

req := &g.BalancesRequest{Address: address.Bytes(), Assets: [][]byte{nil}}
stream, err := g.NewAccountsApiClient(c.conn).GetBalances(ctx, req, grpc.EmptyCallOption{})
if err != nil {
return balanceAtHeight{}, errors.Wrapf(err,
"syncedWavesAvailableBalance: failed to get balance stream from %s node", c.impl.String())
}
balanceRsp, err := stream.Recv()
if err != nil {
return balanceAtHeight{}, errors.Wrapf(err,
"syncedWavesAvailableBalance: failed to get balance from %s node", c.impl.String())
}
available := balanceRsp.GetWaves().Available

afterRsp, err := g.NewBlocksApiClient(c.conn).GetCurrentHeight(ctx, &emptypb.Empty{}, grpc.EmptyCallOption{})
if err != nil {
return balanceAtHeight{}, errors.Wrapf(err,
"syncedWavesAvailableBalance: failed to get height from %s node", c.impl.String())
}
after := uint64(afterRsp.Value)

if before != after {
return balanceAtHeight{}, errors.Errorf(
"syncedWavesAvailableBalance: height changed during balance check on %s node", c.impl.String())
}
return balanceAtHeight{impl: c.impl, balance: available, height: after}, nil
}
79 changes: 44 additions & 35 deletions itests/node_client/http_client.go → itests/clients/http_client.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package node_client
package clients

import (
"context"
Expand All @@ -8,137 +8,146 @@ import (

"github.com/stretchr/testify/require"

"github.com/wavesplatform/gowaves/itests/config"
d "github.com/wavesplatform/gowaves/itests/docker"
"github.com/wavesplatform/gowaves/pkg/client"
"github.com/wavesplatform/gowaves/pkg/crypto"
"github.com/wavesplatform/gowaves/pkg/proto"
)

type HttpClient struct {
type HTTPClient struct {
impl Implementation
cli *client.Client
timeout time.Duration
}

func NewHttpClient(t *testing.T, port string) *HttpClient {
func NewHTTPClient(t *testing.T, impl Implementation, port string) *HTTPClient {
c, err := client.NewClient(client.Options{
BaseUrl: "http://" + d.Localhost + ":" + port + "/",
BaseUrl: "http://" + config.DefaultIP + ":" + port + "/",
Client: &http.Client{Timeout: d.DefaultTimeout},
ApiKey: "itest-api-key",
ApiKey: d.DefaultAPIKey,
ChainID: 'L', // I tried to use constant `utilities.TestChainID`, but after all decided that a little duplication is better in this case.
})
require.NoError(t, err, "couldn't create go node api client")
return &HttpClient{
cli: c,
require.NoError(t, err, "couldn't create %s node HTTP API client", impl.String())
return &HTTPClient{
impl: impl,
cli: c,
// actually, there's no need to use such timeout because above we've already set default context for http client
timeout: 15 * time.Second,
}
}

func (c *HttpClient) GetHeight(t *testing.T) *client.BlocksHeight {
func (c *HTTPClient) GetHeight(t *testing.T) *client.BlocksHeight {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
h, _, err := c.cli.Blocks.Height(ctx)
require.NoError(t, err, "failed to get height from node")
require.NoError(t, err, "failed to get height from %s node", c.impl.String())
return h
}

func (c *HttpClient) StateHash(t *testing.T, height uint64) *proto.StateHash {
func (c *HTTPClient) StateHash(t *testing.T, height uint64) *proto.StateHash {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
stateHash, _, err := c.cli.Debug.StateHash(ctx, height)
require.NoError(t, err, "failed to get stateHash from node")
require.NoError(t, err, "failed to get stateHash from %s node", c.impl.String())
return stateHash
}

func (c *HttpClient) PrintMsg(t *testing.T, msg string) {
func (c *HTTPClient) PrintMsg(t *testing.T, msg string) {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
_, err := c.cli.Debug.PrintMsg(ctx, msg)
require.NoError(t, err, "failed to send Msg to node")
require.NoError(t, err, "failed to send Msg to %s node", c.impl.String())
}

func (c *HttpClient) GetAssetDetails(assetID crypto.Digest) (*client.AssetsDetail, error) {
func (c *HTTPClient) GetAssetDetails(assetID crypto.Digest) (*client.AssetsDetail, error) {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
details, _, err := c.cli.Assets.Details(ctx, assetID)
return details, err
}

func (c *HttpClient) TransactionInfo(t *testing.T, ID crypto.Digest) proto.Transaction {
func (c *HTTPClient) TransactionInfo(t *testing.T, id crypto.Digest) proto.Transaction {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
info, _, err := c.cli.Transactions.Info(ctx, ID)
require.NoError(t, err, "failed to get TransactionInfo from node")
info, _, err := c.cli.Transactions.Info(ctx, id)
require.NoError(t, err, "failed to get TransactionInfo from %s node", c.impl.String())
return info
}

func (c *HttpClient) TransactionInfoRaw(id crypto.Digest) (proto.Transaction, *client.Response, error) {
func (c *HTTPClient) TransactionInfoRaw(id crypto.Digest) (proto.Transaction, *client.Response, error) {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
return c.cli.Transactions.Info(ctx, id)
}

func (c *HttpClient) TransactionBroadcast(transaction proto.Transaction) (*client.Response, error) {
func (c *HTTPClient) TransactionBroadcast(transaction proto.Transaction) (*client.Response, error) {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
return c.cli.Transactions.Broadcast(ctx, transaction)
}

func (c *HttpClient) WavesBalance(t *testing.T, address proto.WavesAddress) *client.AddressesBalance {
func (c *HTTPClient) WavesBalance(t *testing.T, address proto.WavesAddress) *client.AddressesBalance {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
balance, _, err := c.cli.Addresses.Balance(ctx, address)
require.NoError(t, err)
require.NoError(t, err, "failed to get waves balance from %s node", c.impl.String())
return balance
}

func (c *HttpClient) AssetBalance(t *testing.T, address proto.WavesAddress, assetId crypto.Digest) *client.AssetsBalanceAndAsset {
func (c *HTTPClient) AssetBalance(
t *testing.T, address proto.WavesAddress, assetID crypto.Digest,
) *client.AssetsBalanceAndAsset {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
balance, _, err := c.cli.Assets.BalanceByAddressAndAsset(ctx, address, assetId)
require.NoError(t, err)
balance, _, err := c.cli.Assets.BalanceByAddressAndAsset(ctx, address, assetID)
require.NoError(t, err, "failed to get asset balance from %s node", c.impl.String())
return balance
}

func (c *HttpClient) ConnectedPeers() ([]*client.PeersConnectedRow, *client.Response, error) {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
func (c *HTTPClient) ConnectedPeers() ([]*client.PeersConnectedRow, *client.Response, error) {
return c.ConnectedPeersCtx(context.Background())
}

func (c *HTTPClient) ConnectedPeersCtx(ctx context.Context) ([]*client.PeersConnectedRow, *client.Response, error) {
ctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()
connectedPeers, resp, err := c.cli.Peers.Connected(ctx)
return connectedPeers, resp, err
}

func (c *HttpClient) BlockHeader(t *testing.T, height proto.Height) *client.Headers {
func (c *HTTPClient) BlockHeader(t *testing.T, height proto.Height) *client.Headers {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()

header, _, err := c.cli.Blocks.HeadersAt(ctx, height)
require.NoError(t, err)
require.NoError(t, err, "failed to get block header from %s node", c.impl.String())
return header
}

func (c *HttpClient) Rewards(t *testing.T) *client.RewardInfo {
func (c *HTTPClient) Rewards(t *testing.T) *client.RewardInfo {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()

rewardInfo, _, err := c.cli.Blockchain.Rewards(ctx)
require.NoError(t, err)
require.NoError(t, err, "failed to get rewards from %s node", c.impl.String())
return rewardInfo
}

func (c *HttpClient) RewardsAtHeight(t *testing.T, height proto.Height) *client.RewardInfo {
func (c *HTTPClient) RewardsAtHeight(t *testing.T, height proto.Height) *client.RewardInfo {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()

rewardInfo, _, err := c.cli.Blockchain.RewardsAtHeight(ctx, height)
require.NoError(t, err)
require.NoError(t, err, "failed to get rewards from %s node", c.impl.String())
return rewardInfo
}

func (c *HttpClient) RollbackToHeight(t *testing.T, height uint64, returnTxToUtx bool) *proto.BlockID {
func (c *HTTPClient) RollbackToHeight(t *testing.T, height uint64, returnTxToUtx bool) *proto.BlockID {
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()

blockID, _, err := c.cli.Debug.RollbackToHeight(ctx, height, returnTxToUtx)
require.NoError(t, err)
require.NoError(t, err, "failed to rollback to height on %s node", c.impl.String())
return blockID
}
9 changes: 9 additions & 0 deletions itests/clients/implementation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package clients

//go:generate stringer -type Implementation -trimprefix Node
type Implementation byte

const (
NodeGo Implementation = iota
NodeScala
)
24 changes: 24 additions & 0 deletions itests/clients/implementation_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading