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

[Testing, Tooling] Expose integration app via gRPC/HTTP/WS #1017

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
8 changes: 8 additions & 0 deletions pkg/client/block/block_result.go
Original file line number Diff line number Diff line change
@@ -11,6 +11,14 @@ import (
type cometBlockResult coretypes.ResultBlock

func (cbr *cometBlockResult) Height() int64 {

//cdc := codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) cbrPreJSON, err := cdc.MarshalJSON(cbr)

//cbrJSON, err := json.MarshalIndent(cbrPreJSON, "", " ")
//if err != nil {
// panic(err)
//}
//fmt.Println(string(cbrJSON))
return cbr.Block.Header.Height
}

2 changes: 1 addition & 1 deletion pkg/client/interface.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:generate mockgen -destination=../../testutil/mockclient/events_query_client_mock.go -package=mockclient . Dialer,Connection,EventsQueryClient
//go:generate mockgen -destination=../../testutil/mockclient/block_client_mock.go -package=mockclient . Block,BlockClient
//go:generate mockgen -destination=../../testutil/mockclient/block_client_mock.go -package=mockclient . Block,BlockClient,BlockQueryClient
//go:generate mockgen -destination=../../testutil/mockclient/delegation_client_mock.go -package=mockclient . DelegationClient
//go:generate mockgen -destination=../../testutil/mockclient/tx_client_mock.go -package=mockclient . TxContext,TxClient
//go:generate mockgen -destination=../../testutil/mockclient/supplier_client_mock.go -package=mockclient . SupplierClient
149 changes: 149 additions & 0 deletions testutil/e2e/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package e2e

import (
"context"
"errors"
"net"
"net/http"
"sync"
"testing"

"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/gorilla/websocket"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/grpc-ecosystem/grpc-gateway/utilities"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

coretypes "github.com/cometbft/cometbft/rpc/core/types"

"github.com/pokt-network/poktroll/testutil/integration"
"github.com/pokt-network/poktroll/testutil/testclient"
)

// E2EApp wraps an integration.App and provides both gRPC and WebSocket servers for end-to-end testing
type E2EApp struct {
*integration.App
grpcServer *grpc.Server
grpcListener net.Listener
wsServer *http.Server
wsListener net.Listener
wsUpgrader websocket.Upgrader
wsConnMutex sync.RWMutex
wsConnections map[*websocket.Conn]map[string]struct{} // maps connections to their subscribed event queries
blockEventChan chan *coretypes.ResultEvent
}

// NewE2EApp creates a new E2EApp instance with integration.App, gRPC, and WebSocket servers
func NewE2EApp(t *testing.T, opts ...integration.IntegrationAppOptionFn) *E2EApp {
t.Helper()

// Initialize and start gRPC server
creds := insecure.NewCredentials()
grpcServer := grpc.NewServer(grpc.Creds(creds))
mux := runtime.NewServeMux()

rootPattern, err := runtime.NewPattern(
1,
[]int{int(utilities.OpLitPush), int(utilities.OpNop)},
[]string{""},
"",
)
require.NoError(t, err)

// Create the integration app
opts = append(opts, integration.WithGRPCServer(grpcServer))
app := integration.NewCompleteIntegrationApp(t, opts...)
app.RegisterGRPCServer(grpcServer)

flagSet := testclient.NewFlagSet(t, "tcp://127.0.0.1:42070")
keyRing := keyring.NewInMemory(app.GetCodec())
clientCtx := testclient.NewLocalnetClientCtx(t, flagSet).WithKeyring(keyRing)

// Register the handler with the mux
client, err := grpc.NewClient("127.0.0.1:42069", grpc.WithInsecure())
require.NoError(t, err)

for _, mod := range app.GetModuleManager().Modules {
mod.(module.AppModuleBasic).RegisterGRPCGatewayRoutes(clientCtx, mux)
}

// Create listeners for gRPC, WebSocket, and HTTP
grpcListener, err := net.Listen("tcp", "127.0.0.1:42069")
require.NoError(t, err, "failed to create gRPC listener")

wsListener, err := net.Listen("tcp", "127.0.0.1:6969")
require.NoError(t, err, "failed to create WebSocket listener")

e2eApp := &E2EApp{
App: app,
grpcListener: grpcListener,
grpcServer: grpcServer,
wsListener: wsListener,
wsConnections: make(map[*websocket.Conn]map[string]struct{}),
wsUpgrader: websocket.Upgrader{},
blockEventChan: make(chan *coretypes.ResultEvent, 1),
}

mux.Handle(http.MethodPost, rootPattern, newPostHandler(client, e2eApp))

go func() {
if err := e2eApp.grpcServer.Serve(grpcListener); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
panic(err)
}
}
}()

// Initialize and start WebSocket server
e2eApp.wsServer = newWebSocketServer(e2eApp)
go func() {
if err := e2eApp.wsServer.Serve(wsListener); err != nil && errors.Is(err, http.ErrServerClosed) {
if !errors.Is(err, http.ErrServerClosed) {
panic(err)
}
}
}()

// Initialize and start HTTP server
go func() {
if err := http.ListenAndServe("127.0.0.1:42070", mux); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
panic(err)
}
}
}()

// Start event handling
go e2eApp.handleBlockEvents(t)

return e2eApp
}

