Skip to content

Commit

Permalink
Cleanups related to config package
Browse files Browse the repository at this point in the history
  • Loading branch information
tjayrush committed Jan 4, 2025
1 parent cf869e8 commit a2f12a0
Show file tree
Hide file tree
Showing 14 changed files with 159 additions and 234 deletions.
5 changes: 3 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@ import (
"os"

"github.com/TrueBlocks/trueblocks-khedra/v2/pkg/config"
"github.com/TrueBlocks/trueblocks-khedra/v2/pkg/types"
"github.com/urfave/cli/v2"
)

type KhedraApp struct {
Cli *cli.App
config *config.Config
config *types.Config
fileLogger *slog.Logger
progLogger *slog.Logger
}

func NewKhedraApp() *KhedraApp {
cfg := config.MustLoadConfig("config.yaml")
fileLogger, progLogger := config.NewLoggers(cfg.Logging)
fileLogger, progLogger := types.NewLoggers(cfg.Logging)
cli := initializeCli()

k := &KhedraApp{
Expand Down
127 changes: 45 additions & 82 deletions pkg/config/config_env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,16 @@ import (
"path/filepath"
"testing"

"github.com/TrueBlocks/trueblocks-khedra/v2/pkg/types"
"github.com/stretchr/testify/assert"
)

func TestMultipleChainsEnvironmentOverrides(t *testing.T) {
defer setTempEnvVar("TEST_MODE", "true")()
var configFile string

defer setTempEnvVar("TB_KHEDRA_CHAINS_MAINNET_RPCS", "http://rpc1.mainnet,http://rpc2.mainnet")()
defer setTempEnvVar("TB_KHEDRA_CHAINS_SEPOLIA_ENABLED", "true")()

// Use a temporary directory to simulate missing config
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.yaml")

// Mock getConfigFn to return the temporary config path
originalGetConfigFn := getConfigFn
getConfigFn = func() string { return configFile }
defer func() { getConfigFn = originalGetConfigFn }()

// Establish the config file if it doesn't exist
establishConfig(configFile)
defer setupTest(t, &configFile)()

// Load the configuration
cfg := MustLoadConfig(configFile)
Expand All @@ -33,22 +24,12 @@ func TestMultipleChainsEnvironmentOverrides(t *testing.T) {
}

func TestEnvironmentVariableOverridesForServices(t *testing.T) {
// Set environment variables to override the configuration
var configFile string

defer setTempEnvVar("TB_KHEDRA_SERVICES_API_ENABLED", "false")()
defer setTempEnvVar("TB_KHEDRA_SERVICES_API_PORT", "9090")()
defer setTempEnvVar("TEST_MODE", "true")()

// Create a temporary directory for the config file
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.yaml")

// Mock getConfigFn to return the temporary config path
originalGetConfigFn := getConfigFn
getConfigFn = func() string { return configFile }
defer func() { getConfigFn = originalGetConfigFn }()

// Establish the configuration file
establishConfig(configFile)
defer setupTest(t, &configFile)()

// Load the configuration
cfg := MustLoadConfig(configFile)
Expand All @@ -63,25 +44,13 @@ func TestEnvironmentVariableOverridesForServices(t *testing.T) {
}

func TestMultipleServicesEnvironmentOverrides(t *testing.T) {
// Set environment variables to override the configuration
var configFile string

defer setTempEnvVar("TB_KHEDRA_SERVICES_API_ENABLED", "false")()
defer setTempEnvVar("TB_KHEDRA_SERVICES_SCRAPER_ENABLED", "true")()
defer setTempEnvVar("TB_KHEDRA_SERVICES_SCRAPER_PORT", "8081")()
defer setTempEnvVar("TEST_MODE", "true")()

// Create a temporary directory for the config file
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.yaml")

// Mock getConfigFn to return the temporary config path
originalGetConfigFn := getConfigFn
getConfigFn = func() string { return configFile }
defer func() { getConfigFn = originalGetConfigFn }()
defer setupTest(t, &configFile)()

// Establish the configuration file
establishConfig(configFile)

// Load the configuration
cfg := MustLoadConfig(configFile)

// Check if the API and Scraper services exist in the configuration
Expand All @@ -98,21 +67,9 @@ func TestMultipleServicesEnvironmentOverrides(t *testing.T) {
}

func TestNoEnvironmentVariables(t *testing.T) {
defer setTempEnvVar("TEST_MODE", "true")()

// Use a temporary directory to simulate missing config
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.yaml")

// Mock getConfigFn to return the temporary config path
originalGetConfigFn := getConfigFn
getConfigFn = func() string { return configFile }
defer func() { getConfigFn = originalGetConfigFn }()

// Establish the config file if it doesn't exist
establishConfig(configFile)
var configFile string
defer setupTest(t, &configFile)()

// Load the configuration
cfg := MustLoadConfig(configFile)

assert.NotEqual(t, cfg.Chains["mainnet"], nil, "mainnet chain should exist in the configuration")
Expand All @@ -121,44 +78,21 @@ func TestNoEnvironmentVariables(t *testing.T) {
}

func TestEnvironmentVariableOverridesForChains(t *testing.T) {
defer setTempEnvVar("TEST_MODE", "true")()
var configFile string

defer setTempEnvVar("TB_KHEDRA_CHAINS_MAINNET_RPCS", "http://rpc1.mainnet,http://rpc2.mainnet")()
defer setTempEnvVar("TB_KHEDRA_CHAINS_MAINNET_ENABLED", "false")()
defer setupTest(t, &configFile)()

// Use a temporary directory to simulate missing config
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.yaml")

// Mock getConfigFn to return the temporary config path
originalGetConfigFn := getConfigFn
getConfigFn = func() string { return configFile }
defer func() { getConfigFn = originalGetConfigFn }()

// Establish the config file if it doesn't exist
establishConfig(configFile)

// Load the configuration
cfg := MustLoadConfig(configFile)

assert.Equal(t, []string{"http://rpc1.mainnet", "http://rpc2.mainnet"}, cfg.Chains["mainnet"].RPCs, "RPCs for mainnet should be overridden by environment variable")
assert.False(t, cfg.Chains["mainnet"].Enabled, "Enabled flag for mainnet should be overridden by environment variable")
}

func TestInvalidBooleanValueForChains(t *testing.T) {
defer setTempEnvVar("TEST_MODE", "true")()
defer setTempEnvVar("TB_KHEDRA_CHAINS_MAINNET_ENABLED", "not_a_bool")()

// Use a temporary directory to simulate missing config
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.yaml")

// Mock getConfigFn to return the temporary config path
originalGetConfigFn := getConfigFn
getConfigFn = func() string { return configFile }
defer func() { getConfigFn = originalGetConfigFn }()

// Establish the config file if it doesn't exist
establishConfig(configFile)
defer setupTest(t, nil)()

// Attempt to load the configuration and expect an error
_, err := loadConfig()
Expand All @@ -178,3 +112,32 @@ func setTempEnvVar(key, value string) func() {
}
}
}

// setupTest sets up a temporary folder, updates the getConfigFn pointer, calls establishConfig,
// and assigns the config file path to the provided string pointer if it is not nil.
// Returns a cleanup function to restore the original state.
func setupTest(t *testing.T, configFile *string) func() {
os.Setenv("TEST_MODE", "true")

// Use a temporary directory to simulate the config environment
tmpDir := t.TempDir()
tempConfigFile := filepath.Join(tmpDir, "config.yaml")

// If configFile pointer is not nil, assign the path to it
if configFile != nil {
*configFile = tempConfigFile
}

// Mock getConfigFn to return the temporary config path
originalGetConfigFn := getConfigFn
getConfigFn = func() string { return tempConfigFile }

// Establish the config file
types.EstablishConfig(tempConfigFile)

// Return a cleanup function to restore the original state
return func() {
os.Unsetenv("TEST_MODE")
getConfigFn = originalGetConfigFn
}
}
67 changes: 12 additions & 55 deletions pkg/config/edge_case_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,107 +3,64 @@ package config

import (
"fmt"
"path/filepath"
"strconv"
"testing"

"github.com/TrueBlocks/trueblocks-khedra/v2/pkg/types"
"github.com/stretchr/testify/assert"
)

func TestInvalidPortForService(t *testing.T) {
// Set an invalid port for the API service
defer setTempEnvVar("TB_KHEDRA_SERVICES_API_PORT", "invalid_port")()
defer setTempEnvVar("TEST_MODE", "true")()
defer setupTest(t, nil)()

// Use a temporary directory to simulate missing config
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.yaml")

originalGetConfigFn := getConfigFn
getConfigFn = func() string { return configFile }
defer func() { getConfigFn = originalGetConfigFn }()

establishConfig(configFile)

// Load the configuration and expect an error
_, err := loadConfig()
assert.Error(t, err, "loadConfig should return an error for invalid port value")
assert.Contains(t, err.Error(), "invalid_port", "Error message should indicate invalid port")
}

func TestLargeNumberOfChains(t *testing.T) {
// Set a large number of chains in the configuration
defer setTempEnvVar("TEST_MODE", "true")()

tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.yaml")
var configFile string
defer setupTest(t, &configFile)()

originalGetConfigFn := getConfigFn
getConfigFn = func() string { return configFile }
defer func() { getConfigFn = originalGetConfigFn }()

establishConfig(configFile)

cfg := NewConfig()
cfg.Chains = make(map[string]Chain)
cfg := types.NewConfig()
cfg.Chains = make(map[string]types.Chain)
nChains := 1000
for i := 0; i < nChains; i++ {
chainName := "chain" + strconv.Itoa(i)
// fmt.Println(chainName)
cfg.Chains[chainName] = Chain{
cfg.Chains[chainName] = types.Chain{
Name: chainName,
RPCs: []string{fmt.Sprintf("http://%s.rpc", chainName)},
Enabled: true,
}
}

// Write the large config to the file
writeConfig(&cfg, configFile)
types.WriteConfig(&cfg, configFile)

// Load the configuration and verify all chains are present
cfg = MustLoadConfig(configFile)
assert.Equal(t, nChains+2, len(cfg.Chains), "All chains should be loaded correctly")
}

func TestMissingChainInConfig(t *testing.T) {
// Set environment variables for a chain not in the config file
defer setTempEnvVar("TB_KHEDRA_CHAINS_UNKNOWN_NAME", "unknown")()
defer setTempEnvVar("TB_KHEDRA_CHAINS_UNKNOWN_RPCS", "http://unknown.rpc")()
defer setTempEnvVar("TB_KHEDRA_CHAINS_UNKNOWN_ENABLED", "true")()
defer setTempEnvVar("TEST_MODE", "true")()

// Use a temporary directory to simulate missing config
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.yaml")

originalGetConfigFn := getConfigFn
getConfigFn = func() string { return configFile }
defer func() { getConfigFn = originalGetConfigFn }()

establishConfig(configFile)
defer setupTest(t, nil)()

_, err := loadConfig()
assert.Error(t, err, "An error should occur if an unknown chain is defined in the environment but not in the configuration file")
}

func TestEmptyRPCsForChain(t *testing.T) {
// Set RPCs for the mainnet chain to an invalid empty value
defer setTempEnvVar("TB_KHEDRA_CHAINS_MAINNET_RPCS", "")()
defer setTempEnvVar("TEST_MODE", "true")()
var configFile string

// Use a temporary directory to simulate missing config
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "config.yaml")

originalGetConfigFn := getConfigFn
getConfigFn = func() string { return configFile }
defer func() { getConfigFn = originalGetConfigFn }()

establishConfig(configFile)
defer setTempEnvVar("TB_KHEDRA_CHAINS_MAINNET_RPCS", "")()
defer setupTest(t, &configFile)()

// Load the configuration
cfg := MustLoadConfig(configFile)

// Ensure the configuration does not include an empty RPC array
assert.NotEmpty(t, cfg.Chains["mainnet"].RPCs, "Mainnet RPCs should not be empty in the final configuration")
}
Loading

0 comments on commit a2f12a0

Please sign in to comment.