Files
DenozordecandCursor f8e0520817 feat(httpapi): harden control plane and speed up prefix refresh
Очередь job получила lease и fencing, телеметрия и прогресс deploy сохраняются, ревизия пишет manifest входов. Обновление префиксов не переписывает неизменённый снимок, большие наборы идут через COPY, а устаревшая ревизия не попадает в deploy. Бандл ноды кэшируется, prune и постановка job больше не держат горячий путь.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-02 17:23:59 +07:00

96 lines
3.0 KiB
Go

package importer
import (
"context"
"errors"
"strings"
"testing"
"evobgp/internal/store"
)
type importBackend struct {
store.Backend
created int
onCreate func()
}
func (s *importBackend) GetModule(string, string) (*store.Module, error) {
return &store.Module{Type: "AS_PREFIXES"}, nil
}
func (s *importBackend) ListCommunities(string) ([]*store.Community, error) { return nil, nil }
func (s *importBackend) CreateASEntry(_, _ string, e *store.ASEntry) (*store.ASEntry, error) {
s.created++
if s.onCreate != nil {
s.onCreate()
}
return e, nil
}
func TestCSVByteLimitRejectsValidTruncatedPrefix(t *testing.T) {
header := "asn,community\n"
for _, extra := range []int{0, 1} {
s := &importBackend{}
body := header + strings.Repeat("\n", MaxCSVBytes-len(header)) + strings.Repeat("\n", extra)
_, err := ImportModuleEntriesCSV(context.Background(), s, "tenant", "module", strings.NewReader(body))
if extra == 0 && err != nil {
t.Fatalf("exact limit: %v", err)
}
if extra == 1 && !errors.Is(err, ErrCSVTooLarge) {
t.Fatalf("limit+1: %v", err)
}
if s.created != 0 {
t.Fatal("oversized import created entries")
}
}
}
func TestCSVRowLimitCheckedBeforeWrites(t *testing.T) {
for _, header := range []string{"", "asn,community\n"} {
for _, extra := range []int{0, 1} {
s := &importBackend{}
_, err := ImportModuleEntriesCSV(context.Background(), s, "tenant", "module", strings.NewReader(header+strings.Repeat("64512,\n", MaxCSVRows+extra)))
if extra == 0 && (err != nil || s.created != MaxCSVRows) {
t.Fatalf("exact rows: created=%d err=%v", s.created, err)
}
if extra == 1 && (!errors.Is(err, ErrCSVTooLarge) || s.created != 0) {
t.Fatalf("rows+1: created=%d err=%v", s.created, err)
}
}
}
}
func TestCSVCancellationStopsFurtherWrites(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
s := &importBackend{onCreate: cancel}
_, err := ImportModuleEntriesCSV(ctx, s, "tenant", "module", strings.NewReader("asn,community\n64512,\n64513,\n"))
if !errors.Is(err, context.Canceled) || s.created != 1 {
t.Fatalf("created=%d err=%v", s.created, err)
}
}
func TestCSVFieldLimitAndQuotedFields(t *testing.T) {
for _, tc := range []struct {
name, input string
oversized bool
}{
{"exact", "64512," + strings.Repeat(",", MaxCSVFields-2) + "\n", false},
{"over", "64512," + strings.Repeat(",", MaxCSVFields-1) + "\n", true},
{"many_fields", strings.Repeat(",", 1<<20) + "\n", true},
{"quoted_extra", "64512,,\"" + strings.Repeat(",", 128) + "\nquoted \"\"text\"\"\"\n", false},
} {
t.Run(tc.name, func(t *testing.T) {
s := &importBackend{}
_, err := ImportModuleEntriesCSV(context.Background(), s, "tenant", "module", strings.NewReader(tc.input))
if tc.oversized {
if !errors.Is(err, ErrCSVTooLarge) || s.created != 0 {
t.Fatalf("created=%d err=%v", s.created, err)
}
} else if err != nil || s.created != 1 {
t.Fatalf("created=%d err=%v", s.created, err)
}
})
}
}