Repository: gofiber/fiber
File: ctx_test.go (Go)

Code before:
func Test_Ctx_Stale(t *testing.T) {
	t.Parallel()
	app := New()
	c := app.AcquireCtx(&fasthttp.RequestCtx{})

	require.True(t, c.Stale())
}

// go test -run Test_Ctx_Subdomains
func Test_Ctx_Subdomains(t *testing.T) {
	t.Parallel()
	app := New()
	c := app.AcquireCtx(&fasthttp.RequestCtx{})

	c.Request().URI().SetHost("john.doe.is.awesome.google.com")
	require.Equal(t, []string{"john", "doe"}, c.Subdomains(4))

	c.Request().URI().SetHost("localhost:3000")
	require.Empty(t, c.Subdomains())

	c.Request().URI().SetHost("john.doe.google.com")
	require.Empty(t, c.Subdomains(-1), "negative offset should return empty slice")

	c.Request().URI().SetHost("john.doe.google.com")
	require.Empty(t, c.Subdomains(0), "negative offset should return empty slice")
}

// go test -run Test_Ctx_Subdomains_OffsetTooHigh
func Test_Ctx_Subdomains_OffsetTooHigh(t *testing.T) {
	t.Parallel()
	app := New()
	c := app.AcquireCtx(&fasthttp.RequestCtx{})

	c.Request().URI().SetHost("john.doe.is.awesome.google.com")
	require.Empty(t, c.Subdomains(10))
}

// go test -v -run=^$ -bench=Benchmark_Ctx_Subdomains -benchmem -count=4
func Benchmark_Ctx_Subdomains(b *testing.B) {
	app := New()
	c := app.AcquireCtx(&fasthttp.RequestCtx{})

	c.Request().SetRequestURI("http://john.doe.google.com")
	var res []string
	b.ReportAllocs()
	for b.Loop() {
		res = c.Subdomains()
	}
	require.Equal(b, []string{"john", "doe"}, res)
}


Review comment (bug):
if we add

```go
require.Empty(t, c.Subdomains(-1))
```

we get a panic:

```bash
--- FAIL: Test_Ctx_Subdomains_OffsetTooHigh (0.00s)
panic: runtime error: slice bounds out of range [:7] with capacity 6 [recovered]
	panic: runtime error: slice bounds out of range [:7] with capacity 6

goroutine 4 [running]:
testing.tRunner.func1.2({0x102a2b100, 0x140000229c0})
	/opt/homebrew/Cellar/go/1.24.3/libexec/src/testing/testing.go:1734 +0x1ac
testing.tRunner.func1()
	/opt/homebrew/Cellar/go/1.24.3/libexec/src/testing/testing.go:1737 +0x334
panic({0x102a2b100?, 0x140000229c0?})
	/opt/homebrew/Cellar/go/1.24.3/libexec/src/runtime/panic.go:792 +0x124
github.com/gofiber/fiber/v3.(*DefaultCtx).Subdomains(0x102a79a70?, {0x1400000fb10?, 0x102975220?, 0x1400000c5e8?})
	/Users/sixcolors/Documents/GitHub/fiber/ctx.go:1767 +0x90
github.com/gofiber/fiber/v3.Test_Ctx_Subdomains_OffsetTooHigh(0x14000003a40)
	/Users/sixcolors/Documents/GitHub/fiber/ctx_test.go:3037 +0x1ac
testing.tRunner(0x14000003a40, 0x102a6f288)
	/opt/homebrew/Cellar/go/1.24.3/libexec/src/testing/testing.go:1792 +0xe4
created by testing.(*T).Run in goroutine 1
	/opt/homebrew/Cellar/go/1.24.3/libexec/src/testing/testing.go:1851 +0x374
FAIL	github.com/gofiber/fiber/v3	0.222s
FAIL
```

Code after:
func Test_Ctx_Stale(t *testing.T) {
	t.Parallel()
	app := New()
	c := app.AcquireCtx(&fasthttp.RequestCtx{})

	require.True(t, c.Stale())
}

// go test -run Test_Ctx_Subdomains
func Test_Ctx_Subdomains(t *testing.T) {
	app := New()

	type tc struct {
		name   string
		host   string
		offset []int // nil ⇒ call without argument
		want   []string
	}

	cases := []tc{
		{
			name:   "default offset (2) drops registrable domain + TLD",
			host:   "john.doe.is.awesome.google.com",
			offset: nil, // Subdomains()
			want:   []string{"john", "doe", "is", "awesome"},
		},
		{
			name:   "custom offset trims N right-hand labels",
			host:   "john.doe.is.awesome.google.com",
			offset: []int{4},
			want:   []string{"john", "doe"},
		},
		{
			name:   "offset too high returns empty",
			host:   "john.doe.is.awesome.google.com",
			offset: []int{10},
			want:   []string{},
		},
		{
			name:   "zero offset returns all labels",
			host:   "john.doe.google.com",
			offset: []int{0},
			want:   []string{"john", "doe", "google", "com"},
		},
		{
			name:   "offset 1 keeps registrable domain",
			host:   "john.doe.google.com",
			offset: []int{1},
			want:   []string{"john", "doe", "google"},
		},
		{