Skip to content

Commit

Permalink
Incorporated feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
smickovskid committed May 21, 2024
1 parent 7dd922f commit ff1204a
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 103 deletions.
4 changes: 4 additions & 0 deletions docs/RunningE2eTests.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@ The main test config logic resides in the `integration-tests/testconfig/` direct
There are a few possibile combinations to run tests that we support.

**Devnet**
Devnet requires previously deployed programs that are owned by the person running the tests. The program ID's are required for testnet, but ignored in localnet.

- `Common.network` needs to be set to `devnet` which will instruct the tests to run against devnet
- `ocr2_program_id`, `access_controller_program_id`, `store_program_id`, `link_token_address`, `vault_address` need to be set so the tests know what programs to use so we avoid deploying each time.
- `rpc_url` and `ws_url` need to be set

**Localnet**
Setting localnet will instruct the tests to run in localnet, the program ID's are not taken from the TOML in this scenario, but rather defined in the `integration-tests/config/config.go`.

**K8s**

Running in Kubernetes will require aws auth.
Expand Down
6 changes: 4 additions & 2 deletions gauntlet/packages/gauntlet-solana/src/commands/middlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ export const withProvider: Middleware = (c: SolanaCommand, next: Next) => {
`Invalid NODE_URL (${nodeURL}), please add an http:// or https:// prefix`,
)
const wsUrl = process.env.WS_URL
assertions.assert(wsUrl && isValidURL(wsUrl), `Invalid WS_URL (${wsUrl}), please add an ws:// or wss:// prefix`)
c.provider = new AnchorProvider(new Connection(nodeURL, { wsEndpoint: wsUrl }), c.wallet, {})
if (wsUrl) {
assertions.assert(isValidURL(wsUrl), `Invalid WS_URL (${wsUrl}), please add an ws:// or wss:// prefix`)
}
c.provider = new AnchorProvider(new Connection(nodeURL, wsUrl ? { wsEndpoint: wsUrl } : {}), c.wallet, {})
return next()
}

