mirror of
https://github.com/MeshCore-Beacon/beacon-server.git
synced 2026-10-22 22:21:27 +00:00
GET /traces takes an optional cursorTag so tags sharing a millisecond survive paging. Migrations run under an advisory lock and record each file in the same implicit transaction, so a crash can't strand a fresh database. Overview windowHours counts the hours it covers, hourly observer activity fills unrolled hours from raw rows, and integration fixtures are UTC.
94 lines
2.7 KiB
Go
94 lines
2.7 KiB
Go
// Copyright 2026 Beacon Contributors
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/MeshCore-Beacon/beacon-server/internal/api"
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
func TestListTraceTags_OK(t *testing.T) {
|
|
r := chi.NewRouter()
|
|
r.Get("/traces", listTraceTags(stubReader{
|
|
listTraceTags: func(_ context.Context, _ []string, _, _ string, _, _ time.Time, _ time.Time, _ string, _ int32) ([]api.TraceTagSummary, error) {
|
|
return []api.TraceTagSummary{{TraceTag: "trace-001"}}, nil
|
|
},
|
|
}))
|
|
req := httptest.NewRequest(http.MethodGet, "/traces", nil)
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("expected 200, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestListTraceTags_CursorTag(t *testing.T) {
|
|
var gotCursor time.Time
|
|
var gotTag string
|
|
r := chi.NewRouter()
|
|
r.Get("/traces", listTraceTags(stubReader{
|
|
listTraceTags: func(_ context.Context, _ []string, _, _ string, _, _ time.Time, cursor time.Time, cursorTag string, _ int32) ([]api.TraceTagSummary, error) {
|
|
gotCursor, gotTag = cursor, cursorTag
|
|
return nil, nil
|
|
},
|
|
}))
|
|
for _, tc := range []struct {
|
|
query string
|
|
code int
|
|
tag string
|
|
}{
|
|
{"cursor=1700000000000&cursorTag=A1B2C3D4", http.StatusOK, "a1b2c3d4"},
|
|
{"cursor=1700000000000", http.StatusOK, ""},
|
|
{"cursor=1700000000000&cursorTag=zz", http.StatusBadRequest, ""},
|
|
{"cursorTag=a1b2c3d4", http.StatusBadRequest, ""},
|
|
} {
|
|
gotTag = ""
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/traces?"+tc.query, nil))
|
|
if w.Code != tc.code {
|
|
t.Errorf("%s: code %d, want %d", tc.query, w.Code, tc.code)
|
|
continue
|
|
}
|
|
if tc.code == http.StatusOK && (gotTag != tc.tag || gotCursor.UnixMilli() != 1700000000000) {
|
|
t.Errorf("%s: cursor %v tag %q", tc.query, gotCursor, gotTag)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetTrace_OK(t *testing.T) {
|
|
r := chi.NewRouter()
|
|
r.Get("/traces/{tag}", getTrace(stubReader{
|
|
getTraceByTag: func(_ context.Context, tag string) (*api.TraceDetail, error) {
|
|
return &api.TraceDetail{TraceTag: tag}, nil
|
|
},
|
|
}))
|
|
req := httptest.NewRequest(http.MethodGet, "/traces/trace-001", nil)
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("expected 200, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestGetTrace_NotFound(t *testing.T) {
|
|
r := chi.NewRouter()
|
|
r.Get("/traces/{tag}", getTrace(stubReader{
|
|
getTraceByTag: func(_ context.Context, _ string) (*api.TraceDetail, error) {
|
|
return nil, nil
|
|
},
|
|
}))
|
|
req := httptest.NewRequest(http.MethodGet, "/traces/missing", nil)
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
if w.Code != http.StatusNotFound {
|
|
t.Errorf("expected 404, got %d", w.Code)
|
|
}
|
|
}
|