refactored WatchSlots_Dynamic test

This commit is contained in:
Matt Johnstone 2024-10-29 00:15:21 +02:00
parent 1582782904
commit d06edc078e
No known key found for this signature in database
GPG Key ID: BE985FBB9BE7D3BB
10 changed files with 248 additions and 180 deletions

View File

@ -28,21 +28,21 @@ func TestNewExporterConfig(t *testing.T) {
httpTimeout: 60 * time.Second,
rpcUrl: simulator.Server.URL(),
listenAddress: ":8080",
nodeKeys: nodekeys,
nodeKeys: simulator.Nodekeys,
balanceAddresses: []string{"xxx", "yyy", "zzz"},
comprehensiveSlotTracking: false,
monitorBlockSizes: false,
lightMode: false,
slotPace: time.Second,
wantErr: false,
expectedVoteKeys: votekeys,
expectedVoteKeys: simulator.Votekeys,
},
{
name: "light mode with incompatible options",
httpTimeout: 60 * time.Second,
rpcUrl: simulator.Server.URL(),
listenAddress: ":8080",
nodeKeys: nodekeys,
nodeKeys: simulator.Nodekeys,
balanceAddresses: []string{"xxx", "yyy", "zzz"},
comprehensiveSlotTracking: true,
monitorBlockSizes: false,

View File

@ -41,7 +41,3 @@ func (c *GaugeDesc) expectedCollection(labeledValues ...LV) string {
func (c *GaugeDesc) makeCollectionTest(labeledValues ...LV) collectionTest {
return collectionTest{Name: c.Name, ExpectedResponse: c.expectedCollection(labeledValues...)}
}
func abcValues(a, b, c float64) []LV {
return []LV{NewLV(a, "aaa", "AAA"), NewLV(b, "bbb", "BBB"), NewLV(c, "ccc", "CCC")}
}

View File

@ -25,8 +25,8 @@ const (
StateCurrent = "current"
StateDelinquent = "delinquent"
TransactionTypeVote = "vote"
TransactionTypeTotal = "total"
TransactionTypeVote = "vote"
TransactionTypeNonVote = "non_vote"
)
type SolanaCollector struct {

View File

@ -17,6 +17,9 @@ import (
"time"
)
const InflationRewardLamports = 10
const FeeRewardLamports = 10
type (
Simulator struct {
Server *rpc.MockServer
@ -24,113 +27,80 @@ type (
Slot int
BlockHeight int
Epoch int
EpochSize int
SlotTime time.Duration
TransactionCount int
LeaderSchedule map[string][]int
SlotTime time.Duration
EpochSize int
LeaderSchedule map[string][]int
Nodekeys []string
Votekeys []string
}
)
var (
nodekeys = []string{"aaa", "bbb", "ccc"}
votekeys = []string{"AAA", "BBB", "CCC"}
balances = map[string]float64{"aaa": 1, "bbb": 2, "ccc": 3, "AAA": 4, "BBB": 5, "CCC": 6}
rawVoteAccounts = map[string]any{
"current": []map[string]any{
{
"activatedStake": 42,
"lastVote": 147,
"nodePubkey": "bbb",
"rootSlot": 18,
"votePubkey": "BBB",
},
{
"activatedStake": 43,
"lastVote": 148,
"nodePubkey": "ccc",
"rootSlot": 19,
"votePubkey": "CCC",
},
},
"delinquent": []map[string]any{
{
"activatedStake": 49,
"lastVote": 92,
"nodePubkey": "aaa",
"rootSlot": 3,
"votePubkey": "AAA",
},
},
}
rawBalances = map[string]int{
"aaa": 1 * rpc.LamportsInSol,
"bbb": 2 * rpc.LamportsInSol,
"ccc": 3 * rpc.LamportsInSol,
"AAA": 4 * rpc.LamportsInSol,
"BBB": 5 * rpc.LamportsInSol,
"CCC": 6 * rpc.LamportsInSol,
}
balanceMetricResponse = `
# HELP solana_account_balance Solana account balances, grouped by address
# TYPE solana_account_balance gauge
solana_account_balance{address="AAA"} 4
solana_account_balance{address="BBB"} 5
solana_account_balance{address="CCC"} 6
solana_account_balance{address="aaa"} 1
solana_account_balance{address="bbb"} 2
solana_account_balance{address="ccc"} 3
`
dynamicLeaderSchedule = map[string][]int{
"aaa": {0, 1, 2, 3, 12, 13, 14, 15},
"bbb": {4, 5, 6, 7, 16, 17, 18, 19},
"ccc": {8, 9, 10, 11, 20, 21, 22, 23},
}
)
/*
===== DYNAMIC CLIENT =====:
*/
func voteTx(nodekey string) []string {
return []string{nodekey, strings.ToUpper(nodekey), VoteProgram}
}
func NewSimulator(t *testing.T, slot int) (*Simulator, *rpc.Client) {
nodekeys := []string{"aaa", "bbb", "ccc"}
votekeys := []string{"AAA", "BBB", "CCC"}
validatorInfos := make(map[string]rpc.MockValidatorInfo)
for _, nodekey := range nodekeys {
for i, nodekey := range nodekeys {
validatorInfos[nodekey] = rpc.MockValidatorInfo{
Votekey: strings.ToUpper(nodekey),
Votekey: votekeys[i],
Stake: 1_000_000,
Delinquent: false,
}
}
leaderSchedule := map[string][]int{
"aaa": {0, 1, 2, 3, 12, 13, 14, 15},
"bbb": {4, 5, 6, 7, 16, 17, 18, 19},
"ccc": {8, 9, 10, 11, 20, 21, 22, 23},
}
mockServer, client := rpc.NewMockClient(t,
map[string]any{
"getVersion": map[string]string{"solana-core": "v1.0.0"},
"getLeaderSchedule": dynamicLeaderSchedule,
"getLeaderSchedule": leaderSchedule,
"getHealth": "ok",
},
rawBalances,
map[string]int{"AAA": 10, "BBB": 10, "CCC": 10},
map[string]int{
"aaa": 1 * rpc.LamportsInSol,
"bbb": 2 * rpc.LamportsInSol,
"ccc": 3 * rpc.LamportsInSol,
"AAA": 4 * rpc.LamportsInSol,
"BBB": 5 * rpc.LamportsInSol,
"CCC": 6 * rpc.LamportsInSol,
},
map[string]int{
"AAA": InflationRewardLamports,
"BBB": InflationRewardLamports,
"CCC": InflationRewardLamports,
},
nil,
validatorInfos,
)
server := Simulator{
simulator := Simulator{
Slot: 0,
Server: mockServer,
EpochSize: 24,
SlotTime: 100 * time.Millisecond,
LeaderSchedule: dynamicLeaderSchedule,
LeaderSchedule: leaderSchedule,
Nodekeys: nodekeys,
Votekeys: votekeys,
}
server.PopulateSlot(0)
for {
server.Slot++
server.PopulateSlot(server.Slot)
if server.Slot == slot {
break
simulator.PopulateSlot(0)
if slot > 0 {
for {
simulator.Slot++
simulator.PopulateSlot(simulator.Slot)
if simulator.Slot == slot {
break
}
}
}
return &server, client
return &simulator, client
}
func (c *Simulator) Run(ctx context.Context) {
@ -173,7 +143,7 @@ func (c *Simulator) PopulateSlot(slot int) {
{"xxx", "yyy", "zzz"},
}
// assume all validators voted
for _, nodekey := range nodekeys {
for _, nodekey := range c.Nodekeys {
transactions = append(transactions, voteTx(nodekey))
info := c.Server.GetValidatorInfo(nodekey)
info.LastVote = slot
@ -181,7 +151,7 @@ func (c *Simulator) PopulateSlot(slot int) {
}
c.TransactionCount += len(transactions)
block = &rpc.MockBlockInfo{Fee: 100, Transactions: transactions}
block = &rpc.MockBlockInfo{Fee: FeeRewardLamports, Transactions: transactions}
}
// add slot info:
c.Server.SetOpt(rpc.SlotInfosOpt, slot, rpc.MockSlotInfo{Leader: leader, Block: block})
@ -251,17 +221,17 @@ func runCollectionTests(t *testing.T, collector prometheus.Collector, testCases
}
}
func newTestConfig(fast bool) *ExporterConfig {
func newTestConfig(simulator *Simulator, fast bool) *ExporterConfig {
pace := time.Duration(100) * time.Second
if fast {
pace = time.Duration(500) * time.Millisecond
}
config := ExporterConfig{
time.Second * time.Duration(1),
"http://localhost:8899",
simulator.Server.URL(),
":8080",
nodekeys,
votekeys,
simulator.Nodekeys,
simulator.Votekeys,
nil,
true,
true,
@ -272,19 +242,54 @@ func newTestConfig(fast bool) *ExporterConfig {
}
func TestSolanaCollector(t *testing.T) {
_, client := NewSimulator(t, 35)
collector := NewSolanaCollector(client, newTestConfig(false))
simulator, client := NewSimulator(t, 35)
collector := NewSolanaCollector(client, newTestConfig(simulator, false))
prometheus.NewPedanticRegistry().MustRegister(collector)
testCases := []collectionTest{
collector.ValidatorActiveStake.makeCollectionTest(abcValues(1_000_000, 1_000_000, 1_000_000)...),
collector.ValidatorLastVote.makeCollectionTest(abcValues(34, 34, 34)...),
collector.ValidatorRootSlot.makeCollectionTest(abcValues(0, 0, 0)...),
collector.ValidatorDelinquent.makeCollectionTest(abcValues(0, 0, 0)...),
{Name: "solana_account_balance", ExpectedResponse: balanceMetricResponse},
collector.NodeVersion.makeCollectionTest(NewLV(1, "v1.0.0")),
collector.NodeIsHealthy.makeCollectionTest(NewLV(1)),
collector.NodeNumSlotsBehind.makeCollectionTest(NewLV(0)),
collector.ValidatorActiveStake.makeCollectionTest(
NewLV(1_000_000, "aaa", "AAA"),
NewLV(1_000_000, "bbb", "BBB"),
NewLV(1_000_000, "ccc", "CCC"),
),
collector.ValidatorLastVote.makeCollectionTest(
NewLV(34, "aaa", "AAA"),
NewLV(34, "bbb", "BBB"),
NewLV(34, "ccc", "CCC"),
),
collector.ValidatorRootSlot.makeCollectionTest(
NewLV(0, "aaa", "AAA"),
NewLV(0, "bbb", "BBB"),
NewLV(0, "ccc", "CCC"),
),
collector.ValidatorDelinquent.makeCollectionTest(
NewLV(0, "aaa", "AAA"),
NewLV(0, "bbb", "BBB"),
NewLV(0, "ccc", "CCC"),
),
collector.NodeVersion.makeCollectionTest(
NewLV(1, "v1.0.0"),
),
collector.NodeIsHealthy.makeCollectionTest(
NewLV(1),
),
collector.NodeNumSlotsBehind.makeCollectionTest(
NewLV(0),
),
collector.AccountBalances.makeCollectionTest(
NewLV(4, "AAA"),
NewLV(5, "BBB"),
NewLV(6, "CCC"),
NewLV(1, "aaa"),
NewLV(2, "bbb"),
NewLV(3, "ccc"),
),
collector.NodeMinimumLedgerSlot.makeCollectionTest(
NewLV(11),
),
collector.NodeFirstAvailableBlock.makeCollectionTest(
NewLV(11),
),
}
runCollectionTests(t, collector, testCases)

View File

@ -80,7 +80,7 @@ func NewSlotWatcher(client *rpc.Client, config *ExporterConfig) *SlotWatcher {
NodekeyLabel, SkipStatusLabel, StatusValid, StatusSkipped,
),
},
[]string{SkipStatusLabel, NodekeyLabel},
[]string{NodekeyLabel, SkipStatusLabel},
),
LeaderSlotsByEpochMetric: prometheus.NewCounterVec(
prometheus.CounterOpts{
@ -90,7 +90,7 @@ func NewSlotWatcher(client *rpc.Client, config *ExporterConfig) *SlotWatcher {
NodekeyLabel, SkipStatusLabel, StatusValid, StatusSkipped, EpochLabel,
),
},
[]string{SkipStatusLabel, NodekeyLabel, EpochLabel},
[]string{NodekeyLabel, EpochLabel, SkipStatusLabel},
),
InflationRewardsMetric: prometheus.NewGaugeVec(
prometheus.GaugeOpts{
@ -314,13 +314,13 @@ func (c *SlotWatcher) fetchAndEmitBlockProduction(ctx context.Context, endSlot i
valid := float64(production.BlocksProduced)
skipped := float64(production.LeaderSlots - production.BlocksProduced)
c.LeaderSlotsMetric.WithLabelValues(StatusValid, address).Add(valid)
c.LeaderSlotsMetric.WithLabelValues(StatusSkipped, address).Add(skipped)
c.LeaderSlotsMetric.WithLabelValues(address, StatusValid).Add(valid)
c.LeaderSlotsMetric.WithLabelValues(address, StatusSkipped).Add(skipped)
if slices.Contains(c.config.NodeKeys, address) || c.config.ComprehensiveSlotTracking {
epochStr := toString(c.currentEpoch)
c.LeaderSlotsByEpochMetric.WithLabelValues(StatusValid, address, epochStr).Add(valid)
c.LeaderSlotsByEpochMetric.WithLabelValues(StatusSkipped, address, epochStr).Add(skipped)
c.LeaderSlotsByEpochMetric.WithLabelValues(address, epochStr, StatusValid).Add(valid)
c.LeaderSlotsByEpochMetric.WithLabelValues(address, epochStr, StatusSkipped).Add(skipped)
}
}
@ -395,15 +395,15 @@ func (c *SlotWatcher) fetchAndEmitSingleBlockInfo(
// track block size:
if c.config.MonitorBlockSizes {
c.BlockSizeMetric.WithLabelValues(nodekey, TransactionTypeTotal).Set(float64(len(block.Transactions)))
// now count and emit votes:
voteCount, err := CountVoteTransactions(block)
if err != nil {
return err
}
c.BlockSizeMetric.WithLabelValues(nodekey, TransactionTypeVote).Set(float64(voteCount))
nonVoteCount := len(block.Transactions) - voteCount
c.BlockSizeMetric.WithLabelValues(nodekey, TransactionTypeNonVote).Set(float64(nonVoteCount))
}
return nil
}

View File

@ -17,6 +17,7 @@ type slotMetricValues struct {
EpochNumber float64
EpochFirstSlot float64
EpochLastSlot float64
BlockHeight float64
}
func getSlotMetricValues(watcher *SlotWatcher) slotMetricValues {
@ -26,45 +27,58 @@ func getSlotMetricValues(watcher *SlotWatcher) slotMetricValues {
EpochNumber: testutil.ToFloat64(watcher.EpochNumberMetric),
EpochFirstSlot: testutil.ToFloat64(watcher.EpochFirstSlotMetric),
EpochLastSlot: testutil.ToFloat64(watcher.EpochLastSlotMetric),
BlockHeight: testutil.ToFloat64(watcher.BlockHeightMetric),
}
}
func assertSlotMetricsChangeCorrectly(t *testing.T, initial slotMetricValues, final slotMetricValues) {
// make sure that things have increased
assert.Greaterf(
t,
assert.Greaterf(t,
final.SlotHeight,
initial.SlotHeight,
"Slot has not increased! (%v -> %v)",
initial.SlotHeight,
final.SlotHeight,
initial.SlotHeight, final.SlotHeight,
)
assert.Greaterf(
t,
assert.Greaterf(t,
final.TotalTransactions,
initial.TotalTransactions,
"Total transactions have not increased! (%v -> %v)",
initial.TotalTransactions,
final.TotalTransactions,
initial.TotalTransactions, final.TotalTransactions,
)
assert.GreaterOrEqualf(
t,
assert.GreaterOrEqualf(t,
final.EpochNumber,
initial.EpochNumber,
"Epoch number has decreased! (%v -> %v)",
initial.EpochNumber,
final.EpochNumber,
initial.EpochNumber, final.EpochNumber,
)
assert.GreaterOrEqualf(t,
final.EpochFirstSlot,
initial.EpochFirstSlot,
"Epoch first slot has decreased! (%v -> %v)",
initial.EpochFirstSlot, final.EpochFirstSlot,
)
assert.GreaterOrEqualf(t,
final.EpochLastSlot,
initial.EpochLastSlot,
"Epoch last slot has decreased! (%v -> %v)",
initial.EpochLastSlot, final.EpochLastSlot,
)
assert.Greaterf(t,
final.BlockHeight,
initial.BlockHeight,
"Block height has decreased! (%v -> %v)",
initial.BlockHeight, final.BlockHeight,
)
}
func TestSlotWatcher_WatchSlots_Static(t *testing.T) {
ctx := context.Background()
// TODO: is this test necessary? If not - remove, else, could definitely do with a clean.
config := newTestConfig(true)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
_, client := NewSimulator(t, 35)
watcher := NewSlotWatcher(client, config)
simulator, client := NewSimulator(t, 35)
watcher := NewSlotWatcher(client, newTestConfig(simulator, true))
// reset metrics before running tests:
watcher.LeaderSlotsMetric.Reset()
watcher.LeaderSlotsByEpochMetric.Reset()
@ -94,7 +108,7 @@ func TestSlotWatcher_WatchSlots_Static(t *testing.T) {
}
// add inflation reward tests:
inflationRewards, err := client.GetInflationReward(ctx, rpc.CommitmentFinalized, votekeys, 2)
inflationRewards, err := client.GetInflationReward(ctx, rpc.CommitmentFinalized, simulator.Votekeys, 2)
assert.NoError(t, err)
for i, rewardInfo := range inflationRewards {
epoch := fmt.Sprintf("%v", epochInfo.Epoch)
@ -102,7 +116,7 @@ func TestSlotWatcher_WatchSlots_Static(t *testing.T) {
tests,
testCase{
expectedValue: float64(rewardInfo.Amount) / float64(rpc.LamportsInSol),
metric: watcher.InflationRewardsMetric.WithLabelValues(votekeys[i], epoch),
metric: watcher.InflationRewardsMetric.WithLabelValues(simulator.Votekeys[i], epoch),
},
)
}
@ -116,24 +130,23 @@ func TestSlotWatcher_WatchSlots_Static(t *testing.T) {
}
func TestSlotWatcher_WatchSlots_Dynamic(t *testing.T) {
// TODO: figure out how to get rid of the error logs that happen when this test closes.
// This is presumably due to the context cancelling mid-execution of a WatchSlots() iteration
// create clients:
server, client := NewSimulator(t, 35)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
config := newTestConfig(true)
collector := NewSolanaCollector(client, config)
watcher := NewSlotWatcher(client, config)
simulator, client := NewSimulator(t, 23)
watcher := NewSlotWatcher(client, newTestConfig(simulator, true))
// reset metrics before running tests:
watcher.LeaderSlotsMetric.Reset()
watcher.LeaderSlotsByEpochMetric.Reset()
prometheus.NewPedanticRegistry().MustRegister(collector)
// start client/collector and wait a bit:
go server.Run(ctx)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go watcher.WatchSlots(ctx)
time.Sleep(time.Second)
go watcher.WatchSlots(ctx)
go simulator.Run(ctx)
time.Sleep(time.Second)
initial := getSlotMetricValues(watcher)
@ -149,34 +162,87 @@ func TestSlotWatcher_WatchSlots_Dynamic(t *testing.T) {
assertSlotMetricsChangeCorrectly(t, initial, final)
// sense check to make sure the exporter is not "ahead" of the client (due to double counting or whatever)
assert.LessOrEqualf(
t,
assert.LessOrEqualf(t,
int(final.SlotHeight),
server.Slot,
"Exporter slot (%v) ahead of client slot (%v)!",
int(final.SlotHeight),
server.Slot,
simulator.Slot,
"Exporter slot (%v) ahead of simulator slot (%v)!",
int(final.SlotHeight), simulator.Slot,
)
assert.LessOrEqualf(
t,
assert.LessOrEqualf(t,
int(final.TotalTransactions),
server.TransactionCount,
"Exporter transaction count (%v) ahead of client transaction count (%v)!",
int(final.TotalTransactions),
server.TransactionCount,
simulator.TransactionCount,
"Exporter transaction count (%v) ahead of simulator transaction count (%v)!",
int(final.TotalTransactions), simulator.TransactionCount,
)
assert.LessOrEqualf(
t,
assert.LessOrEqualf(t,
int(final.EpochNumber),
server.Epoch,
"Exporter epoch (%v) ahead of client epoch (%v)!",
int(final.EpochNumber),
server.Epoch,
simulator.Epoch,
"Exporter epoch (%v) ahead of simulator epoch (%v)!",
int(final.EpochNumber), simulator.Epoch,
)
// check block sizes (should always be the same due to simulator design:
for _, nodekey := range simulator.Nodekeys {
assert.Equalf(t,
float64(2),
testutil.ToFloat64(watcher.BlockSizeMetric.WithLabelValues(nodekey, TransactionTypeNonVote)),
"Incorrect %s block size for %s",
TransactionTypeNonVote, nodekey,
)
assert.Equalf(t,
float64(3),
testutil.ToFloat64(watcher.BlockSizeMetric.WithLabelValues(nodekey, TransactionTypeVote)),
"Incorrect %s block size for %s",
TransactionTypeVote, nodekey,
)
}
// check if epoch changed
if final.EpochNumber > initial.EpochNumber {
epochChanged = true
// run some tests for the previous epoch:
leaderSlotsPerEpoch := simulator.EpochSize / len(simulator.Nodekeys)
for i, nodekey := range simulator.Nodekeys {
// leader slots per epoch:
assert.Equalf(t,
float64(leaderSlotsPerEpoch*3/4),
testutil.ToFloat64(
watcher.LeaderSlotsByEpochMetric.WithLabelValues(nodekey, toString(initial.EpochNumber), StatusValid),
),
"Incorrect %s leader slots for %s at epoch %v",
StatusValid, nodekey, initial.EpochNumber,
)
assert.Equalf(t,
float64(leaderSlotsPerEpoch*1/4),
testutil.ToFloat64(
watcher.LeaderSlotsByEpochMetric.WithLabelValues(nodekey, toString(initial.EpochNumber), StatusSkipped),
),
"Incorrect %s leader slots for %s at epoch %v",
StatusSkipped, nodekey, initial.EpochNumber,
)
// inflation rewards:
votekey := simulator.Votekeys[i]
assert.Equalf(t,
float64(InflationRewardLamports)/rpc.LamportsInSol,
testutil.ToFloat64(
watcher.InflationRewardsMetric.WithLabelValues(votekey, toString(initial.EpochNumber)),
),
"Incorrect inflation reward for %s at epoch %v",
votekey, initial.EpochNumber,
)
// fee rewards:
assert.Equalf(t,
float64(FeeRewardLamports*leaderSlotsPerEpoch*3/4)/rpc.LamportsInSol,
testutil.ToFloat64(
watcher.FeeRewardsMetric.WithLabelValues(nodekey, toString(initial.EpochNumber)),
),
"Incorrect fee reward for %s at epoch %v",
nodekey, initial.EpochNumber,
)
}
}
// make current final the new initial (for next iteration)

View File

@ -18,8 +18,8 @@ func assertf(condition bool, format string, args ...any) {
}
}
// toString is just a simple utility function for converting int -> string
func toString(i int64) string {
// toString is just a simple utility function for converting to strings
func toString(i any) string {
return fmt.Sprintf("%v", i)
}

View File

@ -57,31 +57,28 @@ func TestCombineUnique(t *testing.T) {
}
func TestFetchBalances(t *testing.T) {
_, client := rpc.NewMockClient(t, nil, rawBalances, nil, nil, nil)
simulator, client := NewSimulator(t, 0)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fetchedBalances, err := FetchBalances(ctx, client, CombineUnique(nodekeys, votekeys))
fetchedBalances, err := FetchBalances(ctx, client, CombineUnique(simulator.Nodekeys, simulator.Votekeys))
assert.NoError(t, err)
assert.Equal(t, balances, fetchedBalances)
assert.Equal(t,
map[string]float64{"aaa": 1, "bbb": 2, "ccc": 3, "AAA": 4, "BBB": 5, "CCC": 6},
fetchedBalances,
)
}
func TestGetAssociatedVoteAccounts(t *testing.T) {
_, client := rpc.NewMockClient(t,
map[string]any{"getVoteAccounts": rawVoteAccounts},
nil,
nil,
nil,
nil,
)
simulator, client := NewSimulator(t, 1)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
voteAccounts, err := GetAssociatedVoteAccounts(ctx, client, rpc.CommitmentFinalized, nodekeys)
voteAccounts, err := GetAssociatedVoteAccounts(ctx, client, rpc.CommitmentFinalized, simulator.Nodekeys)
assert.NoError(t, err)
assert.Equal(t, votekeys, voteAccounts)
assert.Equal(t, simulator.Votekeys, voteAccounts)
}
func TestGetEpochBounds(t *testing.T) {

View File

@ -35,7 +35,7 @@ type (
inflationRewards map[string]int
easyResults map[string]any
slotInfos map[int]MockSlotInfo
SlotInfos map[int]MockSlotInfo
validatorInfos map[string]MockValidatorInfo
}
@ -76,7 +76,7 @@ func NewMockServer(
easyResults: easyResults,
balances: balances,
inflationRewards: inflationRewards,
slotInfos: slotInfos,
SlotInfos: slotInfos,
validatorInfos: validatorInfos,
}
@ -130,10 +130,10 @@ func (s *MockServer) SetOpt(opt MockOpt, key any, value any) {
}
s.easyResults[key.(string)] = value
case SlotInfosOpt:
if s.slotInfos == nil {
s.slotInfos = make(map[int]MockSlotInfo)
if s.SlotInfos == nil {
s.SlotInfos = make(map[int]MockSlotInfo)
}
s.slotInfos[key.(int)] = value.(MockSlotInfo)
s.SlotInfos[key.(int)] = value.(MockSlotInfo)
case ValidatorInfoOpt:
if s.validatorInfos == nil {
s.validatorInfos = make(map[string]MockValidatorInfo)
@ -174,13 +174,13 @@ func (s *MockServer) getResult(method string, params ...any) (any, *RPCError) {
return rewards, nil
}
if method == "getBlock" && s.slotInfos != nil {
if method == "getBlock" && s.SlotInfos != nil {
// get params:
slot := int(params[0].(float64))
config := params[1].(map[string]any)
transactionDetails, rewardsIncluded := config["transactionDetails"].(string), config["rewards"].(bool)
slotInfo, ok := s.slotInfos[slot]
slotInfo, ok := s.SlotInfos[slot]
if !ok {
s.logger.Warnf("no slot info for slot %d", slot)
return nil, &RPCError{Code: BlockCleanedUpCode, Message: "Block cleaned up."}
@ -211,7 +211,7 @@ func (s *MockServer) getResult(method string, params ...any) (any, *RPCError) {
return map[string]any{"rewards": rewards, "transactions": transactions}, nil
}
if method == "getBlockProduction" && s.slotInfos != nil {
if method == "getBlockProduction" && s.SlotInfos != nil {
// get params:
config := params[0].(map[string]any)
slotRange := config["range"].(map[string]any)
@ -222,7 +222,7 @@ func (s *MockServer) getResult(method string, params ...any) (any, *RPCError) {
byIdentity[nodekey] = []int{0, 0}
}
for i := firstSlot; i <= lastSlot; i++ {
info := s.slotInfos[i]
info := s.SlotInfos[i]
production := byIdentity[info.Leader]
production[0]++
if info.Block != nil {

View File

@ -49,6 +49,10 @@ func getEnvLogLevel() zapcore.Level {
return zapcore.WarnLevel
case "error":
return zapcore.ErrorLevel
case "panic":
return zapcore.PanicLevel
case "fatal":
return zapcore.FatalLevel
default:
fmt.Printf("Unrecognised 'LOG_LEVEL' environment variable '%s', using 'info'\n", level)
return zapcore.InfoLevel