Expand Down
2 changes: 1 addition & 1 deletion integration-tests/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func New(testConfig *tc.TestConfig) *Common {
// Getting the default localnet private key
privateKey, err := solana.PrivateKeyFromBase58(solclient.DefaultPrivateKeysSolValidator[1])
if err != nil {
panic("Could not decode private devnet private key")
panic("Could not decode private localnet private key")
}
privateKeyString := fmt.Sprintf("[%s]", formatBuffer([]byte(privateKey)))
publicKey := privateKey.PublicKey().String()
Expand Down
221 changes: 121 additions & 100 deletions integration-tests/smoke/ocr2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package smoke

import (
"fmt"
"maps"
"testing"
"time"

Expand All @@ -14,114 +15,134 @@ import (
tc "github.com/smartcontractkit/chainlink-solana/integration-tests/testconfig"
"github.com/smartcontractkit/chainlink-solana/integration-tests/utils"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
"github.com/smartcontractkit/chainlink/integration-tests/docker/test_env"
)

func TestSolanaOCRV2Smoke(t *testing.T) {
config, err := tc.GetConfig("Smoke", tc.OCR2)
if err != nil {
t.Fatal(err)
}
for _, test := range []struct {
name string
env map[string]string
}{
{name: "embedded"},
{name: "plugins", env: map[string]string{
"CL_MEDIAN_CMD": "chainlink-feeds",
"CL_SOLANA_CMD": "chainlink-solana",
}},
} {
config, err := tc.GetConfig("Smoke", tc.OCR2)
if err != nil {
t.Fatal(err)
}

state, err := common.NewOCRv2State(t, 1, "gauntlet", &config)
require.NoError(t, err, "Could not setup the ocrv2 state")
if state.Common.Env.WillUseRemoteRunner() {
// run the remote runner and exit
err := state.Common.Env.Run()
require.NoError(t, err)
return
}
state.DeployCluster(utils.ContractsDir)
test := test
t.Run(test.name, func(t *testing.T) {

sg, err := gauntlet.NewSolanaGauntlet(fmt.Sprintf("%s/gauntlet", utils.ProjectRoot))
require.NoError(t, err)
state.Gauntlet = sg
state, err := common.NewOCRv2State(t, 1, "gauntlet-"+test.name, &config)
require.NoError(t, err, "Could not setup the ocrv2 state")
if len(test.env) > 0 {
state.Common.TestEnvDetails.NodeOpts = append(state.Common.TestEnvDetails.NodeOpts, func(n *test_env.ClNode) {
if n.ContainerEnvs == nil {
n.ContainerEnvs = map[string]string{}
}
maps.Copy(n.ContainerEnvs, test.env)
})
}

if *config.Common.InsideK8s {
t.Cleanup(func() {
if err := actions.TeardownRemoteSuite(t, state.Common.Env.Cfg.Namespace, state.Clients.ChainlinkClient.ChainlinkClientK8s, nil, nil, nil); err != nil {
log.Error().Err(err).Msg("Error tearing down environment")
state.DeployCluster(utils.ContractsDir)

sg, err := gauntlet.NewSolanaGauntlet(fmt.Sprintf("%s/gauntlet", utils.ProjectRoot))
require.NoError(t, err)
state.Gauntlet = sg

if *config.Common.InsideK8s {
t.Cleanup(func() {
if err := actions.TeardownRemoteSuite(t, state.Common.Env.Cfg.Namespace, state.Clients.ChainlinkClient.ChainlinkClientK8s, nil, nil, nil); err != nil {
log.Error().Err(err).Msg("Error tearing down environment")
}
})
}
})
}
state.SetupClients()
require.NoError(t, err)

gauntletConfig := map[string]string{
"SECRET": fmt.Sprintf("\"%s\"", *config.SolanaConfig.Secret),
"NODE_URL": state.Common.ChainDetails.RPCURLExternal,
"WS_URL": state.Common.ChainDetails.WSURLExternal,
"PRIVATE_KEY": state.Common.AccountDetails.PrivateKey,
}
state.SetupClients()
require.NoError(t, err)

err = sg.SetupNetwork(gauntletConfig)
require.NoError(t, err, "Error setting gauntlet network")

if *config.Common.Network == "devnet" {
state.Common.ChainDetails.ProgramAddresses.OCR2 = *config.SolanaConfig.OCR2ProgramId
state.Common.ChainDetails.ProgramAddresses.AccessController = *config.SolanaConfig.AccessControllerProgramId
state.Common.ChainDetails.ProgramAddresses.Store = *config.SolanaConfig.StoreProgramId
sg.LinkAddress = *config.SolanaConfig.LinkTokenAddress
sg.VaultAddress = *config.SolanaConfig.VaultAddress
} else {
// Deploying LINK in case of localnet
err = sg.DeployLinkToken()
require.NoError(t, err)
}
gauntletConfig := map[string]string{
"SECRET": fmt.Sprintf("\"%s\"", *config.SolanaConfig.Secret),
"NODE_URL": state.Common.ChainDetails.RPCURLExternal,
"WS_URL": state.Common.ChainDetails.WSURLExternal,
"PRIVATE_KEY": state.Common.AccountDetails.PrivateKey,
}

err = sg.SetupNetwork(gauntletConfig)
require.NoError(t, err, "Error setting gauntlet network")

if *config.Common.Network == "devnet" {
state.Common.ChainDetails.ProgramAddresses.OCR2 = *config.SolanaConfig.OCR2ProgramId
state.Common.ChainDetails.ProgramAddresses.AccessController = *config.SolanaConfig.AccessControllerProgramId
state.Common.ChainDetails.ProgramAddresses.Store = *config.SolanaConfig.StoreProgramId
sg.LinkAddress = *config.SolanaConfig.LinkTokenAddress
sg.VaultAddress = *config.SolanaConfig.VaultAddress
} else {
// Deploying LINK in case of localnet
err = sg.DeployLinkToken()
require.NoError(t, err)
}

err = sg.G.WriteNetworkConfigVar(sg.NetworkFilePath, "PROGRAM_ID_OCR2", state.Common.ChainDetails.ProgramAddresses.OCR2)
require.NoError(t, err, "Error adding gauntlet variable")
err = sg.G.WriteNetworkConfigVar(sg.NetworkFilePath, "PROGRAM_ID_ACCESS_CONTROLLER", state.Common.ChainDetails.ProgramAddresses.AccessController)
require.NoError(t, err, "Error adding gauntlet variable")
err = sg.G.WriteNetworkConfigVar(sg.NetworkFilePath, "PROGRAM_ID_STORE", state.Common.ChainDetails.ProgramAddresses.Store)
require.NoError(t, err, "Error adding gauntlet variable")
err = sg.G.WriteNetworkConfigVar(sg.NetworkFilePath, "LINK", sg.LinkAddress)
require.NoError(t, err, "Error adding gauntlet variable")
err = sg.G.WriteNetworkConfigVar(sg.NetworkFilePath, "VAULT_ADDRESS", sg.VaultAddress)
require.NoError(t, err, "Error adding gauntlet variable")

_, err = sg.DeployOCR2()
require.NoError(t, err, "Error deploying OCR")
// Generating default OCR2 config
ocr2Config := ocr_config.NewOCR2Config(state.Clients.ChainlinkClient.NKeys, sg.ProposalAddress, sg.VaultAddress, *config.SolanaConfig.Secret)
ocr2Config.Default()
sg.OCR2Config = ocr2Config

err = sg.ConfigureOCR2()
require.NoError(t, err)

state.CreateJobs()

// Test start
stuck := 0
successFullRounds := 0
prevRound := gauntlet.Transmission{
RoundId: 0,
}
for successFullRounds < *config.OCR2.Smoke.NumberOfRounds {
require.Less(t, stuck, 10, "Rounds have been stuck for more than 10 iterations")
log.Info().Str("Transmission", sg.OcrAddress).Msg("Inspecting transmissions")
transmissions, err := sg.FetchTransmissions(sg.OcrAddress)
require.NoError(t, err)
if len(transmissions) <= 1 {
log.Info().Str("Contract", sg.OcrAddress).Str("No", "Transmissions")
stuck++
continue
}
currentRound := common.GetLatestRound(transmissions)
if prevRound.RoundId == 0 {
prevRound = currentRound
}
if currentRound.RoundId <= prevRound.RoundId {
log.Info().Str("Transmission", sg.OcrAddress).Msg("No new transmissions")
stuck++
continue
}
log.Info().Str("Contract", sg.OcrAddress).Interface("Answer", currentRound.Answer).Int64("RoundID", currentRound.Answer).Msg("New answer found")
require.Equal(t, currentRound.Answer, int64(5), fmt.Sprintf("Actual: %d, Expected: 5", currentRound.Answer))
require.Less(t, prevRound.RoundId, currentRound.RoundId, fmt.Sprintf("Expected round %d to be less than %d", prevRound.RoundId, currentRound.RoundId))
prevRound = currentRound
successFullRounds++
time.Sleep(time.Second * 6)
stuck = 0
}
})

err = sg.G.WriteNetworkConfigVar(sg.NetworkFilePath, "PROGRAM_ID_OCR2", state.Common.ChainDetails.ProgramAddresses.OCR2)
require.NoError(t, err, "Error adding gauntlet variable")
err = sg.G.WriteNetworkConfigVar(sg.NetworkFilePath, "PROGRAM_ID_ACCESS_CONTROLLER", state.Common.ChainDetails.ProgramAddresses.AccessController)
require.NoError(t, err, "Error adding gauntlet variable")
err = sg.G.WriteNetworkConfigVar(sg.NetworkFilePath, "PROGRAM_ID_STORE", state.Common.ChainDetails.ProgramAddresses.Store)
require.NoError(t, err, "Error adding gauntlet variable")
err = sg.G.WriteNetworkConfigVar(sg.NetworkFilePath, "LINK", sg.LinkAddress)
require.NoError(t, err, "Error adding gauntlet variable")
err = sg.G.WriteNetworkConfigVar(sg.NetworkFilePath, "VAULT_ADDRESS", sg.VaultAddress)
require.NoError(t, err, "Error adding gauntlet variable")

_, err = sg.DeployOCR2()
require.NoError(t, err, "Error deploying OCR")
// Generating default OCR2 config
ocr2Config := ocr_config.NewOCR2Config(state.Clients.ChainlinkClient.NKeys, sg.ProposalAddress, sg.VaultAddress, *config.SolanaConfig.Secret)
ocr2Config.Default()
sg.OCR2Config = ocr2Config

err = sg.ConfigureOCR2()
require.NoError(t, err)

state.CreateJobs()

// Test start
stuck := 0
successFullRounds := 0
prevRound := gauntlet.Transmission{
RoundId: 0,
}
for successFullRounds < *config.OCR2.Smoke.NumberOfRounds {
require.Less(t, stuck, 10, "Rounds have been stuck for more than 10 iterations")
log.Info().Str("Transmission", sg.OcrAddress).Msg("Inspecting transmissions")
transmissions, err := sg.FetchTransmissions(sg.OcrAddress)
require.NoError(t, err)
if len(transmissions) <= 1 {
log.Info().Str("Contract", sg.OcrAddress).Str("No", "Transmissions")
stuck++
continue
}
currentRound := common.GetLatestRound(transmissions)
if prevRound.RoundId == 0 {
prevRound = currentRound
}
if currentRound.RoundId <= prevRound.RoundId {
log.Info().Str("Transmission", sg.OcrAddress).Msg("No new transmissions")
stuck++
continue
}
log.Info().Str("Contract", sg.OcrAddress).Interface("Answer", currentRound.Answer).Int64("RoundID", currentRound.Answer).Msg("New answer found")
require.Equal(t, currentRound.Answer, int64(5), fmt.Sprintf("Actual: %d, Expected: 5", currentRound.Answer))
require.Less(t, prevRound.RoundId, currentRound.RoundId, fmt.Sprintf("Expected round %d to be less than %d", prevRound.RoundId, currentRound.RoundId))
prevRound = currentRound
successFullRounds++
time.Sleep(time.Second * 6)
stuck = 0
}
}

0 comments on commit ff1204a

Please sign in to comment.