Files
explorer/stats_test.go
T
zeekay 48f3ebc0ab chore: sync working tree
Commits 3 outstanding change(s) that were sitting uncommitted.
No build artifacts and no secrets in the changeset (both checked).
2026-07-26 10:13:18 -07:00

148 lines
4.0 KiB
Go

package main
import (
"database/sql"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"path/filepath"
"testing"
"time"
_ "github.com/mattn/go-sqlite3"
)
// newTestStatsDB builds a minimal indexer DB mirroring the evm_* schema columns
// the stats service reads: evm_blocks(number, timestamp[unix]), evm_transactions
// (block_number), evm_addresses(hash).
func newTestStatsDB(t *testing.T) string {
t.Helper()
dir := t.TempDir()
path := filepath.Join(dir, "indexer.db")
db, err := sql.Open("sqlite3", path)
if err != nil {
t.Fatal(err)
}
defer db.Close()
_, err = db.Exec(`
CREATE TABLE evm_blocks (number INTEGER PRIMARY KEY, timestamp INTEGER, gas_used INTEGER, gas_limit INTEGER, base_fee TEXT);
CREATE TABLE evm_transactions (hash TEXT PRIMARY KEY, block_number INTEGER, gas_price TEXT);
CREATE TABLE evm_addresses (hash TEXT PRIMARY KEY);
`)
if err != nil {
t.Fatal(err)
}
// 5 blocks over the last 3 days (30s apart within a day), 3 txns, 2 addrs.
now := time.Now()
for i := 0; i < 5; i++ {
ts := now.AddDate(0, 0, -(i % 3)).Unix() + int64(i)*30
if _, err := db.Exec(`INSERT INTO evm_blocks(number,timestamp,gas_used,gas_limit,base_fee) VALUES(?,?,?,?,?)`,
i+1, ts, 21000, 12000000, "0x5"); err != nil {
t.Fatal(err)
}
}
for i := 0; i < 3; i++ {
if _, err := db.Exec(`INSERT INTO evm_transactions(hash,block_number,gas_price) VALUES(?,?,?)`,
fmt.Sprintf("0x%064d", i), i+1, "25000000000"); err != nil {
t.Fatal(err)
}
}
db.Exec(`INSERT INTO evm_addresses(hash) VALUES('0x01'),('0x02')`)
return path
}
func TestStatsCounters(t *testing.T) {
s := NewStatsService(newTestStatsDB(t))
rec := httptest.NewRecorder()
s.handleCounters(rec, httptest.NewRequest(http.MethodGet, "/v1/counters", nil))
if rec.Code != 200 {
t.Fatalf("status %d", rec.Code)
}
var out struct {
Counters []statsCounter `json:"counters"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &out); err != nil {
t.Fatal(err)
}
got := map[string]string{}
for _, c := range out.Counters {
got[c.ID] = c.Value
if c.Title == "" {
t.Errorf("counter %s has empty title", c.ID)
}
}
if got["total_blocks"] != "5" {
t.Errorf("total_blocks = %q, want 5", got["total_blocks"])
}
if got["total_txns"] != "3" {
t.Errorf("total_txns = %q, want 3", got["total_txns"])
}
if got["total_addresses"] != "2" {
t.Errorf("total_addresses = %q, want 2", got["total_addresses"])
}
}
func TestStatsLines(t *testing.T) {
s := NewStatsService(newTestStatsDB(t))
rec := httptest.NewRecorder()
s.handleLines(rec, httptest.NewRequest(http.MethodGet, "/v1/lines", nil))
var out struct {
Sections []struct {
ID string `json:"id"`
Charts []statsLineInfo `json:"charts"`
} `json:"sections"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &out); err != nil {
t.Fatal(err)
}
if len(out.Sections) == 0 {
t.Fatal("no sections advertised")
}
found := false
for _, sec := range out.Sections {
for _, c := range sec.Charts {
if c.ID == "newBlocksPerDay" || c.ID == "newTxnsPerDay" {
found = true
}
}
}
if !found {
t.Error("expected block/txn charts advertised")
}
}
func TestStatsLineData(t *testing.T) {
s := NewStatsService(newTestStatsDB(t))
for _, id := range []string{"newBlocksPerDay", "newTxnsPerDay"} {
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/v1/lines/"+id, nil)
req.SetPathValue("id", id)
s.handleLine(rec, req)
if rec.Code != 200 {
t.Fatalf("%s status %d", id, rec.Code)
}
var out statsLineChart
if err := json.Unmarshal(rec.Body.Bytes(), &out); err != nil {
t.Fatal(err)
}
if len(out.Chart) == 0 {
t.Errorf("%s returned no data points", id)
}
if out.Info.ID != id {
t.Errorf("%s info.id = %q", id, out.Info.ID)
}
}
}
func TestStatsLineUnknown(t *testing.T) {
s := NewStatsService(newTestStatsDB(t))
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/v1/lines/nope", nil)
req.SetPathValue("id", "nope")
s.handleLine(rec, req)
if rec.Code != 404 {
t.Errorf("unknown chart status = %d, want 404", rec.Code)
}
}