Files
explorer-monorepo/backend/api/freshness/freshness_test.go

193 lines
5.5 KiB
Go

package freshness
import (
"context"
"testing"
"time"
"github.com/jackc/pgx/v5"
"github.com/stretchr/testify/require"
)
type fakeRow struct {
scan func(dest ...any) error
}
func (r fakeRow) Scan(dest ...any) error {
return r.scan(dest...)
}
func TestBuildSnapshotHealthyState(t *testing.T) {
now := time.Date(2026, 4, 10, 22, 10, 16, 0, time.UTC)
call := 0
queryRow := func(_ context.Context, _ string, _ ...any) pgx.Row {
call++
switch call {
case 1:
return fakeRow{scan: func(dest ...any) error {
*dest[0].(*int64) = 200
*dest[1].(*time.Time) = now.Add(-2 * time.Second)
return nil
}}
case 2:
return fakeRow{scan: func(dest ...any) error {
*dest[0].(*string) = "0xabc"
*dest[1].(*int64) = 198
*dest[2].(*time.Time) = now.Add(-5 * time.Second)
return nil
}}
case 3:
return fakeRow{scan: func(dest ...any) error {
*dest[0].(*int64) = 198
*dest[1].(*time.Time) = now.Add(-5 * time.Second)
return nil
}}
default:
t.Fatalf("unexpected call %d", call)
return nil
}
}
probe := func(context.Context) (*Reference, error) {
ts := now.Add(-1 * time.Second).Format(time.RFC3339)
age := int64(1)
block := int64(200)
return &Reference{
BlockNumber: &block,
Timestamp: &ts,
AgeSeconds: &age,
Source: SourceReported,
Confidence: ConfidenceHigh,
Provenance: ProvenanceRPC,
Completeness: CompletenessComplete,
}, nil
}
snapshot, completeness, sampling, err := BuildSnapshot(context.Background(), 138, queryRow, probe, now, nil, nil)
require.NoError(t, err)
require.Equal(t, int64(200), *snapshot.ChainHead.BlockNumber)
require.Equal(t, int64(198), *snapshot.LatestIndexedTransaction.BlockNumber)
require.Equal(t, int64(2), *snapshot.LatestNonEmptyBlock.DistanceFromHead)
require.Equal(t, CompletenessComplete, completeness.TransactionsFeed)
require.NotNil(t, sampling.StatsGeneratedAt)
}
func TestBuildSnapshotFreshHeadStaleTransactionVisibility(t *testing.T) {
now := time.Date(2026, 4, 11, 0, 10, 16, 0, time.UTC)
call := 0
queryRow := func(_ context.Context, _ string, _ ...any) pgx.Row {
call++
switch call {
case 1:
return fakeRow{scan: func(dest ...any) error {
*dest[0].(*int64) = 3875999
*dest[1].(*time.Time) = now.Add(-3 * time.Second)
return nil
}}
case 2:
return fakeRow{scan: func(dest ...any) error {
*dest[0].(*string) = "0xstale"
*dest[1].(*int64) = 3860660
*dest[2].(*time.Time) = now.Add(-(9*time.Hour + 8*time.Minute))
return nil
}}
case 3:
return fakeRow{scan: func(dest ...any) error {
*dest[0].(*int64) = 3860660
*dest[1].(*time.Time) = now.Add(-(9*time.Hour + 8*time.Minute))
return nil
}}
default:
t.Fatalf("unexpected call %d", call)
return nil
}
}
probe := func(context.Context) (*Reference, error) {
ts := now.Add(-1 * time.Second).Format(time.RFC3339)
age := int64(1)
block := int64(3876000)
return &Reference{
BlockNumber: &block,
Timestamp: &ts,
AgeSeconds: &age,
Source: SourceReported,
Confidence: ConfidenceHigh,
Provenance: ProvenanceRPC,
Completeness: CompletenessComplete,
}, nil
}
snapshot, completeness, _, err := BuildSnapshot(context.Background(), 138, queryRow, probe, now, nil, nil)
require.NoError(t, err)
require.Equal(t, int64(15340), *snapshot.LatestNonEmptyBlock.DistanceFromHead)
require.Equal(t, CompletenessStale, completeness.TransactionsFeed)
require.Equal(t, CompletenessComplete, completeness.BlocksFeed)
}
func TestBuildSnapshotQuietChainButCurrent(t *testing.T) {
now := time.Date(2026, 4, 10, 23, 10, 16, 0, time.UTC)
call := 0
queryRow := func(_ context.Context, _ string, _ ...any) pgx.Row {
call++
switch call {
case 1:
return fakeRow{scan: func(dest ...any) error {
*dest[0].(*int64) = 3875000
*dest[1].(*time.Time) = now.Add(-1 * time.Second)
return nil
}}
case 2:
return fakeRow{scan: func(dest ...any) error {
*dest[0].(*string) = "0xquiet"
*dest[1].(*int64) = 3874902
*dest[2].(*time.Time) = now.Add(-512 * time.Second)
return nil
}}
case 3:
return fakeRow{scan: func(dest ...any) error {
*dest[0].(*int64) = 3874902
*dest[1].(*time.Time) = now.Add(-512 * time.Second)
return nil
}}
default:
t.Fatalf("unexpected call %d", call)
return nil
}
}
probe := func(context.Context) (*Reference, error) {
ts := now.Add(-1 * time.Second).Format(time.RFC3339)
age := int64(1)
block := int64(3875000)
return &Reference{
BlockNumber: &block,
Timestamp: &ts,
AgeSeconds: &age,
Source: SourceReported,
Confidence: ConfidenceHigh,
Provenance: ProvenanceRPC,
Completeness: CompletenessComplete,
}, nil
}
snapshot, completeness, _, err := BuildSnapshot(context.Background(), 138, queryRow, probe, now, nil, nil)
require.NoError(t, err)
require.Equal(t, int64(98), *snapshot.LatestNonEmptyBlock.DistanceFromHead)
require.Equal(t, CompletenessComplete, completeness.TransactionsFeed)
}
func TestBuildSnapshotUnknownFieldsRemainNullSafe(t *testing.T) {
queryRow := func(_ context.Context, _ string, _ ...any) pgx.Row {
return fakeRow{scan: func(dest ...any) error {
return pgx.ErrNoRows
}}
}
snapshot, completeness, sampling, err := BuildSnapshot(context.Background(), 138, queryRow, nil, time.Now().UTC(), nil, nil)
require.NoError(t, err)
require.Nil(t, snapshot.ChainHead.BlockNumber)
require.Equal(t, CompletenessUnavailable, completeness.TransactionsFeed)
require.NotNil(t, sampling.StatsGeneratedAt)
}