cmd/vet: add subtestnames analyzer; fix all existing violations
Add a new vet analyzer that checks t.Run subtest names don't contain characters requiring quoting when re-running via "go test -run". This enforces the style guide rule: don't use spaces or punctuation in subtest names. The analyzer flags: - Direct t.Run calls with string literal names containing spaces, regex metacharacters, quotes, or other problematic characters - Table-driven t.Run(tt.name, ...) calls where tt ranges over a slice/map literal with bad name field values Also fix all 978 existing violations across 81 test files, replacing spaces with hyphens and shortening long sentence-like names to concise hyphenated forms. Updates #19242 Change-Id: Ib0ad96a111bd8e764582d1d4902fe2599454ab65 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
0f02c20c5e
commit
5ef3713c9f
+65
-58
@@ -137,14 +137,14 @@ func TestFlattenExtraClaims(t *testing.T) {
|
||||
expected map[string]any
|
||||
}{
|
||||
{
|
||||
name: "empty extra claims",
|
||||
name: "empty-extra-claims",
|
||||
input: []capRule{
|
||||
{ExtraClaims: map[string]any{}},
|
||||
},
|
||||
expected: map[string]any{},
|
||||
},
|
||||
{
|
||||
name: "string and number values",
|
||||
name: "string-and-number-values",
|
||||
input: []capRule{
|
||||
{
|
||||
ExtraClaims: map[string]any{
|
||||
@@ -159,7 +159,7 @@ func TestFlattenExtraClaims(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "slice of strings and ints",
|
||||
name: "slice-of-strings-and-ints",
|
||||
input: []capRule{
|
||||
{
|
||||
ExtraClaims: map[string]any{
|
||||
@@ -172,7 +172,8 @@ func TestFlattenExtraClaims(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "duplicate values deduplicated (slice input)",
|
||||
// duplicate values deduplicated via slice input
|
||||
name: "dedup-slice-input",
|
||||
input: []capRule{
|
||||
{
|
||||
ExtraClaims: map[string]any{
|
||||
@@ -190,7 +191,8 @@ func TestFlattenExtraClaims(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ignore unsupported map type, keep valid scalar",
|
||||
// ignore unsupported map type, keep valid scalar
|
||||
name: "ignore-unsupported-map-keep-scalar",
|
||||
input: []capRule{
|
||||
{
|
||||
ExtraClaims: map[string]any{
|
||||
@@ -204,7 +206,7 @@ func TestFlattenExtraClaims(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "scalar first, slice second",
|
||||
name: "scalar-first-slice-second",
|
||||
input: []capRule{
|
||||
{ExtraClaims: map[string]any{"foo": "bar"}},
|
||||
{ExtraClaims: map[string]any{"foo": []any{"baz"}}},
|
||||
@@ -214,7 +216,7 @@ func TestFlattenExtraClaims(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "conflicting scalar and unsupported map",
|
||||
name: "conflicting-scalar-and-unsupported-map",
|
||||
input: []capRule{
|
||||
{ExtraClaims: map[string]any{"foo": "bar"}},
|
||||
{ExtraClaims: map[string]any{"foo": map[string]any{"bad": "entry"}}},
|
||||
@@ -224,7 +226,7 @@ func TestFlattenExtraClaims(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple slices with overlap",
|
||||
name: "multiple-slices-with-overlap",
|
||||
input: []capRule{
|
||||
{ExtraClaims: map[string]any{"roles": []any{"admin", "user"}}},
|
||||
{ExtraClaims: map[string]any{"roles": []any{"admin", "guest"}}},
|
||||
@@ -234,7 +236,7 @@ func TestFlattenExtraClaims(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "slice with unsupported values",
|
||||
name: "slice-with-unsupported-values",
|
||||
input: []capRule{
|
||||
{ExtraClaims: map[string]any{
|
||||
"mixed": []any{"ok", 42, map[string]string{"oops": "fail"}},
|
||||
@@ -245,7 +247,7 @@ func TestFlattenExtraClaims(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "duplicate scalar value",
|
||||
name: "duplicate-scalar-value",
|
||||
input: []capRule{
|
||||
{ExtraClaims: map[string]any{"env": "prod"}},
|
||||
{ExtraClaims: map[string]any{"env": "prod"}},
|
||||
@@ -279,7 +281,7 @@ func TestExtraClaims(t *testing.T) {
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "extra claim",
|
||||
name: "extra-claim",
|
||||
claim: tailscaleClaims{
|
||||
Claims: jwt.Claims{},
|
||||
Nonce: "foobar",
|
||||
@@ -312,7 +314,7 @@ func TestExtraClaims(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "duplicate claim distinct values",
|
||||
name: "duplicate-claim-distinct-values",
|
||||
claim: tailscaleClaims{
|
||||
Claims: jwt.Claims{},
|
||||
Nonce: "foobar",
|
||||
@@ -350,7 +352,7 @@ func TestExtraClaims(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple extra claims",
|
||||
name: "multiple-extra-claims",
|
||||
claim: tailscaleClaims{
|
||||
Claims: jwt.Claims{},
|
||||
Nonce: "foobar",
|
||||
@@ -389,7 +391,7 @@ func TestExtraClaims(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "overwrite claim",
|
||||
name: "overwrite-claim",
|
||||
claim: tailscaleClaims{
|
||||
Claims: jwt.Claims{},
|
||||
Nonce: "foobar",
|
||||
@@ -422,7 +424,7 @@ func TestExtraClaims(t *testing.T) {
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "empty extra claims",
|
||||
name: "empty-extra-claims",
|
||||
claim: tailscaleClaims{
|
||||
Claims: jwt.Claims{},
|
||||
Nonce: "foobar",
|
||||
@@ -496,21 +498,21 @@ func TestServeToken(t *testing.T) {
|
||||
expected map[string]any
|
||||
}{
|
||||
{
|
||||
name: "GET not allowed",
|
||||
name: "GET-not-allowed",
|
||||
method: "GET",
|
||||
grantType: "authorization_code",
|
||||
strictMode: false,
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "unsupported grant type",
|
||||
name: "unsupported-grant-type",
|
||||
method: "POST",
|
||||
grantType: "pkcs",
|
||||
strictMode: false,
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid code",
|
||||
name: "invalid-code",
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
code: "invalid-code",
|
||||
@@ -518,7 +520,7 @@ func TestServeToken(t *testing.T) {
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "omit code from form",
|
||||
name: "omit-code-from-form",
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
omitCode: true,
|
||||
@@ -526,7 +528,7 @@ func TestServeToken(t *testing.T) {
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid redirect uri",
|
||||
name: "invalid-redirect-uri",
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
code: "valid-code",
|
||||
@@ -536,7 +538,7 @@ func TestServeToken(t *testing.T) {
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid remoteAddr",
|
||||
name: "invalid-remoteAddr",
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
redirectURI: "https://rp.example.com/callback",
|
||||
@@ -546,7 +548,7 @@ func TestServeToken(t *testing.T) {
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "extra claim included (non-strict)",
|
||||
name: "extra-claim-included-non-strict",
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
redirectURI: "https://rp.example.com/callback",
|
||||
@@ -568,7 +570,8 @@ func TestServeToken(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "attempt to overwrite protected claim (non-strict)",
|
||||
// attempt to overwrite protected claim in non-strict mode
|
||||
name: "overwrite-protected-claim-non-strict",
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
redirectURI: "https://rp.example.com/callback",
|
||||
@@ -708,7 +711,7 @@ func TestExtraUserInfo(t *testing.T) {
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "extra claim",
|
||||
name: "extra-claim",
|
||||
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||
caps: tailcfg.PeerCapMap{
|
||||
tailcfg.PeerCapabilityTsIDP: {
|
||||
@@ -725,7 +728,7 @@ func TestExtraUserInfo(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "duplicate claim distinct values",
|
||||
name: "duplicate-claim-distinct-values",
|
||||
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||
caps: tailcfg.PeerCapMap{
|
||||
tailcfg.PeerCapabilityTsIDP: {
|
||||
@@ -742,7 +745,7 @@ func TestExtraUserInfo(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple extra claims",
|
||||
name: "multiple-extra-claims",
|
||||
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||
caps: tailcfg.PeerCapMap{
|
||||
tailcfg.PeerCapabilityTsIDP: {
|
||||
@@ -761,13 +764,13 @@ func TestExtraUserInfo(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty extra claims",
|
||||
name: "empty-extra-claims",
|
||||
caps: tailcfg.PeerCapMap{},
|
||||
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||
expected: map[string]any{},
|
||||
},
|
||||
{
|
||||
name: "attempt to overwrite protected claim",
|
||||
name: "overwrite-protected-claim",
|
||||
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||
caps: tailcfg.PeerCapMap{
|
||||
tailcfg.PeerCapabilityTsIDP: {
|
||||
@@ -783,7 +786,7 @@ func TestExtraUserInfo(t *testing.T) {
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "extra claim omitted",
|
||||
name: "extra-claim-omitted",
|
||||
tokenValidTill: time.Now().Add(1 * time.Minute),
|
||||
caps: tailcfg.PeerCapMap{
|
||||
tailcfg.PeerCapabilityTsIDP: {
|
||||
@@ -798,7 +801,7 @@ func TestExtraUserInfo(t *testing.T) {
|
||||
expected: map[string]any{},
|
||||
},
|
||||
{
|
||||
name: "expired token",
|
||||
name: "expired-token",
|
||||
caps: tailcfg.PeerCapMap{},
|
||||
tokenValidTill: time.Now().Add(-1 * time.Minute),
|
||||
expected: map[string]any{},
|
||||
@@ -1131,19 +1134,22 @@ func TestGetAllowInsecureRegistration(t *testing.T) {
|
||||
expectAllowInsecureRegistration bool
|
||||
}{
|
||||
{
|
||||
name: "flag explicitly set to false - insecure registration disabled (strict mode)",
|
||||
// flag explicitly set to false - insecure registration disabled (strict mode)
|
||||
name: "flag-false-insecure-disabled",
|
||||
flagSet: true,
|
||||
flagValue: false,
|
||||
expectAllowInsecureRegistration: false,
|
||||
},
|
||||
{
|
||||
name: "flag explicitly set to true - insecure registration enabled",
|
||||
// flag explicitly set to true - insecure registration enabled
|
||||
name: "flag-true-insecure-enabled",
|
||||
flagSet: true,
|
||||
flagValue: true,
|
||||
expectAllowInsecureRegistration: true,
|
||||
},
|
||||
{
|
||||
name: "flag unset - insecure registration enabled (default for backward compatibility)",
|
||||
// flag unset - insecure registration enabled (default for backward compatibility)
|
||||
name: "flag-unset-insecure-enabled-default",
|
||||
flagSet: false,
|
||||
flagValue: false, // not used when unset
|
||||
expectAllowInsecureRegistration: true,
|
||||
@@ -1192,7 +1198,7 @@ func TestMigrateOAuthClients(t *testing.T) {
|
||||
expectOldRenamed bool
|
||||
}{
|
||||
{
|
||||
name: "migrate from old file to new file",
|
||||
name: "migrate-old-to-new",
|
||||
setupOldFile: true,
|
||||
oldFileContent: map[string]*funnelClient{
|
||||
"old-client": {
|
||||
@@ -1206,7 +1212,7 @@ func TestMigrateOAuthClients(t *testing.T) {
|
||||
expectOldRenamed: true,
|
||||
},
|
||||
{
|
||||
name: "new file already exists - no migration",
|
||||
name: "new-file-exists-no-migration",
|
||||
setupNewFile: true,
|
||||
newFileContent: map[string]*funnelClient{
|
||||
"existing-client": {
|
||||
@@ -1220,12 +1226,12 @@ func TestMigrateOAuthClients(t *testing.T) {
|
||||
expectOldRenamed: false,
|
||||
},
|
||||
{
|
||||
name: "neither file exists - create empty new file",
|
||||
name: "neither-exists-create-empty",
|
||||
expectNewFileExists: true,
|
||||
expectOldRenamed: false,
|
||||
},
|
||||
{
|
||||
name: "both files exist - prefer new file",
|
||||
name: "both-exist-prefer-new",
|
||||
setupOldFile: true,
|
||||
setupNewFile: true,
|
||||
oldFileContent: map[string]*funnelClient{
|
||||
@@ -1373,19 +1379,19 @@ func TestGetConfigFilePath(t *testing.T) {
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "file exists in current directory - use current directory",
|
||||
name: "file-in-cwd-use-cwd",
|
||||
fileName: "test-config.json",
|
||||
createInCwd: true,
|
||||
expectInCwd: true,
|
||||
},
|
||||
{
|
||||
name: "file does not exist - use root path",
|
||||
name: "file-missing-use-root",
|
||||
fileName: "test-config.json",
|
||||
createInCwd: false,
|
||||
expectInCwd: false,
|
||||
},
|
||||
{
|
||||
name: "file exists in both - prefer current directory",
|
||||
name: "file-in-both-prefer-cwd",
|
||||
fileName: "test-config.json",
|
||||
createInCwd: true,
|
||||
createInRoot: true,
|
||||
@@ -1472,7 +1478,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
|
||||
}{
|
||||
// Security boundary test: funnel rejection
|
||||
{
|
||||
name: "funnel requests are always rejected for security",
|
||||
name: "funnel-rejected",
|
||||
strictMode: true,
|
||||
clientID: "test-client",
|
||||
redirectURI: "https://rp.example.com/callback",
|
||||
@@ -1487,7 +1493,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
|
||||
|
||||
// Strict mode parameter validation tests (non-funnel)
|
||||
{
|
||||
name: "strict mode - missing client_id",
|
||||
name: "strict-missing-client_id",
|
||||
strictMode: true,
|
||||
clientID: "",
|
||||
redirectURI: "https://rp.example.com/callback",
|
||||
@@ -1496,7 +1502,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
|
||||
expectCode: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
name: "strict mode - missing redirect_uri",
|
||||
name: "strict-missing-redirect_uri",
|
||||
strictMode: true,
|
||||
clientID: "test-client",
|
||||
redirectURI: "",
|
||||
@@ -1507,7 +1513,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
|
||||
|
||||
// Strict mode client validation tests (non-funnel)
|
||||
{
|
||||
name: "strict mode - invalid client_id",
|
||||
name: "strict-invalid-client_id",
|
||||
strictMode: true,
|
||||
clientID: "invalid-client",
|
||||
redirectURI: "https://rp.example.com/callback",
|
||||
@@ -1517,7 +1523,7 @@ func TestAuthorizeStrictMode(t *testing.T) {
|
||||
expectCode: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
name: "strict mode - redirect_uri mismatch",
|
||||
name: "strict-redirect_uri-mismatch",
|
||||
strictMode: true,
|
||||
clientID: "test-client",
|
||||
redirectURI: "https://wrong.example.com/callback",
|
||||
@@ -1666,7 +1672,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
||||
expectIDToken bool
|
||||
}{
|
||||
{
|
||||
name: "strict mode - valid token exchange with form credentials",
|
||||
name: "strict-token-exchange-form-creds",
|
||||
strictMode: true,
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
@@ -1680,7 +1686,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
||||
expectIDToken: true,
|
||||
},
|
||||
{
|
||||
name: "strict mode - valid token exchange with basic auth",
|
||||
name: "strict-token-exchange-basic-auth",
|
||||
strictMode: true,
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
@@ -1695,7 +1701,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
||||
expectIDToken: true,
|
||||
},
|
||||
{
|
||||
name: "strict mode - missing client credentials",
|
||||
name: "strict-missing-client-creds",
|
||||
strictMode: true,
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
@@ -1708,7 +1714,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
||||
expectCode: http.StatusUnauthorized,
|
||||
},
|
||||
{
|
||||
name: "strict mode - client_id mismatch",
|
||||
name: "strict-client_id-mismatch",
|
||||
strictMode: true,
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
@@ -1722,7 +1728,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
||||
expectCode: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
name: "strict mode - invalid client secret",
|
||||
name: "strict-invalid-client-secret",
|
||||
strictMode: true,
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
@@ -1737,7 +1743,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
||||
expectCode: http.StatusUnauthorized,
|
||||
},
|
||||
{
|
||||
name: "strict mode - redirect_uri mismatch",
|
||||
name: "strict-redirect_uri-mismatch",
|
||||
strictMode: true,
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
@@ -1752,7 +1758,7 @@ func TestServeTokenWithClientValidation(t *testing.T) {
|
||||
expectCode: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
name: "non-strict mode - no client validation required",
|
||||
name: "non-strict-no-client-validation",
|
||||
strictMode: false,
|
||||
method: "POST",
|
||||
grantType: "authorization_code",
|
||||
@@ -1913,7 +1919,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
||||
expectUserInfo bool
|
||||
}{
|
||||
{
|
||||
name: "strict mode - valid token with existing client",
|
||||
name: "strict-valid-token-existing-client",
|
||||
strictMode: true,
|
||||
setupToken: true,
|
||||
setupClient: true,
|
||||
@@ -1923,7 +1929,8 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
||||
expectUserInfo: true,
|
||||
},
|
||||
{
|
||||
name: "strict mode - valid token but client no longer exists",
|
||||
// valid token but client no longer exists
|
||||
name: "strict-token-client-deleted",
|
||||
strictMode: true,
|
||||
setupToken: true,
|
||||
setupClient: false,
|
||||
@@ -1934,7 +1941,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
||||
expectCode: http.StatusUnauthorized,
|
||||
},
|
||||
{
|
||||
name: "strict mode - expired token",
|
||||
name: "strict-expired-token",
|
||||
strictMode: true,
|
||||
setupToken: true,
|
||||
setupClient: true,
|
||||
@@ -1945,7 +1952,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
||||
expectCode: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
name: "strict mode - invalid token",
|
||||
name: "strict-invalid-token",
|
||||
strictMode: true,
|
||||
setupToken: false,
|
||||
token: "invalid-token",
|
||||
@@ -1953,7 +1960,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
||||
expectCode: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
name: "strict mode - token without client association",
|
||||
name: "strict-token-no-client-assoc",
|
||||
strictMode: true,
|
||||
setupToken: true,
|
||||
setupClient: false,
|
||||
@@ -1964,7 +1971,7 @@ func TestServeUserInfoWithClientValidation(t *testing.T) {
|
||||
expectCode: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
name: "non-strict mode - no client validation required",
|
||||
name: "non-strict-no-client-validation",
|
||||
strictMode: false,
|
||||
setupToken: true,
|
||||
setupClient: false,
|
||||
|
||||
Reference in New Issue
Block a user