diff --git a/cmd/solana_exporter/config_test.go b/cmd/solana_exporter/config_test.go new file mode 100644 index 0000000..b494bad --- /dev/null +++ b/cmd/solana_exporter/config_test.go @@ -0,0 +1,106 @@ +package main + +import ( + "context" + "github.com/stretchr/testify/assert" + "testing" + "time" +) + +func TestNewExporterConfig(t *testing.T) { + simulator, _ := NewSimulator(t, 35) + tests := []struct { + name string + httpTimeout time.Duration + rpcUrl string + listenAddress string + nodeKeys []string + balanceAddresses []string + comprehensiveSlotTracking bool + monitorBlockSizes bool + lightMode bool + slotPace time.Duration + wantErr bool + expectedVoteKeys []string + }{ + { + name: "valid configuration", + httpTimeout: 60 * time.Second, + rpcUrl: simulator.Server.URL(), + listenAddress: ":8080", + nodeKeys: nodekeys, + balanceAddresses: []string{"xxx", "yyy", "zzz"}, + comprehensiveSlotTracking: false, + monitorBlockSizes: false, + lightMode: false, + slotPace: time.Second, + wantErr: false, + expectedVoteKeys: votekeys, + }, + { + name: "light mode with incompatible options", + httpTimeout: 60 * time.Second, + rpcUrl: simulator.Server.URL(), + listenAddress: ":8080", + nodeKeys: nodekeys, + balanceAddresses: []string{"xxx", "yyy", "zzz"}, + comprehensiveSlotTracking: true, + monitorBlockSizes: false, + lightMode: true, + slotPace: time.Second, + wantErr: true, + expectedVoteKeys: nil, + }, + { + name: "empty node keys", + httpTimeout: 60 * time.Second, + rpcUrl: simulator.Server.URL(), + listenAddress: ":8080", + nodeKeys: []string{}, + balanceAddresses: []string{"xxx", "yyy", "zzz"}, + comprehensiveSlotTracking: false, + monitorBlockSizes: false, + lightMode: false, + slotPace: time.Second, + wantErr: false, + expectedVoteKeys: []string{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + config, err := NewExporterConfig( + context.Background(), + tt.httpTimeout, + tt.rpcUrl, + tt.listenAddress, + tt.nodeKeys, + tt.balanceAddresses, + tt.comprehensiveSlotTracking, + tt.monitorBlockSizes, + tt.lightMode, + tt.slotPace, + ) + + // Check error expectation + if tt.wantErr { + assert.Errorf(t, err, "NewExporterConfig() error = %v, wantErr %v", err, tt.wantErr) + return + } + + assert.NoError(t, err) + + // Verify config values + assert.Equal(t, tt.httpTimeout, config.HttpTimeout) + assert.Equal(t, tt.rpcUrl, config.RpcUrl) + assert.Equal(t, tt.listenAddress, config.ListenAddress) + assert.Equal(t, tt.nodeKeys, config.NodeKeys) + assert.Equal(t, tt.balanceAddresses, config.BalanceAddresses) + assert.Equal(t, tt.comprehensiveSlotTracking, config.MonitorBlockSizes) + assert.Equal(t, tt.lightMode, config.LightMode) + assert.Equal(t, tt.slotPace, config.SlotPace) + assert.Equal(t, tt.monitorBlockSizes, config.MonitorBlockSizes) + assert.Equal(t, tt.expectedVoteKeys, config.VoteKeys) + }) + } +} diff --git a/cmd/solana_exporter/exporter_test.go b/cmd/solana_exporter/exporter_test.go index 3daf022..6ee7d1a 100644 --- a/cmd/solana_exporter/exporter_test.go +++ b/cmd/solana_exporter/exporter_test.go @@ -18,7 +18,7 @@ import ( ) type ( - DynamicServer struct { + Simulator struct { Server *rpc.MockServer Slot int @@ -95,7 +95,7 @@ func voteTx(nodekey string) []string { return []string{nodekey, strings.ToUpper(nodekey), VoteProgram} } -func NewDynamicRpcClient(t *testing.T, slot int) (*DynamicServer, *rpc.Client) { +func NewSimulator(t *testing.T, slot int) (*Simulator, *rpc.Client) { validatorInfos := make(map[string]rpc.MockValidatorInfo) for _, nodekey := range nodekeys { validatorInfos[nodekey] = rpc.MockValidatorInfo{ @@ -115,7 +115,7 @@ func NewDynamicRpcClient(t *testing.T, slot int) (*DynamicServer, *rpc.Client) { nil, validatorInfos, ) - server := DynamicServer{ + server := Simulator{ Slot: 0, Server: mockServer, EpochSize: 24, @@ -133,7 +133,7 @@ func NewDynamicRpcClient(t *testing.T, slot int) (*DynamicServer, *rpc.Client) { return &server, client } -func (c *DynamicServer) Run(ctx context.Context) { +func (c *Simulator) Run(ctx context.Context) { for { select { case <-ctx.Done(): @@ -150,7 +150,7 @@ func (c *DynamicServer) Run(ctx context.Context) { } } -func (c *DynamicServer) getLeader() string { +func (c *Simulator) getLeader() string { index := c.Slot % c.EpochSize for leader, slots := range c.LeaderSchedule { if slices.Contains(slots, index) { @@ -160,7 +160,7 @@ func (c *DynamicServer) getLeader() string { panic(fmt.Sprintf("leader not found at slot %d", c.Slot)) } -func (c *DynamicServer) PopulateSlot(slot int) { +func (c *Simulator) PopulateSlot(slot int) { leader := c.getLeader() var block *rpc.MockBlockInfo @@ -272,7 +272,7 @@ func newTestConfig(fast bool) *ExporterConfig { } func TestSolanaCollector(t *testing.T) { - _, client := NewDynamicRpcClient(t, 35) + _, client := NewSimulator(t, 35) collector := NewSolanaCollector(client, newTestConfig(false)) prometheus.NewPedanticRegistry().MustRegister(collector) diff --git a/cmd/solana_exporter/slots_test.go b/cmd/solana_exporter/slots_test.go index 8e2ce11..3a5af79 100644 --- a/cmd/solana_exporter/slots_test.go +++ b/cmd/solana_exporter/slots_test.go @@ -62,7 +62,7 @@ func TestSlotWatcher_WatchSlots_Static(t *testing.T) { config := newTestConfig(true) - _, client := NewDynamicRpcClient(t, 35) + _, client := NewSimulator(t, 35) watcher := NewSlotWatcher(client, config) // reset metrics before running tests: @@ -117,7 +117,7 @@ func TestSlotWatcher_WatchSlots_Static(t *testing.T) { func TestSlotWatcher_WatchSlots_Dynamic(t *testing.T) { // create clients: - server, client := NewDynamicRpcClient(t, 35) + server, client := NewSimulator(t, 35) ctx, cancel := context.WithCancel(context.Background()) defer cancel() config := newTestConfig(true)