package utils

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestValidateCallbackURLPattern(t *testing.T) {
	// #nosec G101
	const wildcardUserinfoPattern = "https://user:*@example.com/callback"

	tests := []struct {
		name        string
		pattern     string
		shouldError bool
	}{
		{
			name:        "exact URL",
			pattern:     "https://example.com/callback",
			shouldError: false,
		},
		{
			name:        "wildcard scheme",
			pattern:     "*://example.com/callback",
			shouldError: false,
		},
		{
			name:        "wildcard port",
			pattern:     "https://example.com:*/callback",
			shouldError: false,
		},
		{
			name:        "partial wildcard port",
			pattern:     "https://example.com:80*/callback",
			shouldError: false,
		},
		{
			name:        "wildcard userinfo",
			pattern:     wildcardUserinfoPattern,
			shouldError: false,
		},
		{
			name:        "glob wildcard",
			pattern:     "*",
			shouldError: false,
		},
		{
			name:        "relative URL",
			pattern:     "/callback",
			shouldError: true,
		},
		{
			name:        "missing scheme separator",
			pattern:     "https//example.com/callback",
			shouldError: true,
		},
		{
			name:        "malformed wildcard host glob",
			pattern:     "https://exa[mple.com/callback",
			shouldError: true,
		},
		{
			name:        "malformed IPv6 host",
			pattern:     "http://[::1",
			shouldError: true,
		},
		{
			name:        "javascript scheme",
			pattern:     "javascript:alert(1)",
			shouldError: true,
		},
		{
			name:        "data scheme",
			pattern:     "data:text/html;base64,PGgxPkhlbGxvPC9oMT4=",
			shouldError: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := ValidateCallbackURLPattern(tt.pattern)
			if tt.shouldError {
				require.Error(t, err)
				return
			}

			require.NoError(t, err)
		})
	}
}

func TestNormalizeToURLPatternStandard(t *testing.T) {
	tests := []struct {
		name     string
		input    string
		expected string
	}{
		{
			name:     "exact URL unchanged",
			input:    "https://example.com/callback",
			expected: "https://example.com/callback",
		},
		{
			name:     "single wildcard path segment converted to named parameter",
			input:    "https://example.com/api/*/callback",
			expected: "https://example.com/api/:p5/callback",
		},
		{
			name:     "single wildcard in path suffix converted to named parameter",
			input:    "https://example.com/test*",
			expected: "https://example.com/test:p5",
		},
		{
			name:     "globstar converted to single asterisk",
			input:    "https://example.com/**/callback",
			expected: "https://example.com/*/callback",
		},
		{
			name:     "mixed globstar and single wildcard conversion",
			input:    "https://example.com/**/v1/**/callback/*",
			expected: "https://example.com/*/v1/*/callback/:p19",
		},
		{
			name:     "URL without path unchanged",
			input:    "https://example.com",
			expected: "https://example.com",
		},
		{
			name:     "relative path conversion",
			input:    "/foo/*/bar",
			expected: "/foo/:p5/bar",
		},
		{
			name:     "wildcard in hostname is not normalized by this function",
			input:    "https://*.example.com/callback",
			expected: "https://*.example.com/callback",
		},
		{
			name:     "IPv6 hostname escapes all colons inside address",
			input:    "https://[2001:db8:1:1::a:1]/callback",
			expected: "https://[2001\\:db8\\:1\\:1\\:\\:a\\:1]/callback",
		},
		{
			name:     "IPv6 hostname with port escapes only address colons",
			input:    "https://[::1]:8080/callback",
			expected: "https://[\\:\\:1]:8080/callback",
		},
		{
			name:     "wildcard in query is converted when query is part of input",
			input:    "https://example.com/callback?code=*",
			expected: "https://example.com/callback?code=:p15",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert.Equal(t, tt.expected, normalizeToURLPatternStandard(tt.input))
		})
	}
}

