Skip to content

Commit

Permalink
test: add rapid pbt for trace parser (#913)
Browse files Browse the repository at this point in the history
* Add other steps to read/write test

* Improve error logging in trace handler test

* Push ActionType handling into Unmarshal/Marshal and out of own class

* Rename generic trace handler files to be clear they are for json

* Rename to marshalling to be more generic

* Add marshal/unmarshal for proposals

* Export unexported field

* Add test for marshal/unmarshalling chain state

* Fix pointer issues

* Fix typo: action -> proposal

* Log proposal string in test

* Use json.RawMessage instead of map[string]any

* For uniformity, also use RawMessage for step unmarshalling

* Add tests for extra proposal types

* Add more proposal types to test and unify names

* Add handling for ParamsProposal

* Regenerate traces

* Chore: Export forgotten field

* Use string, not int, to help marshal/unmarshal

* Add rapid to go.mod and .sum

* Add rapidpbt for chainState marshalling

* Rename file to make clear it only relates to chainState

* Add error return to TraceWriter and TraceParser

* gst

* Add generators  for actions and steps, utilize in test driver

* Restrict range for time

* Add test for time marshal/unmarshal

* Make time have a lower bound, since negative numbers are not supported by RFC3339

* Improve label string for argument to time.Unix

* Correct lower bound for time: 1900 years negative instead of 2000

* Convert timestamp to utc

* Format file

* Ignore testdata folder

* Add go comment

* Add docstring to GetTraceGen
  • Loading branch information
p-offtermatt committed Sep 12, 2023
1 parent 4bab3dd commit e4ae9d5
Show file tree
Hide file tree
Showing 9 changed files with 699 additions and 17 deletions.
17 changes: 17 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.5.9
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/orderedcode v0.0.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
Expand Down Expand Up @@ -126,6 +127,14 @@ require (
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/mapstructure v1.5.0
github.com/linxGnu/grocksdb v1.7.10 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
github.com/minio/highwayhash v1.0.2 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect
Expand Down Expand Up @@ -168,6 +177,14 @@ require (
require (
github.com/spf13/viper v1.16.0
google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529
)
require pgregory.net/rapid v0.5.7

replace (
github.com/cosmos/cosmos-sdk => github.com/cosmos/cosmos-sdk v0.45.15-ics
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.27
google.golang.org/grpc => google.golang.org/grpc v1.33.2
)

require (
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1879,6 +1879,10 @@ nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA=
pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
pgregory.net/rapid v0.5.3 h1:163N50IHFqr1phZens4FQOdPgfJscR7a562mjQqeo4M=
pgregory.net/rapid v0.5.3/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
pgregory.net/rapid v0.5.7 h1:p7/XbOgyFY1I/3Q12UTXfos70VZTcgc3WeoyiEru5cs=
pgregory.net/rapid v0.5.7/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
Expand Down
1 change: 1 addition & 0 deletions tests/e2e/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
testdata
348 changes: 348 additions & 0 deletions tests/e2e/action_rapid_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,348 @@
package main

import (
"testing"
"time"

"github.com/stretchr/testify/require"
"pgregory.net/rapid"
)

func GetActionGen() *rapid.Generator[any] {
return rapid.OneOf(
GetSendTokensActionGen().AsAny(),
GetStartChainActionGen().AsAny(),
GetSubmitTextProposalActionGen().AsAny(),
GetSubmitConsumerAdditionProposalActionGen().AsAny(),
GetSubmitConsumerRemovalProposalActionGen().AsAny(),
GetSubmitParamChangeProposalActionGen().AsAny(),
GetSubmitEquivocationProposalActionGen().AsAny(),
GetVoteGovProposalActionGen().AsAny(),
GetStartConsumerChainActionGen().AsAny(),
GetAddChainToRelayerActionGen().AsAny(),
GetAddIbcConnectionActionGen().AsAny(),
GetAddIbcChannelActionGen().AsAny(),
GetStartHermesActionGen().AsAny(),
GetTransferChannelCompleteActionGen().AsAny(),
GetRelayPacketsActionGen().AsAny(),
GetRelayRewardPacketsToProviderActionGen().AsAny(),
GetDelegateTokensActionGen().AsAny(),
GetUnbondTokensActionGen().AsAny(),
GetRedelegateTokensActionGen().AsAny(),
GetDowntimeSlashActionGen().AsAny(),
GetUnjailValidatorActionGen().AsAny(),
GetRegisterRepresentativeActionGen().AsAny(),
GetDoublesignSlashActionGen().AsAny(),
GetAssignConsumerPubKeyActionGen().AsAny(),
GetSlashThrottleDequeueGen().AsAny(),
)
}

func GetSendTokensActionGen() *rapid.Generator[SendTokensAction] {
return rapid.Custom(func(t *rapid.T) SendTokensAction {
return SendTokensAction{
Amount: rapid.Uint().Draw(t, "Amount"),
Chain: GetChainIDGen().Draw(t, "Chain"),
From: GetValidatorIDGen().Draw(t, "From"),
To: GetValidatorIDGen().Draw(t, "To"),
}
})
}

func GetStartChainActionGen() *rapid.Generator[StartChainAction] {
return rapid.Custom(func(t *rapid.T) StartChainAction {
return StartChainAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
Validators: GetStartChainValidatorsGen().Draw(t, "Validators"),
GenesisChanges: rapid.String().Draw(t, "GenesisChanges"),
SkipGentx: rapid.Bool().Draw(t, "SkipGentx"),
}
})
}

func GetStartChainValidatorsGen() *rapid.Generator[[]StartChainValidator] {
return rapid.Custom(func(t *rapid.T) []StartChainValidator {
return rapid.SliceOf(GetStartChainValidatorGen()).Draw(t, "StartChainValidators")
})
}

func GetStartChainValidatorGen() *rapid.Generator[StartChainValidator] {
return rapid.Custom(func(t *rapid.T) StartChainValidator {
return StartChainValidator{
Id: GetValidatorIDGen().Draw(t, "Id"),
Allocation: rapid.Uint().Draw(t, "Allocation"),
Stake: rapid.Uint().Draw(t, "Stake"),
}
})
}

func GetSubmitTextProposalActionGen() *rapid.Generator[submitTextProposalAction] {
return rapid.Custom(func(t *rapid.T) submitTextProposalAction {
return submitTextProposalAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
From: GetValidatorIDGen().Draw(t, "From"),
Deposit: rapid.Uint().Draw(t, "Deposit"),
PropType: rapid.String().Draw(t, "PropType"),
Title: rapid.String().Draw(t, "Title"),
Description: rapid.String().Draw(t, "Description"),
}
})
}

func GetSubmitConsumerAdditionProposalActionGen() *rapid.Generator[submitConsumerAdditionProposalAction] {
return rapid.Custom(func(t *rapid.T) submitConsumerAdditionProposalAction {
return submitConsumerAdditionProposalAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
From: GetValidatorIDGen().Draw(t, "From"),
Deposit: rapid.Uint().Draw(t, "Deposit"),
ConsumerChain: GetChainIDGen().Draw(t, "ConsumerChain"),
SpawnTime: rapid.Uint().Draw(t, "SpawnTime"),
InitialHeight: GetHeightGen().Draw(t, "InitialHeight"),
}
})
}

func GetSubmitConsumerRemovalProposalActionGen() *rapid.Generator[submitConsumerRemovalProposalAction] {
return rapid.Custom(func(t *rapid.T) submitConsumerRemovalProposalAction {
return submitConsumerRemovalProposalAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
From: GetValidatorIDGen().Draw(t, "From"),
Deposit: rapid.Uint().Draw(t, "Deposit"),
ConsumerChain: GetChainIDGen().Draw(t, "ConsumerChain"),
StopTimeOffset: time.Duration(rapid.Int64().Draw(t, "StopTimeOffset")),
}
})
}

