Skip to content

Commit

Permalink
integration-tests/ocr2_test.go: implement validateRounds
Browse files Browse the repository at this point in the history
  • Loading branch information
cfal committed Aug 8, 2023
1 parent e64b5f4 commit 974d080
Showing 1 changed file with 138 additions and 99 deletions.
237 changes: 138 additions & 99 deletions integration-tests/ocr2_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package ocr2_test

import (
"context"
"encoding/json"
"fmt"
"math/big"
"os"
"strconv"
"testing"
Expand All @@ -11,10 +13,12 @@ import (
"github.com/smartcontractkit/chainlink-cosmos/integration-tests/common"
"github.com/smartcontractkit/chainlink-cosmos/integration-tests/gauntlet"
"github.com/smartcontractkit/chainlink-cosmos/ops/utils"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters/cosmwasm"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client"
"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/params"
relaylogger "github.com/smartcontractkit/chainlink-relay/pkg/logger"
"github.com/smartcontractkit/chainlink/integration-tests/actions"
ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2/types"

"github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -148,7 +152,7 @@ func TestOCRBasic(t *testing.T) {
ocrAddress)
require.NoError(t, err, "Could not create jobs for contract")

err = validateRounds(t, cosmosClient, ocrAddress, commonConfig.IsSoak)
err = validateRounds(t, cosmosClient, types.MustAccAddressFromBech32(ocrAddress), types.MustAccAddressFromBech32(ocrProxyAddress), commonConfig.IsSoak, commonConfig.TestDuration)
require.NoError(t, err, "Validating round should not fail")

//if !testState.Common.Testnet {
Expand All @@ -168,17 +172,27 @@ func TestOCRBasic(t *testing.T) {
})
}

