From 44c2bc04fe8fda44d60eec10d200c32e8ca7741a Mon Sep 17 00:00:00 2001 From: pharr117 Date: Sat, 17 Feb 2024 19:38:15 -0500 Subject: [PATCH 1/2] Tests for config validations and setups --- .github/workflows/go-test.yaml | 3 +- config/common_configs_test.go | 89 ++++++++++++++++++++++++++++++++++ config/index_config.go | 11 ++--- config/index_config_test.go | 72 +++++++++++++++++++++++++++ config/update_denoms_config.go | 67 ------------------------- 5 files changed, 167 insertions(+), 75 deletions(-) create mode 100644 config/common_configs_test.go create mode 100644 config/index_config_test.go delete mode 100644 config/update_denoms_config.go diff --git a/.github/workflows/go-test.yaml b/.github/workflows/go-test.yaml index 27b5588c..39616e9e 100644 --- a/.github/workflows/go-test.yaml +++ b/.github/workflows/go-test.yaml @@ -23,5 +23,4 @@ jobs: - uses: actions/checkout@v3 - name: test code run: | - cd db - go test -v ./... + go test -timeout 30m -v ./... diff --git a/config/common_configs_test.go b/config/common_configs_test.go new file mode 100644 index 00000000..f970e37e --- /dev/null +++ b/config/common_configs_test.go @@ -0,0 +1,89 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/suite" +) + +type ConfigTestSuite struct { + suite.Suite +} + +func (suite *ConfigTestSuite) TestValidateDatabaseConf() { + conf := Database{ + Host: "", + Port: "", + Database: "", + User: "", + Password: "", + } + + err := validateDatabaseConf(conf) + suite.Require().Error(err) + conf.Host = "fake-host" + + err = validateDatabaseConf(conf) + suite.Require().Error(err) + + conf.Port = "5432" + err = validateDatabaseConf(conf) + suite.Require().Error(err) + + conf.Database = "fake-database" + err = validateDatabaseConf(conf) + suite.Require().Error(err) + + conf.User = "fake-user" + err = validateDatabaseConf(conf) + suite.Require().Error(err) + + conf.Password = "fake-password" + err = validateDatabaseConf(conf) + suite.Require().NoError(err) +} + +func (suite *ConfigTestSuite) TestValidateProbeConf() { + conf := Probe{ + RPC: "", + AccountPrefix: "", + ChainID: "", + ChainName: "", + } + + _, err := validateProbeConf(conf) + suite.Require().Error(err) + + conf.RPC = "fake-rpc" + _, err = validateProbeConf(conf) + suite.Require().Error(err) + + conf.AccountPrefix = "fake-account-prefix" + _, err = validateProbeConf(conf) + suite.Require().Error(err) + + conf.ChainID = "fake-chain-id" + _, err = validateProbeConf(conf) + suite.Require().Error(err) + + conf.ChainName = "fake-chain-name" + _, err = validateProbeConf(conf) + suite.Require().NoError(err) +} + +func (suite *ConfigTestSuite) TestValidateThrottlingConf() { + conf := throttlingBase{ + Throttling: -1, + } + + err := validateThrottlingConf(conf) + suite.Require().Error(err) + + conf.Throttling = 0.5 + err = validateThrottlingConf(conf) + suite.Require().NoError(err) +} + +func TestConfigSuite(t *testing.T) { + suite.Run(t, new(ConfigTestSuite)) +} diff --git a/config/index_config.go b/config/index_config.go index 88c17088..738926c5 100644 --- a/config/index_config.go +++ b/config/index_config.go @@ -9,12 +9,11 @@ import ( ) type IndexConfig struct { - Database Database - ConfigFileLocation string - Base indexBase - Log log - Probe Probe - Flags flags + Database Database + Base indexBase + Log log + Probe Probe + Flags flags } type indexBase struct { diff --git a/config/index_config_test.go b/config/index_config_test.go new file mode 100644 index 00000000..caf966f3 --- /dev/null +++ b/config/index_config_test.go @@ -0,0 +1,72 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/suite" +) + +type IndexConfigTestSuite struct { + suite.Suite +} + +func (suite *IndexConfigTestSuite) TestIndexConfig() { + conf := IndexConfig{ + // Setup valid configs for everything but base, these are tested elsewhere + Database: Database{ + Host: "fake-host", + Port: "5432", + Database: "fake-database", + User: "fake-user", + Password: "fake-password", + LogLevel: "info", + }, + Log: log{ + Level: "info", + Path: "", + Pretty: false, + }, + Probe: Probe{ + RPC: "fake-rpc", + AccountPrefix: "cosmos", + ChainID: "fake-chain-id", + ChainName: "fake-chain-name", + }, + Flags: flags{ + IndexTxMessageRaw: false, + }, + } + + err := conf.Validate() + suite.Require().Error(err) + + conf.Base.TransactionIndexingEnabled = true + + err = conf.Validate() + suite.Require().Error(err) + + conf.Base.StartBlock = 1 + err = conf.Validate() + suite.Require().Error(err) + + conf.Base.EndBlock = 2 + err = conf.Validate() + suite.Require().NoError(err) +} + +func (suite *IndexConfigTestSuite) TestCheckSuperfluousIndexKeys() { + keys := []string{ + "fake-key", + } + validKeys := CheckSuperfluousIndexKeys(keys) + suite.Require().Len(validKeys, 1) + + keys = append(keys, "base.start-block") + + validKeys = CheckSuperfluousIndexKeys(keys) + suite.Require().Len(validKeys, 1) +} + +func TestIndexConfig(t *testing.T) { + suite.Run(t, new(IndexConfigTestSuite)) +} diff --git a/config/update_denoms_config.go b/config/update_denoms_config.go deleted file mode 100644 index ca99941c..00000000 --- a/config/update_denoms_config.go +++ /dev/null @@ -1,67 +0,0 @@ -package config - -import "github.com/spf13/cobra" - -type UpdateDenomsConfig struct { - Database Database - Probe Probe - Log log - Base updateDenomsBase -} - -type updateDenomsBase struct { - retryBase - UpdateAll bool `mapstructure:"update-all"` -} - -func SetupUpdateDenomsSpecificFlags(conf *UpdateDenomsConfig, cmd *cobra.Command) { - cmd.Flags().BoolVar(&conf.Base.UpdateAll, "base.update-all", false, "If provided, the update script will ignore the config chain-id and update all denoms by reaching out to all assetlists supported.") - cmd.PersistentFlags().Int64Var(&conf.Base.RequestRetryAttempts, "base.request-retry-attempts", 0, "number of RPC query retries to make") - cmd.PersistentFlags().Uint64Var(&conf.Base.RequestRetryMaxWait, "base.request-retry-max-wait", 30, "max retry incremental backoff wait time in seconds") -} - -func (conf *UpdateDenomsConfig) Validate() error { - err := validateDatabaseConf(conf.Database) - if err != nil { - return err - } - - probeConf := conf.Probe - - probeConf, err = validateProbeConf(probeConf) - - if err != nil { - return err - } - - conf.Probe = probeConf - - return nil -} - -func CheckSuperfluousUpdateDenomsKeys(keys []string) []string { - validKeys := make(map[string]struct{}) - - addDatabaseConfigKeys(validKeys) - addLogConfigKeys(validKeys) - addProbeConfigKeys(validKeys) - - // add base keys - for _, key := range getValidConfigKeys(updateDenomsBase{}, "base") { - validKeys[key] = struct{}{} - } - - for _, key := range getValidConfigKeys(retryBase{}, "base") { - validKeys[key] = struct{}{} - } - - // Check keys - ignoredKeys := make([]string, 0) - for _, key := range keys { - if _, ok := validKeys[key]; !ok { - ignoredKeys = append(ignoredKeys, key) - } - } - - return ignoredKeys -} From 0a783460a8e4c1279af1330ab7d09e5645171589 Mon Sep 17 00:00:00 2001 From: pharr117 Date: Sat, 17 Feb 2024 21:58:21 -0500 Subject: [PATCH 2/2] Add filter config test using json parsing as mocks --- config/filter_config_test.go | 101 +++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 config/filter_config_test.go diff --git a/config/filter_config_test.go b/config/filter_config_test.go new file mode 100644 index 00000000..137177de --- /dev/null +++ b/config/filter_config_test.go @@ -0,0 +1,101 @@ +package config + +import ( + "encoding/json" + "testing" + + "github.com/DefiantLabs/cosmos-indexer/db/models" + "github.com/DefiantLabs/cosmos-indexer/filter" + "github.com/stretchr/testify/suite" +) + +type FilterConfigTestSuite struct { + suite.Suite +} + +//nolint:dogsled +func (suite *FilterConfigTestSuite) TestParseJSONFilterConfig() { + conf := blockFilterConfigs{} + + beginFilterEventTypeInvalid, err := getMockEventTypeBytes(true) + + suite.Require().NoError(err) + + conf.BeginBlockFilters = []json.RawMessage{beginFilterEventTypeInvalid} + + confBytes, err := json.Marshal(conf) + suite.Require().NoError(err) + + _, _, _, _, _, err = ParseJSONFilterConfig(confBytes) + + suite.Require().Error(err) + + beginFilterEventTypeValid, err := getMockEventTypeBytes(false) + suite.Require().NoError(err) + + conf.BeginBlockFilters = []json.RawMessage{beginFilterEventTypeValid} + + confBytes, err = json.Marshal(conf) + suite.Require().NoError(err) + + beginBlockFilters, _, _, _, _, err := ParseJSONFilterConfig(confBytes) + + suite.Require().NoError(err) + suite.Require().Len(beginBlockFilters, 1) + suite.Require().True(beginBlockFilters[0].EventMatches(filter.EventData{Event: models.BlockEvent{BlockEventType: models.BlockEventType{Type: "coin_received"}}})) + suite.Require().False(beginBlockFilters[0].EventMatches(filter.EventData{Event: models.BlockEvent{BlockEventType: models.BlockEventType{Type: "dne"}}})) + + conf.BeginBlockFilters = []json.RawMessage{} + + messageTypeFilterInvalid, err := getMockMessageTypeBytes(true) + suite.Require().NoError(err) + + conf.MessageTypeFilters = []json.RawMessage{messageTypeFilterInvalid} + + confBytes, err = json.Marshal(conf) + suite.Require().NoError(err) + + _, _, _, _, _, err = ParseJSONFilterConfig(confBytes) + suite.Require().Error(err) + + messageTypeFilterValid, err := getMockMessageTypeBytes(false) + suite.Require().NoError(err) + + conf.MessageTypeFilters = []json.RawMessage{messageTypeFilterValid} + + confBytes, err = json.Marshal(conf) + suite.Require().NoError(err) + + _, _, _, _, messageTypeFilters, err := ParseJSONFilterConfig(confBytes) + + suite.Require().NoError(err) + suite.Require().Len(messageTypeFilters, 1) + suite.Require().True(messageTypeFilters[0].MessageTypeMatches(filter.MessageTypeData{MessageType: "/cosmos.bank.v1beta1.MsgSend"})) + suite.Require().False(messageTypeFilters[0].MessageTypeMatches(filter.MessageTypeData{MessageType: "dne"})) +} + +func getMockEventTypeBytes(skipEventTypeKey bool) (json.RawMessage, error) { + mockEventType := make(map[string]any) + + mockEventType["type"] = "event_type" + if !skipEventTypeKey { + mockEventType["event_type"] = "coin_received" + } + + return json.Marshal(mockEventType) +} + +func getMockMessageTypeBytes(skipMessageTypeKey bool) (json.RawMessage, error) { + mockMessageType := make(map[string]any) + + mockMessageType["type"] = "message_type" + if !skipMessageTypeKey { + mockMessageType["message_type"] = "/cosmos.bank.v1beta1.MsgSend" + } + + return json.Marshal(mockMessageType) +} + +func TestFilterConfigTestSuite(t *testing.T) { + suite.Run(t, new(FilterConfigTestSuite)) +}