func GetSubmitParamChangeProposalActionGen() *rapid.Generator[submitParamChangeProposalAction] {
return rapid.Custom(func(t *rapid.T) submitParamChangeProposalAction {
return submitParamChangeProposalAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
From: GetValidatorIDGen().Draw(t, "From"),
Deposit: rapid.Uint().Draw(t, "Deposit"),
Subspace: rapid.String().Draw(t, "Subspace"),
Key: rapid.String().Draw(t, "Key"),
Value: rapid.String().Draw(t, "Value"), // TODO: make this more generic
}
})
}

func GetSubmitEquivocationProposalActionGen() *rapid.Generator[submitEquivocationProposalAction] {
return rapid.Custom(func(t *rapid.T) submitEquivocationProposalAction {
return submitEquivocationProposalAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
From: GetValidatorIDGen().Draw(t, "From"),
Deposit: rapid.Uint().Draw(t, "Deposit"),
Height: rapid.Int64().Draw(t, "Height"),
Time: GetTimeGen().Draw(t, "Time"),
Power: rapid.Int64().Draw(t, "Power"),
}
})
}

func TestMarshalAndUnmarshalTime(t *testing.T) {
rapid.Check(t, func(t *rapid.T) {
time1 := GetTimeGen().Draw(t, "time")
data, err := time1.MarshalJSON()
require.NoError(t, err)
var time2 time.Time
err = time2.UnmarshalJSON(data)
require.NoError(t, err)
require.True(t, time1.Equal(time2))
})
}

