104 lines
3.4 KiB
Go
104 lines
3.4 KiB
Go
package db
|
|
|
|
import (
|
|
"errors"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"cloudipvalidator/internal/config"
|
|
)
|
|
|
|
func TestBootstrapInboundChecksSeedsOnceFromConfig(t *testing.T) {
|
|
d, ctx := newTestDB(t)
|
|
|
|
cfg := &config.ControlAPI{Inbound: config.InboundConfig{Ports: []int{22, 80}, ICMP: true}}
|
|
if err := d.BootstrapFromConfig(ctx, cfg); err != nil {
|
|
t.Fatalf("first bootstrap: %v", err)
|
|
}
|
|
settings, err := d.GetInboundChecks(ctx)
|
|
if err != nil {
|
|
t.Fatalf("get inbound checks: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(settings.Ports, []int{22, 80}) || !settings.ICMP {
|
|
t.Fatalf("expected seeded {[22 80] true}, got %+v", settings)
|
|
}
|
|
|
|
// A second bootstrap with a different YAML value must not overwrite the
|
|
// now-non-empty table — same "DB is source of truth once seeded"
|
|
// semantics as validators/sites/targets/check_types/settings.
|
|
cfg2 := &config.ControlAPI{Inbound: config.InboundConfig{Ports: []int{443}, ICMP: false}}
|
|
if err := d.BootstrapFromConfig(ctx, cfg2); err != nil {
|
|
t.Fatalf("second bootstrap: %v", err)
|
|
}
|
|
settings, err = d.GetInboundChecks(ctx)
|
|
if err != nil {
|
|
t.Fatalf("get inbound checks after second bootstrap: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(settings.Ports, []int{22, 80}) || !settings.ICMP {
|
|
t.Fatalf("expected YAML to be ignored on non-empty table, got %+v", settings)
|
|
}
|
|
}
|
|
|
|
func TestSetInboundChecksRejectsPortOutOfRange(t *testing.T) {
|
|
d, ctx := newTestDB(t)
|
|
if err := d.BootstrapFromConfig(ctx, &config.ControlAPI{}); err != nil {
|
|
t.Fatalf("bootstrap: %v", err)
|
|
}
|
|
for _, p := range []int{0, -1, 65536, 70000} {
|
|
if err := d.SetInboundChecks(ctx, []int{p}, false); !errors.Is(err, ErrValidation) {
|
|
t.Fatalf("port %d: expected ErrValidation, got %v", p, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSetInboundChecksRejectsDuplicatePorts(t *testing.T) {
|
|
d, ctx := newTestDB(t)
|
|
if err := d.BootstrapFromConfig(ctx, &config.ControlAPI{}); err != nil {
|
|
t.Fatalf("bootstrap: %v", err)
|
|
}
|
|
if err := d.SetInboundChecks(ctx, []int{22, 80, 22}, false); !errors.Is(err, ErrValidation) {
|
|
t.Fatalf("expected ErrValidation for duplicate port, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestGetSetInboundChecksRoundTrip(t *testing.T) {
|
|
d, ctx := newTestDB(t)
|
|
if err := d.BootstrapFromConfig(ctx, &config.ControlAPI{}); err != nil {
|
|
t.Fatalf("bootstrap: %v", err)
|
|
}
|
|
before, err := d.GetInboundChecks(ctx)
|
|
if err != nil {
|
|
t.Fatalf("get inbound checks: %v", err)
|
|
}
|
|
if len(before.Ports) != 0 || before.ICMP {
|
|
t.Fatalf("expected default {[] false}, got %+v", before)
|
|
}
|
|
|
|
if err := d.SetInboundChecks(ctx, []int{22, 443, 8080}, true); err != nil {
|
|
t.Fatalf("set inbound checks: %v", err)
|
|
}
|
|
after, err := d.GetInboundChecks(ctx)
|
|
if err != nil {
|
|
t.Fatalf("get inbound checks after set: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(after.Ports, []int{22, 443, 8080}) || !after.ICMP {
|
|
t.Fatalf("expected {[22 443 8080] true}, got %+v", after)
|
|
}
|
|
if after.UpdatedAt.Before(before.UpdatedAt) {
|
|
t.Fatalf("expected updated_at not to go backwards, before=%v after=%v", before.UpdatedAt, after.UpdatedAt)
|
|
}
|
|
|
|
// Setting an empty port list + icmp:false is legal — it's the "disable
|
|
// all inbound checks without touching sites" configuration.
|
|
if err := d.SetInboundChecks(ctx, nil, false); err != nil {
|
|
t.Fatalf("set empty inbound checks: %v", err)
|
|
}
|
|
cleared, err := d.GetInboundChecks(ctx)
|
|
if err != nil {
|
|
t.Fatalf("get inbound checks after clear: %v", err)
|
|
}
|
|
if len(cleared.Ports) != 0 || cleared.ICMP {
|
|
t.Fatalf("expected {[] false} after clearing, got %+v", cleared)
|
|
}
|
|
}
|