func TestMatchCallbackURL(t *testing.T) {
	tests := []struct {
		name        string
		pattern     string
		input       string
		shouldMatch bool
	}{
		// Basic matching
		{
			"exact match",
			"https://example.com/callback",
			"https://example.com/callback",
			true,
		},
		{
			"no match",
			"https://example.org/callback",
			"https://example.com/callback",
			false,
		},
		{
			"exact match - IPv4",
			"https://10.1.0.1/callback",
			"https://10.1.0.1/callback",
			true,
		},
		{
			"exact match - IPv6",
			"https://[2001:db8:1:1::a:1]/callback",
			"https://[2001:db8:1:1::a:1]/callback",
			true,
		},

		// Scheme
		{
			"scheme mismatch",
			"https://example.com/callback",
			"http://example.com/callback",
			false,
		},
		{
			"wildcard scheme",
			"*://example.com/callback",
			"https://example.com/callback",
			true,
		},

		// Hostname
		{
			"hostname mismatch",
			"https://example.com/callback",
			"https://malicious.com/callback",
			false,
		},
		{
			"wildcard subdomain",
			"https://*.example.com/callback",
			"https://subdomain.example.com/callback",
			true,
		},
		{
			"partial wildcard in hostname prefix",
			"https://app*.example.com/callback",
			"https://app1.example.com/callback",
			true,
		},
		{
			"partial wildcard in hostname suffix",
			"https://*-prod.example.com/callback",
			"https://api-prod.example.com/callback",
			true,
		},
		{
			"partial wildcard in hostname middle",
			"https://app-*-server.example.com/callback",
			"https://app-staging-server.example.com/callback",
			true,
		},
		{
			"subdomain wildcard doesn't match domain hijack attempt",
			"https://*.example.com/callback",
			"https://malicious.site?url=abc.example.com/callback",
			false,
		},
		{
			"hostname mismatch with confusable characters",
			"https://example.com/callback",
			"https://examp1e.com/callback",
			false,
		},
		{
			"hostname mismatch with homograph attack",
			"https://example.com/callback",
			"https://еxample.com/callback",
			false,
		},

		// Port
		{
			"port mismatch",
			"https://example.com:8080/callback",
			"https://example.com:9090/callback",
			false,
		},
		{
			"wildcard port",
			"https://example.com:*/callback",
			"https://example.com:8080/callback",
			true,
		},
		{
			"partial wildcard in port prefix",
			"https://example.com:80*/callback",
			"https://example.com:8080/callback",
			true,
		},
		{
			"wildcard port - IPv4",
			"https://10.1.0.1:*/callback",
			"https://10.1.0.1:8080/callback",
			true,
		},
		{
			"partial wildcard in port prefix - IPv4",
			"https://10.1.0.1:80*/callback",
			"https://10.1.0.1:8080/callback",
			true,
		},
		{
			"wildcard port - IPv6",
			"https://[2001:db8:1:1::a:1]:*/callback",
			"https://[2001:db8:1:1::a:1]:8080/callback",
			true,
		},
		{
			"partial wildcard in port prefix - IPv6",
			"https://[2001:db8:1:1::a:1]:80*/callback",
			"https://[2001:db8:1:1::a:1]:8080/callback",
			true,
		},

		// Path
		{
			"path mismatch",
			"https://example.com/callback",
			"https://example.com/other",
			false,
		},
		{
			"wildcard path segment",
			"https://example.com/api/*/callback",
			"https://example.com/api/v1/callback",
			true,
		},
		{
			"wildcard entire path",
			"https://example.com/*",
			"https://example.com/callback",
			true,
		},
		{
			"wildcard entire path - IPv4",
			"https://10.1.0.1/*",
			"https://10.1.0.1/callback",
			true,
		},
		{
			"wildcard entire path - IPv6",
			"https://[2001:db8:1:1::a:1]/*",
			"https://[2001:db8:1:1::a:1]/callback",
			true,
		},
		{
			"partial wildcard in path prefix",
			"https://example.com/test*",
			"https://example.com/testcase",
			true,
		},
		{
			"partial wildcard in path suffix",
			"https://example.com/*-callback",
			"https://example.com/oauth-callback",
			true,
		},
		{
			"partial wildcard in path middle",
			"https://example.com/api-*-v1/callback",
			"https://example.com/api-internal-v1/callback",
			true,
		},
		{
			"multiple partial wildcards in path",
			"https://example.com/*/test*/callback",
			"https://example.com/v1/testing/callback",
			true,
		},
		{
			"multiple wildcard segments in path",
			"https://example.com/**/callback",
			"https://example.com/api/v1/foo/bar/callback",
			true,
		},
		{
			"multiple wildcard segments in path",
			"https://example.com/**/v1/**/callback",
			"https://example.com/api/v1/foo/bar/callback",
			true,
		},
		{
			"partial wildcard matching full path segment",
			"https://example.com/foo-*",
			"https://example.com/foo-bar",
			true,
		},

		// Credentials
		{
			"username mismatch",
			"https://user:pass@example.com/callback",
			"https://admin:pass@example.com/callback",
			false,
		},
		{
			"missing credentials",
			"https://user:pass@example.com/callback",
			"https://example.com/callback",
			false,
		},
		{
			"wildcard password",
			"https://user:*@example.com/callback",
			"https://user:secret123@example.com/callback",
			true,
		},
		{
			"partial wildcard in username",
			"https://admin*:pass@example.com/callback",
			"https://admin123:pass@example.com/callback",
			true,
		},
		{
			"partial wildcard in password",
			"https://user:pass*@example.com/callback",
			"https://user:password123@example.com/callback",
			true,
		},
		{
			"wildcard password doesn't allow domain hijack",
			"https://user:*@example.com/callback",
			"https://user:password@malicious.site#example.com/callback",
			false,
		},
		{
			"credentials with @ in password trying to hijack hostname",
			"https://user:pass@example.com/callback",
			"https://user:pass@evil.com@example.com/callback",
			false,
		},

		// Query parameters
		{
			"extra query parameter",
			"https://example.com/callback?code=*",
			"https://example.com/callback?code=abc123&extra=value",
			false,
		},
		{
			"missing query parameter",
			"https://example.com/callback?code=*&state=*",
			"https://example.com/callback?code=abc123",
			false,
		},
		{
			"query parameter after fragment",
			"https://example.com/callback?code=123",
			"https://example.com/callback#section?code=123",
			false,
		},
		{
			"query parameter name mismatch",
			"https://example.com/callback?code=*",
			"https://example.com/callback?token=abc123",
			false,
		},
		{
			"wildcard query parameter",
			"https://example.com/callback?code=*",
			"https://example.com/callback?code=abc123",
			true,
		},
		{
			"multiple query parameters",
			"https://example.com/callback?code=*&state=*",
			"https://example.com/callback?code=abc123&state=xyz789",
			true,
		},
		{
			"query parameters in different order",
			"https://example.com/callback?state=*&code=*",
			"https://example.com/callback?code=abc123&state=xyz789",
			true,
		},
		{
			"exact query parameter value",
			"https://example.com/callback?mode=production",
			"https://example.com/callback?mode=production",
			true,
		},
		{
			"query parameter value mismatch",
			"https://example.com/callback?mode=production",
			"https://example.com/callback?mode=development",
			false,
		},
		{
			"mixed exact and wildcard query parameters",
			"https://example.com/callback?mode=production&code=*",
			"https://example.com/callback?mode=production&code=abc123",
			true,
		},
		{
			"mixed exact and wildcard with wrong exact value",
			"https://example.com/callback?mode=production&code=*",
			"https://example.com/callback?mode=development&code=abc123",
			false,
		},
		{
			"multiple values for same parameter",
			"https://example.com/callback?param=*&param=*",
			"https://example.com/callback?param=value1&param=value2",
			true,
		},
		{
			"unexpected query parameters",
			"https://example.com/callback",
			"https://example.com/callback?extra=value",
			false,
		},
		{
			"query parameter with redirect to external site",
			"https://example.com/callback?code=*",
			"https://example.com/callback?code=123&redirect=https://evil.com",
			false,
		},
		{
			"open redirect via encoded URL in query param",
			"https://example.com/callback?state=*",
			"https://example.com/callback?state=abc&next=//evil.com",
			false,
		},

		// Fragment
		{
			"fragment ignored when both pattern and input have fragment",
			"https://example.com/callback#fragment",
			"https://example.com/callback#fragment",
			true,
		},
		{
			"fragment ignored when pattern has fragment but input doesn't",
			"https://example.com/callback#fragment",
			"https://example.com/callback",
			true,
		},
		{
			"fragment ignored when input has fragment but pattern doesn't",
			"https://example.com/callback",
			"https://example.com/callback#section",
			true,
		},

		// Path traversal and injection attempts
		{
			"path traversal attempt",
			"https://example.com/callback",
			"https://example.com/../admin/callback",
			false,
		},
		{
			"backslash instead of forward slash",
			"https://example.com/callback",
			"https://example.com\\callback",
			true,
		},
		{
			"double slash in hostname (protocol smuggling)",
			"https://example.com/callback",
			"https://example.com//evil.com/callback",
			false,
		},
		{
			"CRLF injection attempt in path",
			"https://example.com/callback",
			"https://example.com/callback%0d%0aLocation:%20https://evil.com",
			false,
		},
		{
			"null byte injection",
			"https://example.com/callback",
			"https://example.com/callback%00.evil.com",
			false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			matches, err := matchCallbackURL(tt.pattern, tt.input)
			require.NoError(t, err)
			assert.Equal(t, tt.shouldMatch, matches)
		})
	}
}

