mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-07-20 17:01:15 +00:00
271 lines
7.8 KiB
Go
271 lines
7.8 KiB
Go
package validators
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestDomainValidator_SafeHostname(t *testing.T) {
|
|
type testCase struct {
|
|
description string
|
|
options DomainValidatorOptions
|
|
input string
|
|
expected string
|
|
errorFunc func(t *testing.T, e error)
|
|
}
|
|
|
|
tests := []testCase{
|
|
{
|
|
description: "Empty url fails",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "url cannot be empty")
|
|
},
|
|
},
|
|
{
|
|
description: "URL without host fails",
|
|
input: "/foo",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "missing host in url")
|
|
},
|
|
},
|
|
{
|
|
description: "Invalid url fails",
|
|
input: "foo:foo",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "failed to parse host")
|
|
},
|
|
},
|
|
{
|
|
description: "With scheme and invalid url should fail",
|
|
options: DomainValidatorOptions{WithScheme: true, AllowedSchemes: []string{"https"}},
|
|
input: "https://foo:foo",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "failed to parse input url")
|
|
},
|
|
},
|
|
{
|
|
description: "Scheme disabled with scheme should pass",
|
|
input: "https://example.com",
|
|
expected: "example.com",
|
|
},
|
|
{
|
|
description: "Domain without scheme should parse if scheme is disabled",
|
|
input: "example.com",
|
|
expected: "example.com",
|
|
},
|
|
{
|
|
description: "Domain without scheme should not parse if scheme is enabled",
|
|
options: DomainValidatorOptions{WithScheme: true},
|
|
input: "example.com",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "invalid scheme")
|
|
},
|
|
},
|
|
{
|
|
description: "Domain with scheme and disallowed scheme should fail",
|
|
options: DomainValidatorOptions{WithScheme: true, AllowedSchemes: []string{"https"}},
|
|
input: "foo://example.com",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "invalid scheme")
|
|
},
|
|
},
|
|
{
|
|
description: "Domain with scheme and allowed scheme should pass",
|
|
options: DomainValidatorOptions{WithScheme: true, AllowedSchemes: []string{"https"}},
|
|
input: "https://example.com",
|
|
expected: "example.com",
|
|
},
|
|
{
|
|
description: "Domain should get lowercased",
|
|
input: "EXAMPLE.COM",
|
|
expected: "example.com",
|
|
},
|
|
{
|
|
description: "DNS dot should be removed",
|
|
input: "example.com.",
|
|
expected: "example.com",
|
|
},
|
|
{
|
|
description: "IPv4 address should fail",
|
|
input: "127.0.0.1",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "ip addresses are not supported")
|
|
},
|
|
},
|
|
{
|
|
description: "IPv6 address should fail",
|
|
input: "[::1]",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "ip addresses are not supported")
|
|
},
|
|
},
|
|
{
|
|
description: "Domains with unicode characters should be allowed",
|
|
input: "bücher.example.com",
|
|
expected: "xn--bcher-kva.example.com",
|
|
},
|
|
{
|
|
description: "Invalid IDNA domain should fail",
|
|
input: "ab--cd.example.com",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "invalid label")
|
|
},
|
|
},
|
|
{
|
|
description: "With port enabled without any port should work",
|
|
options: DomainValidatorOptions{WithPort: true},
|
|
input: "example.com",
|
|
expected: "example.com",
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.description, func(t *testing.T) {
|
|
v := NewDomainValidator(test.options)
|
|
res, err := v.SafeHostname(test.input)
|
|
if test.errorFunc != nil {
|
|
test.errorFunc(t, err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
assert.Equal(t, test.expected, res)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDomainValidator_Validate(t *testing.T) {
|
|
type testCase struct {
|
|
description string
|
|
options DomainValidatorOptions
|
|
expected string
|
|
actual string
|
|
errorFunc func(t *testing.T, e error)
|
|
}
|
|
|
|
tests := []testCase{
|
|
{
|
|
description: "Invalid expected domain fails checks",
|
|
expected: "foo:foo",
|
|
actual: "bar.com",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "failed to parse host:")
|
|
},
|
|
},
|
|
{
|
|
description: "Invalid check domain fails checks",
|
|
expected: "example.com",
|
|
actual: "foo:foo",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "failed to parse host:")
|
|
},
|
|
},
|
|
{
|
|
description: "Valid domains with non-matching schemes should fail",
|
|
options: DomainValidatorOptions{WithScheme: true, AllowedSchemes: []string{"https", "http"}},
|
|
expected: "https://example.com",
|
|
actual: "http://example.com",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorIs(t, e, ErrSchemeMismatch)
|
|
},
|
|
},
|
|
{
|
|
description: "Valid domains with matching schemes should pass",
|
|
options: DomainValidatorOptions{WithScheme: true, AllowedSchemes: []string{"https", "http"}},
|
|
expected: "https://example.com",
|
|
actual: "https://example.com",
|
|
},
|
|
{
|
|
description: "Port validation with ports enabled and empty ports should work",
|
|
options: DomainValidatorOptions{WithPort: true},
|
|
expected: "example.com",
|
|
actual: "example.com",
|
|
},
|
|
{
|
|
description: "Port validation should pass with same port",
|
|
options: DomainValidatorOptions{WithPort: true},
|
|
expected: "example.com:8080",
|
|
actual: "example.com:8080",
|
|
},
|
|
{
|
|
description: "Port enabled with scheme and matching port should pass",
|
|
options: DomainValidatorOptions{WithPort: true},
|
|
expected: "https://example.com:443",
|
|
actual: "https://example.com:443",
|
|
},
|
|
{
|
|
description: "Failure to format expected domain should fail",
|
|
expected: "ab--cd.example.com",
|
|
actual: "example.com",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "idna: invalid label")
|
|
},
|
|
},
|
|
{
|
|
description: "Failure to format check domain should fail",
|
|
expected: "example.com",
|
|
actual: "ab--cd.example.com",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorContains(t, e, "idna: invalid label")
|
|
},
|
|
},
|
|
{
|
|
description: "Valid domains with matching schemes and ports should pass",
|
|
options: DomainValidatorOptions{WithScheme: true, AllowedSchemes: []string{"https", "http"}, WithPort: true},
|
|
expected: "https://example.com:8080",
|
|
actual: "https://example.com:8080",
|
|
},
|
|
{
|
|
description: "Valid domains with matching schemes should pass",
|
|
options: DomainValidatorOptions{WithScheme: true, AllowedSchemes: []string{"https", "http"}},
|
|
expected: "https://example.com",
|
|
actual: "https://example.com",
|
|
},
|
|
{
|
|
description: "Valid domains with non matching ports should fail",
|
|
options: DomainValidatorOptions{WithPort: true},
|
|
expected: "example.com:8080",
|
|
actual: "example.com:8085",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorIs(t, e, ErrPortMismatch)
|
|
},
|
|
},
|
|
{
|
|
description: "Valid domains without ports or schemes should pass",
|
|
actual: "example.com",
|
|
expected: "example.com",
|
|
},
|
|
{
|
|
description: "Unicode valid domains should pass",
|
|
expected: "xn--bcher-kva.example.com",
|
|
actual: "bücher.example.com",
|
|
},
|
|
{
|
|
description: "Unicode valid domains should pass (reverse)",
|
|
expected: "bücher.example.com",
|
|
actual: "xn--bcher-kva.example.com",
|
|
},
|
|
{
|
|
description: "Non matching hostnames should fail",
|
|
expected: "example.com",
|
|
actual: "foo.com",
|
|
errorFunc: func(t *testing.T, e error) {
|
|
assert.ErrorIs(t, e, ErrHostnameMismatch)
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.description, func(t *testing.T) {
|
|
v := NewDomainValidator(test.options)
|
|
err := v.Validate(test.expected, test.actual)
|
|
if test.errorFunc != nil {
|
|
test.errorFunc(t, err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
}
|