Files

162 lines
4.9 KiB
Go

package store
import (
"context"
"os"
"path/filepath"
"testing"
"time"
"speedtest/internal/probe"
)
func TestStoreAppendsAndListsRecordsNewestFirst(t *testing.T) {
path := filepath.Join(t.TempDir(), "records.jsonl")
store := New(path)
ctx := context.Background()
first := Record{
ID: "run-1",
Client: ClientInfo{IP: "198.51.100.10", ISP: "Example Telecom", Region: "Shanghai"},
CreatedAt: time.Date(2026, 6, 5, 8, 0, 0, 0, time.UTC),
Samples: []probe.Sample{{At: time.Date(2026, 6, 5, 8, 0, 0, 0, time.UTC), Kind: "tcp", Success: true, LatencyMS: 30}},
Summary: probe.Summary{
ID: "run-1",
Target: "example.com:80",
StartedAt: time.Date(2026, 6, 5, 8, 0, 0, 0, time.UTC),
FinishedAt: time.Date(2026, 6, 5, 8, 0, 5, 0, time.UTC),
Samples: 1,
Score: 95,
},
}
second := Record{
ID: "run-2",
Client: ClientInfo{IP: "203.0.113.20", ISP: "Example Mobile", Region: "Beijing"},
CreatedAt: time.Date(2026, 6, 5, 8, 1, 0, 0, time.UTC),
Samples: []probe.Sample{{At: time.Date(2026, 6, 5, 8, 1, 0, 0, time.UTC), Kind: "http", Success: true, LatencyMS: 45}},
Summary: probe.Summary{
ID: "run-2",
Target: "103.46.93.38:443",
StartedAt: time.Date(2026, 6, 5, 8, 1, 0, 0, time.UTC),
FinishedAt: time.Date(2026, 6, 5, 8, 1, 5, 0, time.UTC),
Samples: 1,
Score: 88,
},
}
if err := store.Append(ctx, first); err != nil {
t.Fatalf("Append first: %v", err)
}
if err := store.Append(ctx, second); err != nil {
t.Fatalf("Append second: %v", err)
}
records, err := store.List(ctx, 10)
if err != nil {
t.Fatalf("List returned error: %v", err)
}
if len(records) != 2 {
t.Fatalf("len(records) = %d, want 2", len(records))
}
if records[0].ID != "run-2" || records[1].ID != "run-1" {
t.Fatalf("records order = %s, %s; want run-2, run-1", records[0].ID, records[1].ID)
}
if records[0].Client.IP != "203.0.113.20" || records[0].Client.ISP != "Example Mobile" {
t.Fatalf("client info = %#v, want persisted IP and ISP", records[0].Client)
}
if len(records[0].Samples) != 1 || records[0].Samples[0].LatencyMS != 45 {
t.Fatalf("samples = %#v, want persisted curve samples", records[0].Samples)
}
}
func TestStoreListHonorsLimit(t *testing.T) {
path := filepath.Join(t.TempDir(), "records.jsonl")
store := New(path)
ctx := context.Background()
for _, id := range []string{"run-1", "run-2", "run-3"} {
if err := store.Append(ctx, Record{ID: id, Summary: probe.Summary{ID: id, Target: "example.com:80"}}); err != nil {
t.Fatalf("Append %s: %v", id, err)
}
}
records, err := store.List(ctx, 2)
if err != nil {
t.Fatalf("List returned error: %v", err)
}
if len(records) != 2 {
t.Fatalf("len(records) = %d, want 2", len(records))
}
if records[0].ID != "run-3" || records[1].ID != "run-2" {
t.Fatalf("records order = %s, %s; want run-3, run-2", records[0].ID, records[1].ID)
}
}
func TestStoreListIgnoresBlankLinesAndMissingFile(t *testing.T) {
path := filepath.Join(t.TempDir(), "records.jsonl")
store := New(path)
ctx := context.Background()
records, err := store.List(ctx, 10)
if err != nil {
t.Fatalf("List missing file returned error: %v", err)
}
if len(records) != 0 {
t.Fatalf("len(records) = %d, want 0", len(records))
}
content := []byte("\n{\"id\":\"run-1\",\"summary\":{\"id\":\"run-1\",\"target\":\"example.com:80\"}}\n\n{\"id\":\"run-2\",\"summary\":{\"id\":\"run-2\",\"target\":\"example.org:443\"}}\n")
if err := os.WriteFile(path, content, 0644); err != nil {
t.Fatalf("WriteFile: %v", err)
}
records, err = store.List(ctx, 10)
if err != nil {
t.Fatalf("List returned error: %v", err)
}
if len(records) != 2 {
t.Fatalf("len(records) = %d, want 2", len(records))
}
if records[0].ID != "run-2" || records[1].ID != "run-1" {
t.Fatalf("records order = %s, %s; want run-2, run-1", records[0].ID, records[1].ID)
}
}
func TestStoreListsLargeRecordsWithFullSampleCurves(t *testing.T) {
path := filepath.Join(t.TempDir(), "records.jsonl")
store := New(path)
ctx := context.Background()
var samples []probe.Sample
for i := 0; i < 2000; i++ {
samples = append(samples, probe.Sample{
At: time.Date(2026, 6, 10, 8, 0, 0, 0, time.UTC).Add(time.Duration(i) * time.Millisecond),
Kind: "download",
Success: true,
LatencyMS: 10.5,
Bytes: 4 * 1024 * 1024,
Mbps: 38.25,
})
}
if err := store.Append(ctx, Record{
ID: "large-run",
Samples: samples,
Summary: probe.Summary{
ID: "large-run",
Target: "example.com:443",
Samples: len(samples),
},
}); err != nil {
t.Fatalf("Append large record: %v", err)
}
records, err := store.List(ctx, 10)
if err != nil {
t.Fatalf("List returned error: %v", err)
}
if len(records) != 1 || records[0].ID != "large-run" || len(records[0].Samples) != len(samples) {
t.Fatalf("records = %#v, want large record with %d samples", records, len(samples))
}
}