func TestGetCallbackURLFromList_LoopbackSpecialHandling(t *testing.T) {
	tests := []struct {
		name             string
		urls             []string
		inputCallbackURL string
		expectedURL      string
		expectMatch      bool
	}{
		{
			name:             "127.0.0.1 with dynamic port - exact match",
			urls:             []string{"http://127.0.0.1/callback"},
			inputCallbackURL: "http://127.0.0.1:8080/callback",
			expectedURL:      "http://127.0.0.1:8080/callback",
			expectMatch:      true,
		},
		{
			name:             "127.0.0.1 with same port - exact match",
			urls:             []string{"http://127.0.0.1:8080/callback"},
			inputCallbackURL: "http://127.0.0.1:8080/callback",
			expectedURL:      "http://127.0.0.1:8080/callback",
			expectMatch:      true,
		},
		{
			name:             "127.0.0.1 with different port",
			urls:             []string{"http://127.0.0.1/callback"},
			inputCallbackURL: "http://127.0.0.1:9999/callback",
			expectedURL:      "http://127.0.0.1:9999/callback",
			expectMatch:      true,
		},
		{
			name:             "IPv6 loopback with dynamic port - exact match",
			urls:             []string{"http://[::1]/callback"},
			inputCallbackURL: "http://[::1]:8080/callback",
			expectedURL:      "http://[::1]:8080/callback",
			expectMatch:      true,
		},
		{
			name:             "IPv6 loopback with same port - exact match",
			urls:             []string{"http://[::1]:8080/callback"},
			inputCallbackURL: "http://[::1]:8080/callback",
			expectedURL:      "http://[::1]:8080/callback",
			expectMatch:      true,
		},
		{
			name:             "IPv6 loopback with path match",
			urls:             []string{"http://[::1]/auth/*"},
			inputCallbackURL: "http://[::1]:8080/auth/callback",
			expectedURL:      "http://[::1]:8080/auth/callback",
			expectMatch:      true,
		},
		{
			name:             "localhost with dynamic port",
			urls:             []string{"http://localhost/callback"},
			inputCallbackURL: "http://localhost:8080/callback",
			expectedURL:      "http://localhost:8080/callback",
			expectMatch:      true,
		},
		{
			name:             "https loopback doesn't trigger special handling",
			urls:             []string{"https://127.0.0.1/callback"},
			inputCallbackURL: "https://127.0.0.1:8080/callback",
			expectedURL:      "",
			expectMatch:      false,
		},
		{
			name:             "loopback with path match",
			urls:             []string{"http://127.0.0.1/auth/*"},
			inputCallbackURL: "http://127.0.0.1:3000/auth/callback",
			expectedURL:      "http://127.0.0.1:3000/auth/callback",
			expectMatch:      true,
		},
		{
			name:             "loopback with path port",
			urls:             []string{"http://127.0.0.1:*/auth/callback"},
			inputCallbackURL: "http://127.0.0.1:3000/auth/callback",
			expectedURL:      "http://127.0.0.1:3000/auth/callback",
			expectMatch:      true,
		},
		{
			name:             "IPv6 loopback with path port",
			urls:             []string{"http://[::1]:*/auth/callback"},
			inputCallbackURL: "http://[::1]:3000/auth/callback",
			expectedURL:      "http://[::1]:3000/auth/callback",
			expectMatch:      true,
		},
		{
			name:             "loopback with path mismatch",
			urls:             []string{"http://127.0.0.1/callback"},
			inputCallbackURL: "http://127.0.0.1:8080/different",
			expectedURL:      "",
			expectMatch:      false,
		},
		{
			name:             "non-loopback IP",
			urls:             []string{"http://192.168.1.1/callback"},
			inputCallbackURL: "http://192.168.1.1:8080/callback",
			expectedURL:      "",
			expectMatch:      false,
		},
		{
			name:             "wildcard matches loopback",
			urls:             []string{"*"},
			inputCallbackURL: "http://127.0.0.1:8080/callback",
			expectedURL:      "http://127.0.0.1:8080/callback",
			expectMatch:      true,
		},
		{
			name:             "wildcard matches IPv6 loopback",
			urls:             []string{"*"},
			inputCallbackURL: "http://[::1]:8080/callback",
			expectedURL:      "http://[::1]:8080/callback",
			expectMatch:      true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result, err := GetCallbackURLFromList(tt.urls, tt.inputCallbackURL)
			require.NoError(t, err)
			if tt.expectMatch {
				assert.Equal(t, tt.expectedURL, result)
			} else {
				assert.Empty(t, result)
			}
		})
	}
}