func GetTimeGen() *rapid.Generator[time.Time] {
return rapid.Custom(func(t *rapid.T) time.Time {
return time.Unix(rapid.Int64Range(-5.9959e+10, 1.5779e+11).Draw(t, "unix time"), 0).UTC()
})
}

func GetVoteGovProposalActionGen() *rapid.Generator[voteGovProposalAction] {
return rapid.Custom(func(t *rapid.T) voteGovProposalAction {
return voteGovProposalAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
From: rapid.SliceOf(GetValidatorIDGen()).Draw(t, "From"),
Vote: rapid.SliceOf(rapid.String()).Draw(t, "Vote"),
PropNumber: rapid.Uint().Draw(t, "PropNumber"),
}
})
}

func GetStartConsumerChainActionGen() *rapid.Generator[startConsumerChainAction] {
return rapid.Custom(func(t *rapid.T) startConsumerChainAction {
return startConsumerChainAction{
ConsumerChain: GetChainIDGen().Draw(t, "ConsumerChain"),
ProviderChain: GetChainIDGen().Draw(t, "ProviderChain"),
Validators: GetStartChainValidatorsGen().Draw(t, "Validators"),
GenesisChanges: rapid.String().Draw(t, "GenesisChanges"),
}
})
}

func GetAddChainToRelayerActionGen() *rapid.Generator[addChainToRelayerAction] {
return rapid.Custom(func(t *rapid.T) addChainToRelayerAction {
return addChainToRelayerAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
Validator: GetValidatorIDGen().Draw(t, "Validator"),
}
})
}

func GetAddIbcConnectionActionGen() *rapid.Generator[addIbcConnectionAction] {
return rapid.Custom(func(t *rapid.T) addIbcConnectionAction {
return addIbcConnectionAction{
ChainA: GetChainIDGen().Draw(t, "ChainA"),
ChainB: GetChainIDGen().Draw(t, "ChainB"),
ClientA: rapid.Uint().Draw(t, "ClientA"),
ClientB: rapid.Uint().Draw(t, "ClientB"),
}
})
}

func GetAddIbcChannelActionGen() *rapid.Generator[addIbcChannelAction] {
return rapid.Custom(func(t *rapid.T) addIbcChannelAction {
return addIbcChannelAction{
ChainA: GetChainIDGen().Draw(t, "ChainA"),
ChainB: GetChainIDGen().Draw(t, "ChainB"),
ConnectionA: rapid.Uint().Draw(t, "ConnectionA"),
PortA: rapid.String().Draw(t, "PortA"),
PortB: rapid.String().Draw(t, "PortB"),
Order: rapid.String().Draw(t, "Order"),
}
})
}

func GetStartHermesActionGen() *rapid.Generator[startHermesAction] {
return rapid.Just(startHermesAction{})
}

func GetTransferChannelCompleteActionGen() *rapid.Generator[transferChannelCompleteAction] {
return rapid.Custom(func(t *rapid.T) transferChannelCompleteAction {
return transferChannelCompleteAction{
ChainA: GetChainIDGen().Draw(t, "ChainA"),
ChainB: GetChainIDGen().Draw(t, "ChainB"),
ConnectionA: rapid.Uint().Draw(t, "ConnectionA"),
PortA: rapid.String().Draw(t, "PortA"),
PortB: rapid.String().Draw(t, "PortB"),
Order: rapid.String().Draw(t, "Order"),
ChannelA: rapid.Uint().Draw(t, "ChannelA"),
ChannelB: rapid.Uint().Draw(t, "ChannelB"),
}
})
}

func GetRelayPacketsActionGen() *rapid.Generator[relayPacketsAction] {
return rapid.Custom(func(t *rapid.T) relayPacketsAction {
return relayPacketsAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
Port: rapid.String().Draw(t, "Port"),
Channel: rapid.Uint().Draw(t, "Channel"),
}
})
}