// Close gracefully shuts down the E2EApp and its servers
func (app *E2EApp) Close() error {
app.grpcServer.GracefulStop()
if err := app.wsServer.Close(); err != nil {
return err
}

close(app.blockEventChan)

return nil
}

// GetClientConn returns a gRPC client connection to the E2EApp's gRPC server
func (app *E2EApp) GetClientConn(ctx context.Context) (*grpc.ClientConn, error) {
return grpc.DialContext(
ctx,
app.grpcListener.Addr().String(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
}

// GetWSEndpoint returns the WebSocket endpoint URL
func (app *E2EApp) GetWSEndpoint() string {
return "ws://" + app.wsListener.Addr().String() + "/websocket"
}
Loading

Unchanged files with check annotations Beta

"github.com/pokt-network/poktroll/app/volatile"
"github.com/pokt-network/poktroll/testutil/events"
"github.com/pokt-network/poktroll/testutil/integration/suites"

Check failure on line 13 in tests/integration/application/application_transfer_test.go

GitHub Actions / go-test

could not import github.com/pokt-network/poktroll/testutil/integration/suites (-: # github.com/pokt-network/poktroll/testutil/integration/suites
"github.com/pokt-network/poktroll/testutil/testkeyring"
apptypes "github.com/pokt-network/poktroll/x/application/types"
sharedtypes "github.com/pokt-network/poktroll/x/shared/types"
// TestAppTransferSuite runs the application transfer test suite.
func TestAppTransferSuite(t *testing.T) {
suite.Run(t, new(appTransferTestSuite))

Check failure on line 45 in tests/integration/application/application_transfer_test.go

GitHub Actions / go-test

cannot use new(appTransferTestSuite) (value of type *appTransferTestSuite) as suite.TestingSuite value in argument to suite.Run: *appTransferTestSuite does not implement suite.TestingSuite (missing method SetS) (typecheck)
}
func (s *appTransferTestSuite) SetupTest() {
// Construct a new integration app for each test.
s.NewApp(s.T())

Check failure on line 50 in tests/integration/application/application_transfer_test.go

GitHub Actions / go-test

s.NewApp undefined (type *appTransferTestSuite has no field or method NewApp) (typecheck)
s.gatewaySuite.SetApp(s.GetApp())

Check failure on line 51 in tests/integration/application/application_transfer_test.go

GitHub Actions / go-test

s.GetApp undefined (type *appTransferTestSuite has no field or method GetApp) (typecheck)
s.paramsSuite.SetApp(s.GetApp())

Check failure on line 52 in tests/integration/application/application_transfer_test.go

GitHub Actions / go-test

s.GetApp undefined (type *appTransferTestSuite has no field or method GetApp) (typecheck)
// Setup authz accounts and grants to enable updating params.
s.paramsSuite.SetupTestAuthzAccounts(s.T())

Check failure on line 55 in tests/integration/application/application_transfer_test.go

GitHub Actions / go-test

s.T undefined (type *appTransferTestSuite has no field or method T) (typecheck)
s.paramsSuite.SetupTestAuthzGrants(s.T())

Check failure on line 56 in tests/integration/application/application_transfer_test.go

GitHub Actions / go-test

s.T undefined (type *appTransferTestSuite has no field or method T) (typecheck)
// Ensure gateways and apps have bank balances.
s.setupTestAddresses()
})
// Assert the on-chain state shows the application 3 as NOT staked.
_, queryErr := s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app3)

Check failure on line 84 in tests/integration/application/application_transfer_test.go

GitHub Actions / go-test

s.GetAppQueryClient undefined (type *appTransferTestSuite has no field or method GetAppQueryClient) (typecheck)
require.ErrorContains(s.T(), queryErr, "application not found")
require.ErrorContains(s.T(), queryErr, s.app3)
}
// GetBankQueryClient constructs and returns a query client for the bank module
// of the integration app.
func (s *BaseIntegrationSuite) GetBankQueryClient() banktypes.QueryClient {
return banktypes.NewQueryClient(s.GetApp().QueryHelper())

Check failure on line 101 in testutil/integration/suites/base.go

GitHub Actions / go-test

cannot use s.GetApp().QueryHelper() (value of type *baseapp.GRPCQueryRouter) as "github.com/cosmos/gogoproto/grpc".ClientConn value in argument to banktypes.NewQueryClient: *baseapp.GRPCQueryRouter does not implement "github.com/cosmos/gogoproto/grpc".ClientConn (missing method Invoke)
}
// FilterEvents returns the events from the event manager which match the given
s.RunAuthzGrantMsg(t, granterAddr, granteeAddr, authorization)
// Query for the created grant to assert that they were created.
authzQueryClient := authz.NewQueryClient(s.app.QueryHelper())

Check failure on line 46 in testutil/integration/suites/authz.go

GitHub Actions / go-test

cannot use s.app.QueryHelper() (value of type *baseapp.GRPCQueryRouter) as "github.com/cosmos/gogoproto/grpc".ClientConn value in argument to authz.NewQueryClient: *baseapp.GRPCQueryRouter does not implement "github.com/cosmos/gogoproto/grpc".ClientConn (missing method Invoke)) (typecheck)
queryGrantsReq := &authz.QueryGrantsRequest{
Granter: granterAddr.String(),
Grantee: granteeAddr.String(),