package netsettings import ( "context" "errors" "testing" ) // A nil service reaches middleware in test routers and anywhere the settings // aren't wired. It must read as "trust nothing" rather than panic — the // alternative is a nil dereference inside RequireUser, on every request. func TestHops_NilServiceTrustsNothing(t *testing.T) { var s *Service if got := s.Hops(); got != 0 { t.Errorf("(*Service)(nil).Hops() = %d, want 0", got) } } func TestNew_NilPoolYieldsDefault(t *testing.T) { s, err := New(context.Background(), nil, nil) if err != nil { t.Fatalf("New with nil pool: %v", err) } if s == nil { t.Fatal("New returned nil service") } if got := s.Hops(); got != DefaultTrustedProxyHops { t.Errorf("Hops() = %d, want %d", got, DefaultTrustedProxyHops) } } // Range is rejected before the query so the API answers 400 rather than // surfacing a CHECK violation as a 500. func TestSetHops_RejectsOutOfRange(t *testing.T) { s, _ := New(context.Background(), nil, nil) for _, hops := range []int{-1, MaxTrustedProxyHops + 1, 999} { if err := s.SetHops(context.Background(), hops); !errors.Is(err, ErrHopsOutOfRange) { t.Errorf("SetHops(%d) error = %v, want ErrHopsOutOfRange", hops, err) } } } // In-range values with no pool must still fail, and must not mutate the // cache — a write that didn't persist reporting success would leave the // running process disagreeing with the database. func TestSetHops_NoPoolFailsWithoutMutatingCache(t *testing.T) { s, _ := New(context.Background(), nil, nil) before := s.Hops() if err := s.SetHops(context.Background(), 2); err == nil { t.Error("SetHops with nil pool returned nil error") } if after := s.Hops(); after != before { t.Errorf("cache changed from %d to %d despite a failed write", before, after) } }