func TestMatchesAnyURLPattern(t *testing.T) {
	tests := []struct {
		name     string
		patterns []string
		input    string
		want     bool
	}{
		{"empty list denies", nil, "https://app.example.com/oauth/client", false},
		{"empty slice denies", []string{}, "https://app.example.com/oauth/client", false},
		{"exact match", []string{"https://app.example.com/oauth/client"}, "https://app.example.com/oauth/client", true},
		{"wildcard path", []string{"https://app.example.com/**"}, "https://app.example.com/oauth/client", true},
		{"wildcard host segment", []string{"https://*.example.com/oauth/client"}, "https://app.example.com/oauth/client", true},
		{"star matches all", []string{"*"}, "https://anything.example.com/x", true},
		{"no match", []string{"https://other.example.com/**"}, "https://app.example.com/oauth/client", false},
		{"second pattern matches", []string{"https://a.example.com/**", "https://app.example.com/**"}, "https://app.example.com/oauth/client", true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert.Equal(t, tt.want, MatchesAnyURLPattern(tt.patterns, tt.input))
		})
	}
}

func TestLoopbackURLWithWildcardPort(t *testing.T) {
	tests := []struct {
		name   string
		input  string
		output string
	}{
		{
			name:   "localhost http with port strips port",
			input:  "http://localhost:3000/callback",
			output: "http://localhost/callback",
		},
		{
			name:   "localhost http without port stays same",
			input:  "http://localhost/callback",
			output: "http://localhost/callback",
		},
		{
			name:   "IPv4 loopback with port strips port",
			input:  "http://127.0.0.1:8080/callback",
			output: "http://127.0.0.1/callback",
		},
		{
			name:   "IPv4 loopback without port stays same",
			input:  "http://127.0.0.1/callback",
			output: "http://127.0.0.1/callback",
		},
		{
			name:   "IPv6 loopback with port strips port and keeps brackets",
			input:  "http://[::1]:8080/callback",
			output: "http://[::1]/callback",
		},
		{
			name:   "IPv6 loopback preserves path query and fragment",
			input:  "http://[::1]:8080/auth/callback?code=123#state",
			output: "http://[::1]/auth/callback?code=123#state",
		},
		{
			name:   "https loopback returns empty",
			input:  "https://127.0.0.1:8080/callback",
			output: "",
		},
		{
			name:   "non loopback host returns empty",
			input:  "http://example.com:8080/callback",
			output: "",
		},
		{
			name:   "non loopback IP returns empty",
			input:  "http://192.168.1.10:8080/callback",
			output: "",
		},
		{
			name:   "malformed URL returns empty",
			input:  "http://[::1:8080/callback",
			output: "",
		},
		{
			name:   "relative URL returns empty",
			input:  "/callback",
			output: "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			assert.Equal(t, tt.output, loopbackURLWithWildcardPort(tt.input))
		})
	}
}

