Files
pixa/internal/allowlist/allowlist_test.go
T
clawbot 04b5db6fbf
check / check (push) Failing after 1s
next -> main (1.0.0 milestone) (#105)
Accumulating milestone branch. One squashed commit per closed issue; `next` is kept green and mergeable to `main` at any time without notice.

Landed so far:

- `chore: update golangci-lint to v2.12.2 with canonical config` (#54) — canonical v2-schema `.golangci.yml`, pins bumped in `Dockerfile` and `script/bootstrap`, tree at `0 issues.`. Three behaviour deltas are recorded in that PR's body: `Cache.StoreVariant` takes a context, `MetadataStorage.Store` no longer leaks temp files on failure, and the `signing_key` too-short error text gained a `value too short:` prefix.

Sequencing for the milestone is tracked in #103.

Reviewed-on: #105
Co-authored-by: clawbot <clawbot@noreply.example.org>
2026-09-21 09:31:54 +02:00

226 lines
4.3 KiB
Go

package allowlist_test
import (
"net/url"
"testing"
"sneak.berlin/go/pixa/internal/allowlist"
)
const (
testExactHost = "cdn.example.com"
testImageURL = "https://cdn.example.com/image.jpg"
testSuffix = ".example.com"
)
type isAllowedCase struct {
name string
patterns []string
testURL string
want bool
}
func runIsAllowedCases(t *testing.T, tests []isAllowedCase) {
t.Helper()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
w := allowlist.New(tt.patterns)
var u *url.URL
if tt.testURL != "" {
parsed, err := url.Parse(tt.testURL)
if err != nil {
t.Fatalf("failed to parse test URL: %v", err)
}
u = parsed
}
got := w.IsAllowed(u)
if got != tt.want {
t.Errorf("IsAllowed() = %v, want %v", got, tt.want)
}
})
}
}
func TestHostAllowList_IsAllowed_ExactMatch(t *testing.T) {
t.Parallel()
runIsAllowedCases(t, []isAllowedCase{
{
name: "exact match",
patterns: []string{testExactHost},
testURL: testImageURL,
want: true,
},
{
name: "exact match case insensitive",
patterns: []string{"CDN.Example.COM"},
testURL: testImageURL,
want: true,
},
{
name: "exact match not found",
patterns: []string{testExactHost},
testURL: "https://other.example.com/image.jpg",
want: false,
},
{
name: "multiple patterns",
patterns: []string{testExactHost, ".images.org", "static.test.net"},
testURL: "https://photos.images.org/image.jpg",
want: true,
},
{
name: "empty allow list",
patterns: []string{},
testURL: testImageURL,
want: false,
},
{
name: "nil url",
patterns: []string{testExactHost},
testURL: "",
want: false,
},
{
name: "url with port",
patterns: []string{testExactHost},
testURL: "https://cdn.example.com:443/image.jpg",
want: true,
},
{
name: "whitespace in patterns",
patterns: []string{" cdn.example.com ", " .other.com "},
testURL: testImageURL,
want: true,
},
})
}
func TestHostAllowList_IsAllowed_SuffixMatch(t *testing.T) {
t.Parallel()
runIsAllowedCases(t, []isAllowedCase{
{
name: "suffix match",
patterns: []string{testSuffix},
testURL: testImageURL,
want: true,
},
{
name: "suffix match deep subdomain",
patterns: []string{testSuffix},
testURL: "https://cdn.images.example.com/image.jpg",
want: true,
},
{
name: "suffix match apex domain",
patterns: []string{testSuffix},
testURL: "https://example.com/image.jpg",
want: true,
},
{
name: "suffix match not found",
patterns: []string{testSuffix},
testURL: "https://notexample.com/image.jpg",
want: false,
},
{
name: "suffix match partial not allowed",
patterns: []string{testSuffix},
testURL: "https://fakeexample.com/image.jpg",
want: false,
},
})
}
func TestHostAllowList_IsEmpty(t *testing.T) {
t.Parallel()
tests := []struct {
name string
patterns []string
want bool
}{
{
name: "empty",
patterns: []string{},
want: true,
},
{
name: "nil",
patterns: nil,
want: true,
},
{
name: "whitespace only",
patterns: []string{" ", ""},
want: true,
},
{
name: "has entries",
patterns: []string{"example.com"},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
w := allowlist.New(tt.patterns)
if got := w.IsEmpty(); got != tt.want {
t.Errorf("IsEmpty() = %v, want %v", got, tt.want)
}
})
}
}
func TestHostAllowList_Count(t *testing.T) {
t.Parallel()
tests := []struct {
name string
patterns []string
want int
}{
{
name: "empty",
patterns: []string{},
want: 0,
},
{
name: "exact hosts only",
patterns: []string{"a.com", "b.com", "c.com"},
want: 3,
},
{
name: "suffix hosts only",
patterns: []string{".a.com", ".b.com"},
want: 2,
},
{
name: "mixed",
patterns: []string{"exact.com", ".suffix.com"},
want: 2,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
w := allowlist.New(tt.patterns)
if got := w.Count(); got != tt.want {
t.Errorf("Count() = %v, want %v", got, tt.want)
}
})
}
}