func GetRelayRewardPacketsToProviderActionGen() *rapid.Generator[relayRewardPacketsToProviderAction] {
return rapid.Custom(func(t *rapid.T) relayRewardPacketsToProviderAction {
return relayRewardPacketsToProviderAction{
ConsumerChain: GetChainIDGen().Draw(t, "ConsumerChain"),
ProviderChain: GetChainIDGen().Draw(t, "ProviderChain"),
Port: rapid.String().Draw(t, "Port"),
Channel: rapid.Uint().Draw(t, "Channel"),
}
})
}

func GetDelegateTokensActionGen() *rapid.Generator[delegateTokensAction] {
return rapid.Custom(func(t *rapid.T) delegateTokensAction {
return delegateTokensAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
Amount: rapid.Uint().Draw(t, "Amount"),
From: GetValidatorIDGen().Draw(t, "From"),
To: GetValidatorIDGen().Draw(t, "To"),
}
})
}

func GetUnbondTokensActionGen() *rapid.Generator[unbondTokensAction] {
return rapid.Custom(func(t *rapid.T) unbondTokensAction {
return unbondTokensAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
Amount: rapid.Uint().Draw(t, "Amount"),
Sender: GetValidatorIDGen().Draw(t, "Sender"),
UnbondFrom: GetValidatorIDGen().Draw(t, "UnbondFrom"),
}
})
}

func GetRedelegateTokensActionGen() *rapid.Generator[redelegateTokensAction] {
return rapid.Custom(func(t *rapid.T) redelegateTokensAction {
return redelegateTokensAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
Amount: rapid.Uint().Draw(t, "Amount"),
Src: GetValidatorIDGen().Draw(t, "Src"),
Dst: GetValidatorIDGen().Draw(t, "Dst"),
TxSender: GetValidatorIDGen().Draw(t, "TxSender"),
}
})
}

func GetDowntimeSlashActionGen() *rapid.Generator[downtimeSlashAction] {
return rapid.Custom(func(t *rapid.T) downtimeSlashAction {
return downtimeSlashAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
Validator: GetValidatorIDGen().Draw(t, "Validator"),
}
})
}

func GetUnjailValidatorActionGen() *rapid.Generator[unjailValidatorAction] {
return rapid.Custom(func(t *rapid.T) unjailValidatorAction {
return unjailValidatorAction{
Validator: GetValidatorIDGen().Draw(t, "Validator"),
Provider: GetChainIDGen().Draw(t, "Provider"),
}
})
}

func GetRegisterRepresentativeActionGen() *rapid.Generator[registerRepresentativeAction] {
return rapid.Custom(func(t *rapid.T) registerRepresentativeAction {
return registerRepresentativeAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
Representatives: rapid.SliceOf(GetValidatorIDGen()).Draw(t, "Representatives"),
Stakes: rapid.SliceOf(rapid.Uint()).Draw(t, "Stakes"),
}
})
}

func GetDoublesignSlashActionGen() *rapid.Generator[doublesignSlashAction] {
return rapid.Custom(func(t *rapid.T) doublesignSlashAction {
return doublesignSlashAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
Validator: GetValidatorIDGen().Draw(t, "Validator"),
}
})
}

func GetAssignConsumerPubKeyActionGen() *rapid.Generator[assignConsumerPubKeyAction] {
return rapid.Custom(func(t *rapid.T) assignConsumerPubKeyAction {
return assignConsumerPubKeyAction{
Chain: GetChainIDGen().Draw(t, "Chain"),
Validator: GetValidatorIDGen().Draw(t, "Validator"),
ConsumerPubkey: rapid.String().Draw(t, "ConsumerPubkey"),
ReconfigureNode: rapid.Bool().Draw(t, "ReconfigureNode"),
ExpectError: rapid.Bool().Draw(t, "ExpectError"),
}
})
}

func GetSlashThrottleDequeueGen() *rapid.Generator[slashThrottleDequeue] {
return rapid.Custom(func(t *rapid.T) slashThrottleDequeue {
return slashThrottleDequeue{
Chain: GetChainIDGen().Draw(t, "Chain"),
CurrentQueueSize: rapid.Int().Draw(t, "CurrentQueueSize"),
NextQueueSize: rapid.Int().Draw(t, "NextQueueSize"),
Timeout: time.Duration(rapid.Int().Draw(t, "Timeout")) * time.Millisecond,
}
})
}
Loading

0 comments on commit e4ae9d5

Please sign in to comment.