func TestGetCallbackURLFromList_MultiplePatterns(t *testing.T) {
	tests := []struct {
		name             string
		urls             []string
		inputCallbackURL string
		expectedURL      string
		expectMatch      bool
	}{
		{
			name: "matches first pattern",
			urls: []string{
				"https://example.com/callback",
				"https://example.org/callback",
			},
			inputCallbackURL: "https://example.com/callback",
			expectedURL:      "https://example.com/callback",
			expectMatch:      true,
		},
		{
			name: "matches second pattern",
			urls: []string{
				"https://example.com/callback",
				"https://example.org/callback",
			},
			inputCallbackURL: "https://example.org/callback",
			expectedURL:      "https://example.org/callback",
			expectMatch:      true,
		},
		{
			name: "matches none",
			urls: []string{
				"https://example.com/callback",
				"https://example.org/callback",
			},
			inputCallbackURL: "https://malicious.com/callback",
			expectedURL:      "",
			expectMatch:      false,
		},
		{
			name: "matches wildcard pattern",
			urls: []string{
				"https://example.com/callback",
				"https://*.example.org/callback",
			},
			inputCallbackURL: "https://subdomain.example.org/callback",
			expectedURL:      "https://subdomain.example.org/callback",
			expectMatch:      true,
		},
		{
			name:             "empty pattern list",
			urls:             []string{},
			inputCallbackURL: "https://example.com/callback",
			expectedURL:      "",
			expectMatch:      false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result, err := GetCallbackURLFromList(tt.urls, tt.inputCallbackURL)
			require.NoError(t, err)
			if tt.expectMatch {
				assert.Equal(t, tt.expectedURL, result)
			} else {
				assert.Empty(t, result)
			}
		})
	}
}

