Skip to content

Commit

Permalink
feat: Add Echo App Input end-to-end tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fmoura committed Mar 19, 2024
1 parent cb74e85 commit 4e55212
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 9 deletions.
1 change: 1 addition & 0 deletions cmd/cartesi-rollups-cli/root/send/send.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func init() {
}

func run(cmd *cobra.Command, args []string) {

payload, err := hexutil.Decode(hexPayload)
cobra.CheckErr(err)

Expand Down
75 changes: 75 additions & 0 deletions end-to-end-tests/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package endtoendtests

import (
"log/slog"

"github.com/cartesi/rollups-node/internal/node/config"
"github.com/cartesi/rollups-node/pkg/addresses"
"github.com/cartesi/rollups-node/pkg/ethutil"
)

const (
LocalPostgresEndpoint = "postgres://postgres:password@localhost:5432/postgres"
LocalBlockchainID = 31337
LocalBlockchainHttpEndpoint = "http://localhost:8545"
LocalBlockchainWsEnpoint = "ws://localhost:8545"
LocalApplicationDeploymentBlockNumber = 20
LocalInputBoxDeploymentBlockNumber = 20
LocalHttpAddress = "0.0.0.0"
LocalHttpPort = 10000
LocalBlockTimeout = 60
LocalFinalityOffset = 1
LocalEpochDuration = 120
)

func newLocalNodeConfig() config.NodeConfig {
var nodeConfig config.NodeConfig

book := addresses.GetTestBook()

//Log
nodeConfig.Log.Level = slog.LevelInfo
nodeConfig.Log.Pretty = false

//Postgres
nodeConfig.PostgresEndpoint = config.Redacted[string]{LocalPostgresEndpoint}

//Epoch
nodeConfig.RollupsEpochDuration = LocalEpochDuration

//Blochain
nodeConfig.Blockchain.ID = LocalBlockchainID
nodeConfig.Blockchain.HttpEndpoint = config.Redacted[string]{LocalBlockchainHttpEndpoint}
nodeConfig.Blockchain.WsEndpoint = config.Redacted[string]{LocalBlockchainWsEnpoint}
nodeConfig.Blockchain.IsLegacy = false
nodeConfig.Blockchain.FinalityOffset = LocalFinalityOffset
nodeConfig.Blockchain.BlockTimeout = LocalBlockTimeout

//Contracts
nodeConfig.Contracts.HistoryAddress = book.HistoryAddress.Hex()
nodeConfig.Contracts.AuthorityAddress = book.AuthorityAddress.Hex()
nodeConfig.Contracts.ApplicationAddress = book.CartesiDApp.Hex()
nodeConfig.Contracts.ApplicationDeploymentBlockNumber = LocalApplicationDeploymentBlockNumber
nodeConfig.Contracts.InputBoxAddress = book.InputBox.Hex()
nodeConfig.Contracts.InputBoxDeploymentBlockNumber = LocalInputBoxDeploymentBlockNumber

//HTTP endpoint
nodeConfig.Http.Address = LocalHttpAddress
nodeConfig.Http.Port = LocalHttpPort

//Features
nodeConfig.Feature.HostMode = false
nodeConfig.Feature.DisableClaimer = false
nodeConfig.Feature.DisableMachineHashCheck = true

//Experimental
nodeConfig.Experimental.SunodoValidatorEnabled = false

//Auth
nodeConfig.Auth = config.AuthMnemonic{
config.Redacted[string]{ethutil.FoundryMnemonic},
config.Redacted[int]{0},
}

return nodeConfig
}
127 changes: 126 additions & 1 deletion end-to-end-tests/echo_input_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,153 @@
package endtoendtests

import (
"context"
"fmt"
"io/ioutil"
"os"
"testing"
"time"

"github.com/Khan/genqlient/graphql"
"github.com/cartesi/rollups-node/internal/deps"
"github.com/cartesi/rollups-node/internal/machine"
"github.com/cartesi/rollups-node/internal/node"
"github.com/cartesi/rollups-node/pkg/addresses"
"github.com/cartesi/rollups-node/pkg/ethutil"
"github.com/cartesi/rollups-node/pkg/readerclient"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)

type EchoInputTestSuite struct {
suite.Suite
containers *deps.DepsContainers
cancel context.CancelFunc
tempDir string
supervisorErr chan error
}

func (s *EchoInputTestSuite) SetupSuite() {

//run services
//Create machine snapshot
tempDir, err := ioutil.TempDir("", "machine-snapshot")
assert.NoError(s.T(), err)
machine.Save("cartesi/rollups-node-snapshot:devel", tempDir, "test-echo-app")

//run deps
ctx := context.Background()
var depsConfig = deps.NewDefaultDepsConfig()
depsContainers, err := deps.Run(ctx, *depsConfig)
assert.NoError(s.T(), err)

fmt.Println("All Deps are up!!")
time.Sleep(2 * time.Second)

// Run Node Service
nodeConfig := newLocalNodeConfig()

nodeConfig.SnapshotDir = tempDir

ctx, cancel := context.WithCancel(ctx)
supervisor, err := node.Setup(ctx, nodeConfig)
require.NoError(s.T(), err)

ready := make(chan struct{}, 1)
supervisorErr := make(chan error, 1)
go func() {
err := supervisor.Start(ctx, ready)
if err != nil {
supervisorErr <- err
}
}()

select {
case err := <-supervisorErr:
require.NoError(s.T(), err)
case <-ready:
fmt.Println("All services are up!!")
break
}

//Configure Suite for tear down
s.containers = depsContainers
s.tempDir = tempDir
s.cancel = cancel
s.supervisorErr = supervisorErr

}

func (s *EchoInputTestSuite) TearDownSuite() {

//Stop Node services
s.cancel()

//Remove machine snpshot
os.RemoveAll(s.tempDir)

//Terminate deps
ctx := context.Background()
err := deps.Terminate(ctx, s.containers)
require.NoError(s.T(), err)

}

func (s *EchoInputTestSuite) SetupTest() {

}

func (s *EchoInputTestSuite) TestSendInput() {

ctx := context.Background()

// Send Input
client, err := ethclient.DialContext(ctx, "http://localhost:8545")
require.NoError(s.T(), err)
signer, err := ethutil.NewMnemonicSigner(ctx, client, ethutil.FoundryMnemonic, 0)
require.NoError(s.T(), err)

book := addresses.GetTestBook()

inputIndex, err := ethutil.AddInput(ctx, client, book, signer, []byte("0xDEADBEEF"))
require.NoError(s.T(), err)

require.EqualValues(s.T(), 0, inputIndex, "The input index should be 0")

//Check Input if input is Processed
graphQlClient := graphql.NewClient("http://localhost:10000/graphql", nil)

getInputChan := make(chan *readerclient.Input, 1)
getInputErr := make(chan struct{}, 1)
go func() {
fmt.Println("Waiting for Input...")
time.Sleep(2 * time.Second)
var resp *readerclient.Input
attempts := 0
for resp, err = readerclient.GetInput(ctx, graphQlClient, inputIndex); err != nil || attempts < 10; attempts++ {
fmt.Printf("Error : %v \n", err)
fmt.Println("Waiting for Input...")
time.Sleep(2 * time.Second)
}
if attempts == 10 {
getInputErr <- struct{}{}
return
}
getInputChan <- resp
}()

select {
case resp := <-getInputChan:
fmt.Printf("Response %v \n", resp)
break
case err = <-s.supervisorErr:
require.NoError(s.T(), err)
}

}

func TestEchoInput(t *testing.T) {

suite.Run(t, new(EchoInputTestSuite))
}
28 changes: 20 additions & 8 deletions internal/deps/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,19 @@ type DepsContainers struct {
}

func createHook(containerName string,
waitGroup *sync.WaitGroup) []testcontainers.ContainerLifecycleHooks {
finishedWaitGroup *sync.WaitGroup,
startedWaitGroup *sync.WaitGroup) []testcontainers.ContainerLifecycleHooks {
return []testcontainers.ContainerLifecycleHooks{
{
PostStarts: []testcontainers.ContainerHook{
func(ctx context.Context, container testcontainers.Container) error {
startedWaitGroup.Done()
return nil
},
},
PostTerminates: []testcontainers.ContainerHook{
func(ctx context.Context, container testcontainers.Container) error {
waitGroup.Done()
finishedWaitGroup.Done()
return nil
},
},
Expand All @@ -73,14 +80,17 @@ func createHook(containerName string,
// The returned DepContainers struct can be used to gracefully
// terminate the containers using the Terminate method
func Run(ctx context.Context, depsConfig DepsConfig) (*DepsContainers, error) {

noopLogger := log.New(io.Discard, "", 0)
var waitGroup sync.WaitGroup
var finishedWaitGroup sync.WaitGroup
var startedWaitGroup sync.WaitGroup

// wait strategy copied from testcontainers docs
postgresWaitStrategy := wait.ForLog("database system is ready to accept connections").
WithOccurrence(numPostgresCheckReadyAttempts).
WithPollInterval(pollInterval)

startedWaitGroup.Add(1)
postgresReq := testcontainers.ContainerRequest{
Image: depsConfig.PostgresDockerImage,
ExposedPorts: []string{strings.Join([]string{
Expand All @@ -90,7 +100,7 @@ func Run(ctx context.Context, depsConfig DepsConfig) (*DepsContainers, error) {
Env: map[string]string{
"POSTGRES_PASSWORD": depsConfig.PostgresPassword,
},
LifecycleHooks: createHook("rollups-node-dep-postgres", &waitGroup),
LifecycleHooks: createHook("rollups-node-dep-postgres", &finishedWaitGroup, &startedWaitGroup),
}

postgres, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
Expand All @@ -102,8 +112,9 @@ func Run(ctx context.Context, depsConfig DepsConfig) (*DepsContainers, error) {
if err != nil {
return nil, err
}
waitGroup.Add(1)
finishedWaitGroup.Add(1)

startedWaitGroup.Add(1)
devNetReq := testcontainers.ContainerRequest{
Image: depsConfig.DevnetDockerImage,
ExposedPorts: []string{strings.Join([]string{depsConfig.DevnetPort, ":8545/tcp"}, "")},
Expand All @@ -112,7 +123,7 @@ func Run(ctx context.Context, depsConfig DepsConfig) (*DepsContainers, error) {
Env: map[string]string{
"ANVIL_IP_ADDR": "0.0.0.0",
},
LifecycleHooks: createHook("rollups-node-dep-devnet", &waitGroup),
LifecycleHooks: createHook("rollups-node-dep-devnet", &finishedWaitGroup, &startedWaitGroup),
}

devnet, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
Expand All @@ -124,11 +135,12 @@ func Run(ctx context.Context, depsConfig DepsConfig) (*DepsContainers, error) {
return nil, err
}

waitGroup.Add(1)
finishedWaitGroup.Add(1)

containers := []testcontainers.Container{postgres, devnet}

return &DepsContainers{containers, &waitGroup}, nil
startedWaitGroup.Wait()
return &DepsContainers{containers, &finishedWaitGroup}, nil
}

// Terminate terminates all dependencies containers. This method waits for all the containers
Expand Down
4 changes: 4 additions & 0 deletions pkg/addresses/addresses.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type Book struct {
EtherPortal common.Address
InputBox common.Address
CartesiDApp common.Address
HistoryAddress common.Address
AuthorityAddress common.Address
}

// Get the addresses for the test environment.
Expand All @@ -45,6 +47,8 @@ func GetTestBook() *Book {
EtherPortal: common.HexToAddress("0xFfdbe43d4c855BF7e0f105c400A50857f53AB044"),
InputBox: common.HexToAddress("0x59b22D57D4f067708AB0c00552767405926dc768"),
CartesiDApp: common.HexToAddress("0x7FFdf694A877067DE99462A7243b29972D19cf72"),
HistoryAddress: common.HexToAddress("0x325272217ae6815b494bF38cED004c5Eb8a7CdA7"),
AuthorityAddress: common.HexToAddress("0x58c93F83fb3304730C95aad2E360cdb88b782010"),
}
}

Expand Down

0 comments on commit 4e55212

Please sign in to comment.