func validateRounds(t *testing.T, cosmosClient *client.Client, ocrAddress string, isSoak bool) error {
func validateRounds(t *testing.T, cosmosClient *client.Client, ocrAddress types.AccAddress, ocrProxyAddress types.AccAddress, isSoak bool, testDuration time.Duration) error {
var rounds int
if isSoak {
rounds = 99999999
} else {
rounds = 10
}

// TODO: changing mock-adapter values
mockAdapterValue := 5

logger := common.GetTestLogger(t)
//ctx := context.Background() // context background used because timeout handled by requestTimeout param
ctx := context.Background() // context background used because timeout handled by requestTimeout param
// assert new rounds are occurring
//details := ocr2.TransmissionDetails{}
//increasing := 0 // track number of increasing rounds
//var stuck bool
//stuckCount := 0
//var positive bool
increasing := 0 // track number of increasing rounds
var stuck bool
stuckCount := 0
var positive bool
resp, err := cosmosClient.ContractState(
types.MustAccAddressFromBech32(ocrAddress),
ocrAddress,
[]byte(`"link_available_for_payment"`),
)
if err != nil {
Expand Down Expand Up @@ -218,99 +232,124 @@ func validateRounds(t *testing.T, cosmosClient *client.Client, ocrAddress string
//assert.Equal(testState.T, balLINK.Cmp(big.NewInt(0)), 1, "Aggregator should have non-zero balance")
//assert.GreaterOrEqual(testState.T, balLINK.Cmp(balAgg), 0, "Aggregator payment balance should be <= actual LINK balance")

//for start := time.Now(); time.Since(start) < testState.Common.TestDuration; {
//l.Info().Msg(fmt.Sprintf("Elapsed time: %s, Round wait: %s ", time.Since(start), testState.Common.TestDuration))
//res, err := testState.OCR2Client.LatestTransmissionDetails(ctx, caigotypes.StrToFelt(testState.OCRAddr))
//require.NoError(testState.T, err, "Failed to get latest transmission details")
//// end condition: enough rounds have occurred
//if !isSoak && increasing >= rounds && positive {
//break
//}

//// end condition: rounds have been stuck
//if stuck && stuckCount > 50 {
//l.Debug().Msg("failing to fetch transmissions means blockchain may have stopped")
//break
//}

//l.Info().Msg(fmt.Sprintf("Setting adapter value to %d", mockServerValue))
//err = testState.SetMockServerValue("", mockServerValue)
//if err != nil {
//l.Error().Msg(fmt.Sprintf("Setting mock server value error: %+v", err))
//}
//// try to fetch rounds
//time.Sleep(5 * time.Second)

//if err != nil {
//l.Error().Msg(fmt.Sprintf("Transmission Error: %+v", err))
//continue
//}
//l.Info().Msg(fmt.Sprintf("Transmission Details: %+v", res))

//// continue if no changes
//if res.Epoch == 0 && res.Round == 0 {
//continue
//}

//ansCmp := res.LatestAnswer.Cmp(big.NewInt(0))
//positive = ansCmp == 1 || positive

//// if changes from zero values set (should only initially)
//if res.Epoch > 0 && details.Epoch == 0 {
//if !isSoak {
//assert.Greater(testState.T, res.Epoch, details.Epoch)
//assert.GreaterOrEqual(testState.T, res.Round, details.Round)
//assert.NotEqual(testState.T, ansCmp, 0) // assert changed from 0
//assert.NotEqual(testState.T, res.Digest, details.Digest)
//assert.Equal(testState.T, details.LatestTimestamp.Before(res.LatestTimestamp), true)
//}
//details = res
//continue
//}
//// check increasing rounds
//if !isSoak {
//assert.Equal(testState.T, res.Digest, details.Digest, "Config digest should not change")
//} else {
//if res.Digest != details.Digest {
//l.Error().Msg(fmt.Sprintf("Config digest should not change, expected %s got %s", details.Digest, res.Digest))
//}
//}
//if (res.Epoch > details.Epoch || (res.Epoch == details.Epoch && res.Round > details.Round)) && details.LatestTimestamp.Before(res.LatestTimestamp) {
//increasing++
//stuck = false
//stuckCount = 0 // reset counter
//continue
//}
// TODO: this needs to be able to support different readers
ocrLogger, err := relaylogger.New()
require.NoError(t, err, "Failed to create OCR relay logger")
ocrReader := cosmwasm.NewOCR2Reader(ocrAddress, cosmosClient, ocrLogger)

type TransmissionDetails struct {
ConfigDigest ocrtypes.ConfigDigest
Epoch uint32
Round uint8
LatestAnswer *big.Int
LatestTimestamp time.Time
}

//// reach this point, answer has not changed
//stuckCount++
//if stuckCount > 30 {
//stuck = true
//increasing = 0
//}
//}
//if !isSoak {
//assert.GreaterOrEqual(testState.T, increasing, rounds, "Round + epochs should be increasing")
//assert.Equal(testState.T, positive, true, "Positive value should have been submitted")
//assert.Equal(testState.T, stuck, false, "Round + epochs should not be stuck")
//}
previous := TransmissionDetails{}

for start := time.Now(); time.Since(start) < testDuration; {
logger.Info().Msg(fmt.Sprintf("Elapsed time: %s, Round wait: %s ", time.Since(start), testDuration))
configDigest, epoch, round, latestAnswer, latestTimestamp, err := ocrReader.LatestTransmissionDetails(ctx)
require.NoError(t, err, "Failed to get latest transmission details")
// end condition: enough rounds have occurred
if !isSoak && increasing >= rounds && positive {
break
}

// end condition: rounds have been stuck
if stuck && stuckCount > 50 {
logger.Debug().Msg("failing to fetch transmissions means blockchain may have stopped")
break
}

//logger.Info().Msg(fmt.Sprintf("Setting adapter value to %d", mockServerValue))
//err = testState.SetMockServerValue("", mockServerValue)
//if err != nil {
//l.Error().Msg(fmt.Sprintf("Setting mock server value error: %+v", err))
//}

// try to fetch rounds
time.Sleep(5 * time.Second)

if err != nil {
logger.Error().Msg(fmt.Sprintf("Transmission Error: %+v", err))
continue
}
logger.Info().Msg(fmt.Sprintf("Transmission Details: configDigest: %+v, epoch: %+v, round: %+v, latestAnswer: %+v, latestTimestamp: %+v", configDigest, epoch, round, latestAnswer, latestTimestamp))

// continue if no changes
if epoch == 0 && round == 0 {
continue
}

ansCmp := latestAnswer.Cmp(big.NewInt(0))
positive = ansCmp == 1 || positive

// if changes from zero values set (should only initially)
if epoch > 0 && previous.Epoch == 0 {
if !isSoak {
require.Greater(t, epoch, previous.Epoch)
require.GreaterOrEqual(t, round, previous.Round)
require.NotEqual(t, ansCmp, 0) // require changed from 0
require.NotEqual(t, configDigest, previous.ConfigDigest)
require.Equal(t, previous.LatestTimestamp.Before(latestTimestamp), true)
}
previous = TransmissionDetails{
ConfigDigest: configDigest,
Epoch: epoch,
Round: round,
LatestAnswer: latestAnswer,
LatestTimestamp: latestTimestamp,
}
continue
}
// check increasing rounds
if !isSoak {
require.Equal(t, configDigest, previous.ConfigDigest, "Config digest should not change")
} else {
if configDigest != previous.ConfigDigest {
logger.Error().Msg(fmt.Sprintf("Config digest should not change, expected %s got %s", previous.ConfigDigest, configDigest))
}
}
if (epoch > previous.Epoch || (epoch == previous.Epoch && round > previous.Round)) && previous.LatestTimestamp.Before(latestTimestamp) {
increasing++
stuck = false
stuckCount = 0 // reset counter
continue
}

// reach this point, answer has not changed
stuckCount++
if stuckCount > 30 {
stuck = true
increasing = 0
}
}
if !isSoak {
require.GreaterOrEqual(t, increasing, rounds, "Round + epochs should be increasing")
require.Equal(t, positive, true, "Positive value should have been submitted")
require.Equal(t, stuck, false, "Round + epochs should not be stuck")
}

//// Test proxy reading
//// TODO: would be good to test proxy switching underlying feeds
//roundDataRaw, err := testState.Starknet.CallContract(ctx, starknet.CallOps{
//ContractAddress: caigotypes.StrToFelt(testState.ProxyAddr),
//Selector: "latest_round_data",
//})
//if !isSoak {
//require.NoError(testState.T, err, "Reading round data from proxy should not fail")
//assert.Equal(testState.T, len(roundDataRaw), 5, "Round data from proxy should match expected size")
//}
//valueBig, err := starknet.HexToUnsignedBig(roundDataRaw[1])
//require.NoError(testState.T, err)
//value := valueBig.Int64()
//if value < 0 {
//assert.Equal(testState.T, value, int64(mockServerValue), "Reading from proxy should return correct value")
//}
// Test proxy reading
// TODO: would be good to test proxy switching underlying feeds
resp, err = cosmosClient.ContractState(ocrProxyAddress, []byte(`"latest_round_data"`))
if !isSoak {
require.NoError(t, err, "Reading round data from proxy should not fail")
//assert.Equal(t, len(roundDataRaw), 5, "Round data from proxy should match expected size")
}
roundData := struct {
Answer string `json:"answer"`
}{}
err = json.Unmarshal(resp, &roundData)
require.NoError(t, err, "Failed to unmarshal round data")

valueBig, success := new(big.Int).SetString(roundData.Answer, 10)
require.True(t, success, "Failed to parse round data")
value := valueBig.Int64()
if value < 0 {
require.Equal(t, value, int64(mockAdapterValue), "Reading from proxy should return correct value")
}

return nil
}

0 comments on commit 974d080

Please sign in to comment.