// The only wildcards this package supports are * and **
// urlpattern additionally reads ":name" as a single-segment wildcard, so a literal colon in a
// pattern must never widen what it matches
func TestMatchCallbackURL_ColonIsNotAWildcard(t *testing.T) {
	tests := []struct {
		name    string
		pattern string
		input   string
		want    bool
	}{
		{"host label is literal", "https://:host.example.com/cb", "https://evil.example.com/cb", false},
		{"host label matches itself", "https://:host.example.com/cb", "https://:host.example.com/cb", true},
		{"path segment is literal", "https://app.example.com/a:b", "https://app.example.com/a:other", false},
		{"path segment matches itself", "https://app.example.com/a:b", "https://app.example.com/a:b", true},
		{"userinfo is literal", "https://user:pass@app.example.com/cb", "https://user:other@app.example.com/cb", false},
		{"userinfo matches itself", "https://user:pass@app.example.com/cb", "https://user:pass@app.example.com/cb", true},

		// Structural colons must keep working
		{"port is matched exactly", "https://app.example.com:8080/cb", "https://app.example.com:8080/cb", true},
		{"port mismatch is rejected", "https://app.example.com:8080/cb", "https://app.example.com:9090/cb", false},
		{"ipv6 host", "https://[::1]/cb", "https://[::1]/cb", true},
		{"ipv6 host with port", "https://[::1]:8080/cb", "https://[::1]:8080/cb", true},

		// The supported wildcards are unaffected
		{"single asterisk spans one segment", "https://app.example.com/*/cb", "https://app.example.com/x/cb", true},
		{"single asterisk does not span two", "https://app.example.com/*/cb", "https://app.example.com/x/y/cb", false},
		{"globstar spans many segments", "https://app.example.com/**", "https://app.example.com/a/b/c", true},
		{"asterisk in host", "https://*.example.com/cb", "https://sub.example.com/cb", true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := matchCallbackURL(tt.pattern, tt.input)
			require.NoError(t, err)
			assert.Equal(t, tt.want, got)
		})
	}
}
