Skip to content

Commit 85e99de

Browse files
committed
Add tests
1 parent fad3a2a commit 85e99de

1 file changed

Lines changed: 216 additions & 0 deletions

File tree

‎shared/services/megapools_test.go‎

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
package services
2+
3+
import (
4+
"math/big"
5+
"testing"
6+
7+
"github.com/ethereum/go-ethereum/common"
8+
"github.com/rocket-pool/smartnode/bindings/rocketpool"
9+
"github.com/rocket-pool/smartnode/shared/types/api"
10+
)
11+
12+
// ---------------------------------------------------------------------------
13+
// Helpers
14+
// ---------------------------------------------------------------------------
15+
16+
// stubFinder returns a findInQueueFunc that always yields the given position.
17+
// Pass nil to simulate a validator that is not found in the queue.
18+
func stubFinder(pos *big.Int) findInQueueFunc {
19+
return func(
20+
_ *rocketpool.RocketPool,
21+
_ common.Address,
22+
_ uint32,
23+
_ string,
24+
_ *big.Int,
25+
_ *big.Int,
26+
) (*big.Int, error) {
27+
return pos, nil
28+
}
29+
}
30+
31+
// makeQueueDetails builds an api.QueueDetails from plain uint64 values.
32+
func makeQueueDetails(queueIndex, expressLen, standardLen, expressRate uint64) api.QueueDetails {
33+
return api.QueueDetails{
34+
QueueIndex: new(big.Int).SetUint64(queueIndex),
35+
ExpressQueueLength: new(big.Int).SetUint64(expressLen),
36+
StandardQueueLength: new(big.Int).SetUint64(standardLen),
37+
ExpressQueueRate: expressRate,
38+
}
39+
}
40+
41+
// estimatePosition calls calculatePositionInQueue and returns the uint64 result.
42+
// zeroBasedPos is the 0-based index returned by findInQueue (0 = head of queue).
43+
func estimatePosition(t *testing.T, qd api.QueueDetails, zeroBasedPos uint64, queueKey string) uint64 {
44+
t.Helper()
45+
result, err := calculatePositionInQueue(
46+
nil,
47+
qd,
48+
common.Address{},
49+
0,
50+
queueKey,
51+
stubFinder(new(big.Int).SetUint64(zeroBasedPos)),
52+
)
53+
if err != nil {
54+
t.Fatalf("unexpected error: %v", err)
55+
}
56+
if result == nil {
57+
t.Fatal("expected non-nil result, got nil")
58+
}
59+
return result.Uint64()
60+
}
61+
62+
// ---------------------------------------------------------------------------
63+
// Contract cycle recap (expressQueueRate = 2, queueInterval = 3):
64+
// queueIndex % 3 == 0 → express
65+
// queueIndex % 3 == 1 → express
66+
// queueIndex % 3 == 2 → standard
67+
// ---------------------------------------------------------------------------
68+
69+
// ---------------------------------------------------------------------------
70+
// Express queue
71+
// ---------------------------------------------------------------------------
72+
73+
// TestExpressQueue_FirstInEmptyQueue
74+
// pos=1, queueIndex=0, expressRemainingInCycle=2.
75+
// pos(1) <= remaining(2) → 0 standard entries before us.
76+
// overallPosition = 1 + 0 = 1.
77+
func TestExpressQueue_FirstInEmptyQueue(t *testing.T) {
78+
qd := makeQueueDetails(0, 1, 0, 2)
79+
if got := estimatePosition(t, qd, 0, "deposit.queue.express"); got != 1 {
80+
t.Errorf("want 1, got %d", got)
81+
}
82+
}
83+
84+
// TestExpressQueue_SpansIntoNextCycle
85+
// pos=3, queueIndex=0, expressRemainingInCycle=2.
86+
// pos(3) > remaining(2) → standardEntriesBefore = ceil((3-2)/2) = 1.
87+
// overallPosition = 3 + 1 = 4.
88+
func TestExpressQueue_SpansIntoNextCycle(t *testing.T) {
89+
qd := makeQueueDetails(0, 10, 5, 2)
90+
if got := estimatePosition(t, qd, 2, "deposit.queue.express"); got != 4 {
91+
t.Errorf("want 4, got %d", got)
92+
}
93+
}
94+
95+
// TestExpressQueue_MidCycle_NoSpill
96+
// pos=1, queueIndex=1, expressUsedInCycle=1, expressRemainingInCycle=1.
97+
// pos(1) <= remaining(1) → 0 standard entries before us.
98+
// overallPosition = 1 + 0 = 1.
99+
func TestExpressQueue_MidCycle_NoSpill(t *testing.T) {
100+
qd := makeQueueDetails(1, 5, 5, 2)
101+
if got := estimatePosition(t, qd, 0, "deposit.queue.express"); got != 1 {
102+
t.Errorf("want 1, got %d", got)
103+
}
104+
}
105+
106+
// TestExpressQueue_MidCycle_Spills
107+
// pos=2, queueIndex=1, expressRemainingInCycle=1.
108+
// pos(2) > remaining(1) → standardEntriesBefore = ceil((2-1)/2) = 1.
109+
// overallPosition = 2 + 1 = 3.
110+
func TestExpressQueue_MidCycle_Spills(t *testing.T) {
111+
qd := makeQueueDetails(1, 10, 5, 2)
112+
if got := estimatePosition(t, qd, 1, "deposit.queue.express"); got != 3 {
113+
t.Errorf("want 3, got %d", got)
114+
}
115+
}
116+
117+
// TestExpressQueue_StandardQueueCapped
118+
// pos=10, queueIndex=0, uncapped standardEntriesBefore = ceil((10-2)/2) = 4,
119+
// but standardQueueLength=1 → cap to 1.
120+
// overallPosition = 10 + 1 = 11.
121+
func TestExpressQueue_StandardQueueCapped(t *testing.T) {
122+
qd := makeQueueDetails(0, 20, 1, 2)
123+
if got := estimatePosition(t, qd, 9, "deposit.queue.express"); got != 11 {
124+
t.Errorf("want 11, got %d", got)
125+
}
126+
}
127+
128+
// ---------------------------------------------------------------------------
129+
// Standard queue
130+
// ---------------------------------------------------------------------------
131+
132+
// TestStandardQueue_FirstEntry_StartOfCycle
133+
// pos=1, queueIndex=0, expressRemainingInCycle=2.
134+
// expressEntriesBefore = (1-1)*2 + 2 = 2.
135+
// overallPosition = 1 + 2 = 3.
136+
func TestStandardQueue_FirstEntry_StartOfCycle(t *testing.T) {
137+
qd := makeQueueDetails(0, 10, 5, 2)
138+
if got := estimatePosition(t, qd, 0, "deposit.queue.standard"); got != 3 {
139+
t.Errorf("want 3, got %d", got)
140+
}
141+
}
142+
143+
// TestStandardQueue_SecondEntry_StartOfCycle
144+
// pos=2, queueIndex=0.
145+
// expressEntriesBefore = (2-1)*2 + 2 = 4.
146+
// overallPosition = 2 + 4 = 6.
147+
func TestStandardQueue_SecondEntry_StartOfCycle(t *testing.T) {
148+
qd := makeQueueDetails(0, 10, 5, 2)
149+
if got := estimatePosition(t, qd, 1, "deposit.queue.standard"); got != 6 {
150+
t.Errorf("want 6, got %d", got)
151+
}
152+
}
153+
154+
// TestStandardQueue_MidCycle
155+
// pos=1, queueIndex=1, expressUsedInCycle=1, expressRemainingInCycle=1.
156+
// expressEntriesBefore = 0*2 + 1 = 1.
157+
// overallPosition = 1 + 1 = 2.
158+
func TestStandardQueue_MidCycle(t *testing.T) {
159+
qd := makeQueueDetails(1, 10, 5, 2)
160+
if got := estimatePosition(t, qd, 0, "deposit.queue.standard"); got != 2 {
161+
t.Errorf("want 2, got %d", got)
162+
}
163+
}
164+
165+
// TestStandardQueue_JustAfterStandardSlot
166+
// queueIndex=3 wraps back to slot 0 of the next cycle (3%3=0).
167+
// Same as start-of-cycle: expressRemainingInCycle=2.
168+
// pos=1: expressEntriesBefore = 0 + 2 = 2.
169+
// overallPosition = 1 + 2 = 3.
170+
func TestStandardQueue_JustAfterStandardSlot(t *testing.T) {
171+
qd := makeQueueDetails(3, 10, 5, 2)
172+
if got := estimatePosition(t, qd, 0, "deposit.queue.standard"); got != 3 {
173+
t.Errorf("want 3, got %d", got)
174+
}
175+
}
176+
177+
// TestStandardQueue_ExpressQueueCapped
178+
// pos=5, queueIndex=0, uncapped expressEntriesBefore = (5-1)*2 + 2 = 10,
179+
// but expressQueueLength=3 → cap to 3.
180+
// overallPosition = 5 + 3 = 8.
181+
func TestStandardQueue_ExpressQueueCapped(t *testing.T) {
182+
qd := makeQueueDetails(0, 3, 10, 2)
183+
if got := estimatePosition(t, qd, 4, "deposit.queue.standard"); got != 8 {
184+
t.Errorf("want 8, got %d", got)
185+
}
186+
}
187+
188+
// ---------------------------------------------------------------------------
189+
// Edge cases
190+
// ---------------------------------------------------------------------------
191+
192+
// TestNotInQueue — findInQueue returns nil → result must be nil, no error.
193+
func TestNotInQueue(t *testing.T) {
194+
qd := makeQueueDetails(0, 5, 5, 2)
195+
result, err := calculatePositionInQueue(
196+
nil, qd, common.Address{}, 99, "deposit.queue.express", stubFinder(nil),
197+
)
198+
if err != nil {
199+
t.Fatalf("unexpected error: %v", err)
200+
}
201+
if result != nil {
202+
t.Errorf("expected nil result for validator not in queue, got %v", result)
203+
}
204+
}
205+
206+
// TestHighExpressQueueRate — sanity check with expressQueueRate=4 (cycle of 5).
207+
// Standard queue, pos=1, queueIndex=0.
208+
// expressRemainingInCycle = 4.
209+
// expressEntriesBefore = 0*4 + 4 = 4.
210+
// overallPosition = 1 + 4 = 5.
211+
func TestHighExpressQueueRate(t *testing.T) {
212+
qd := makeQueueDetails(0, 10, 5, 4)
213+
if got := estimatePosition(t, qd, 0, "deposit.queue.standard"); got != 5 {
214+
t.Errorf("want 5, got %d", got)
215+
}
216+
}

0 commit comments

Comments
 (0)