Skip to content

Commit 4a229d2

Browse files
committed
test: add blobindexer tests for calculateStartSlot, calculateEstimatedTimeToHeadDuration, calculateEstimatedTimeToHead, calculateBlobsPerSecond, calculateSlotsPerSecond & getLastIndexedFinalizedSlot func
1 parent e39e2b5 commit 4a229d2

File tree

1 file changed

+299
-0
lines changed

1 file changed

+299
-0
lines changed

backend/pkg/blobindexer/blobindexer_test.go

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package blobindexer
22

33
import (
4+
"math"
45
"testing"
56
"time"
67

78
"github.com/ethereum/go-ethereum/common/hexutil"
89
"github.com/gobitfly/beaconchain/pkg/commons/types"
910
"github.com/gobitfly/beaconchain/pkg/commons/utils"
1011
constypes "github.com/gobitfly/beaconchain/pkg/consapi/types"
12+
"go.uber.org/atomic"
1113
)
1214

1315
func TestShouldSkipBlobIndexing(t *testing.T) {
@@ -210,6 +212,303 @@ func TestCalculateMinBlobSlot(t *testing.T) {
210212
}
211213
}
212214

215+
func TestCalculateStartSlot(t *testing.T) {
216+
tests := []struct {
217+
name string
218+
status *BlobIndexerStatus
219+
spec *constypes.StandardSpecResponse
220+
expectedStartSlot uint64
221+
expectedDenebSlot uint64
222+
}{
223+
{
224+
name: "last indexed slot before deneb fork",
225+
status: &BlobIndexerStatus{
226+
LastIndexedFinalizedSlot: 100,
227+
},
228+
spec: &constypes.StandardSpecResponse{
229+
Data: constypes.StandardSpec{
230+
DenebForkEpoch: uint64Ptr(4),
231+
SlotsPerEpoch: 32,
232+
},
233+
},
234+
expectedStartSlot: 128,
235+
expectedDenebSlot: 128,
236+
},
237+
{
238+
name: "last indexed slot after deneb fork",
239+
status: &BlobIndexerStatus{
240+
LastIndexedFinalizedSlot: 150,
241+
},
242+
spec: &constypes.StandardSpecResponse{
243+
Data: constypes.StandardSpec{
244+
DenebForkEpoch: uint64Ptr(4),
245+
SlotsPerEpoch: 32,
246+
},
247+
},
248+
expectedStartSlot: 151,
249+
expectedDenebSlot: 128,
250+
},
251+
}
252+
253+
for _, tt := range tests {
254+
t.Run(tt.name, func(t *testing.T) {
255+
startSlot, denebSlot := calculateStartSlot(tt.status, tt.spec)
256+
if startSlot != tt.expectedStartSlot {
257+
t.Errorf("got startSlot %v, want %v", startSlot, tt.expectedStartSlot)
258+
}
259+
if denebSlot != tt.expectedDenebSlot {
260+
t.Errorf("got denebSlot %v, want %v", denebSlot, tt.expectedDenebSlot)
261+
}
262+
})
263+
}
264+
}
265+
266+
func TestCalculateEstimatedTimeToHeadDuration(t *testing.T) {
267+
tests := []struct {
268+
name string
269+
estimatedTimeToHead float64
270+
expectedDuration time.Duration
271+
}{
272+
{
273+
name: "120 seconds",
274+
estimatedTimeToHead: 120.0,
275+
expectedDuration: 120 * time.Second,
276+
},
277+
{
278+
name: "0 seconds",
279+
estimatedTimeToHead: 0.0,
280+
expectedDuration: 0 * time.Second,
281+
},
282+
{
283+
name: "invalid input",
284+
estimatedTimeToHead: -50.0,
285+
expectedDuration: -50 * time.Second,
286+
},
287+
}
288+
289+
for _, tt := range tests {
290+
t.Run(tt.name, func(t *testing.T) {
291+
duration := calculateEstimatedTimeToHeadDuration(tt.estimatedTimeToHead)
292+
if duration != tt.expectedDuration {
293+
t.Errorf("got duration %v, want %v", duration, tt.expectedDuration)
294+
}
295+
})
296+
}
297+
}
298+
299+
func TestCalculateEstimatedTimeToHead(t *testing.T) {
300+
tests := []struct {
301+
name string
302+
headHeader *constypes.StandardBeaconHeaderResponse
303+
batchStart uint64
304+
slotsPerSecond float64
305+
expectedTimeToHead float64
306+
}{
307+
{
308+
name: "head slot is grater than batch start",
309+
headHeader: &constypes.StandardBeaconHeaderResponse{
310+
Data: constypes.BeaconHeaderData{
311+
Root: hexutil.Bytes{},
312+
Header: constypes.BeaconHeaderMessage{
313+
Message: constypes.BeaconHeaderMessageData{
314+
Slot: 200,
315+
ProposerIndex: 0,
316+
ParentRoot: hexutil.Bytes{},
317+
StateRoot: hexutil.Bytes{},
318+
BodyRoot: hexutil.Bytes{},
319+
},
320+
Signature: hexutil.Bytes{},
321+
},
322+
},
323+
},
324+
batchStart: 100,
325+
slotsPerSecond: 2.0,
326+
expectedTimeToHead: 50.0,
327+
},
328+
{
329+
name: "head slot equals batch start",
330+
headHeader: &constypes.StandardBeaconHeaderResponse{
331+
Data: constypes.BeaconHeaderData{
332+
Root: hexutil.Bytes{},
333+
Header: constypes.BeaconHeaderMessage{
334+
Message: constypes.BeaconHeaderMessageData{
335+
Slot: 100,
336+
ProposerIndex: 0,
337+
ParentRoot: hexutil.Bytes{},
338+
StateRoot: hexutil.Bytes{},
339+
BodyRoot: hexutil.Bytes{},
340+
},
341+
Signature: hexutil.Bytes{},
342+
},
343+
},
344+
},
345+
batchStart: 100,
346+
slotsPerSecond: 2.0,
347+
expectedTimeToHead: 0.0,
348+
},
349+
{
350+
name: "batch start is grater head slot",
351+
headHeader: &constypes.StandardBeaconHeaderResponse{
352+
Data: constypes.BeaconHeaderData{
353+
Root: hexutil.Bytes{},
354+
Header: constypes.BeaconHeaderMessage{
355+
Message: constypes.BeaconHeaderMessageData{
356+
Slot: 50,
357+
ProposerIndex: 0,
358+
ParentRoot: hexutil.Bytes{},
359+
StateRoot: hexutil.Bytes{},
360+
BodyRoot: hexutil.Bytes{},
361+
},
362+
Signature: hexutil.Bytes{},
363+
},
364+
},
365+
},
366+
batchStart: 100,
367+
slotsPerSecond: 2.0,
368+
expectedTimeToHead: -25.0,
369+
},
370+
}
371+
372+
for _, tt := range tests {
373+
t.Run(tt.name, func(t *testing.T) {
374+
estimatedTimeToHead := calculateEstimatedTimeToHead(tt.headHeader, tt.batchStart, tt.slotsPerSecond)
375+
if estimatedTimeToHead != tt.expectedTimeToHead {
376+
t.Errorf("got estimatedTimeToHead %v, want %v", estimatedTimeToHead, tt.expectedTimeToHead)
377+
}
378+
})
379+
}
380+
}
381+
382+
func TestCalculateBlobsPerSecond(t *testing.T) {
383+
tests := []struct {
384+
name string
385+
batchBlobsIndexed int64
386+
batchStartTs time.Time
387+
expectedBlobsPerSec float64
388+
}{
389+
{
390+
name: "100 blobs indexed in 10 seconds",
391+
batchBlobsIndexed: 100,
392+
batchStartTs: time.Now().Add(-10 * time.Second),
393+
expectedBlobsPerSec: 10.0,
394+
},
395+
{
396+
name: "0 blobs indexed",
397+
batchBlobsIndexed: 0,
398+
batchStartTs: time.Now().Add(-10 * time.Second),
399+
expectedBlobsPerSec: 0.0,
400+
},
401+
{
402+
name: "invalid input",
403+
batchBlobsIndexed: 100,
404+
batchStartTs: time.Now().Add(10 * time.Second),
405+
expectedBlobsPerSec: -10.0,
406+
},
407+
}
408+
409+
for _, tt := range tests {
410+
t.Run(tt.name, func(t *testing.T) {
411+
batchBlobsIndexed := atomic.Int64{}
412+
batchBlobsIndexed.Store(tt.batchBlobsIndexed)
413+
414+
blobsPerSecond := calculateBlobsPerSecond(&batchBlobsIndexed, tt.batchStartTs)
415+
if math.Round(blobsPerSecond) != tt.expectedBlobsPerSec {
416+
t.Errorf("got blobsPerSecond %v, want %v", blobsPerSecond, tt.expectedBlobsPerSec)
417+
}
418+
})
419+
}
420+
}
421+
422+
func TestCalculateSlotsPerSecond(t *testing.T) {
423+
tests := []struct {
424+
name string
425+
batchEnd uint64
426+
batchStart uint64
427+
batchStartTs time.Time
428+
expectedSlotsPerSec float64
429+
}{
430+
{
431+
name: "100 slots in 10 seconds",
432+
batchEnd: 200,
433+
batchStart: 100,
434+
batchStartTs: time.Now().Add(-10 * time.Second),
435+
expectedSlotsPerSec: 10.0,
436+
},
437+
{
438+
name: "0 slots processed",
439+
batchEnd: 100,
440+
batchStart: 100,
441+
batchStartTs: time.Now().Add(-10 * time.Second),
442+
expectedSlotsPerSec: 0.0,
443+
},
444+
{
445+
name: "invalid input",
446+
batchEnd: 200,
447+
batchStart: 100,
448+
batchStartTs: time.Now().Add(10 * time.Second),
449+
expectedSlotsPerSec: -10.0,
450+
},
451+
}
452+
453+
for _, tt := range tests {
454+
t.Run(tt.name, func(t *testing.T) {
455+
slotsPerSecond := calculateSlotsPerSecond(tt.batchEnd, tt.batchStart, tt.batchStartTs)
456+
if math.Round(slotsPerSecond) != tt.expectedSlotsPerSec {
457+
t.Errorf("got slotsPerSecond %v, want %v", slotsPerSecond, tt.expectedSlotsPerSec)
458+
}
459+
})
460+
}
461+
}
462+
463+
func TestGetLastIndexedFinalizedSlot(t *testing.T) {
464+
finalizedHeader := &constypes.StandardBeaconHeaderResponse{
465+
Data: constypes.BeaconHeaderData{
466+
Header: constypes.BeaconHeaderMessage{
467+
Message: constypes.BeaconHeaderMessageData{
468+
Slot: 150,
469+
},
470+
},
471+
},
472+
}
473+
474+
tests := []struct {
475+
name string
476+
batchEnd uint64
477+
expectedLastIndexedSlot uint64
478+
}{
479+
480+
{
481+
name: "batchEnd before finalized slot",
482+
batchEnd: 100,
483+
expectedLastIndexedSlot: 100,
484+
},
485+
{
486+
name: "batchEnd equal to finalized slot",
487+
batchEnd: 150,
488+
expectedLastIndexedSlot: 150,
489+
},
490+
{
491+
name: "batchEnd after finalized slot",
492+
batchEnd: 200,
493+
expectedLastIndexedSlot: 150,
494+
},
495+
{
496+
name: "batchEnd is 0",
497+
batchEnd: 0,
498+
expectedLastIndexedSlot: 0,
499+
},
500+
}
501+
502+
for _, tt := range tests {
503+
t.Run(tt.name, func(t *testing.T) {
504+
lastIndexedSlot := getLastIndexedFinalizedSlot(tt.batchEnd, finalizedHeader)
505+
if lastIndexedSlot != tt.expectedLastIndexedSlot {
506+
t.Errorf("got lastIndexedSlot %v, want %v", lastIndexedSlot, tt.expectedLastIndexedSlot)
507+
}
508+
})
509+
}
510+
}
511+
213512
// unit64Ptr returns a pointer to a uint64
214513
func uint64Ptr(i uint64) *uint64 {
215514
return &i

0 commit comments

Comments
 (0)