162 lines
4.9 KiB
Go
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))
|
|
}
|
|
}
|