package audit import ( "encoding/json" "testing" ) func TestJSON(t *testing.T) { tests := []struct { verify func(t *testing.T, result string) name string pairs []string }{ { name: "single pair", pairs: []string{"username", "alice"}, verify: func(t *testing.T, result string) { var m map[string]string if err := json.Unmarshal([]byte(result), &m); err != nil { t.Fatalf("invalid JSON: %v", err) } if m["username"] != "alice" { t.Fatalf("expected alice, got %s", m["username"]) } }, }, { name: "multiple pairs", pairs: []string{"jti", "abc-123", "reason", "logout"}, verify: func(t *testing.T, result string) { var m map[string]string if err := json.Unmarshal([]byte(result), &m); err != nil { t.Fatalf("invalid JSON: %v", err) } if m["jti"] != "abc-123" { t.Fatalf("expected abc-123, got %s", m["jti"]) } if m["reason"] != "logout" { t.Fatalf("expected logout, got %s", m["reason"]) } }, }, { name: "special characters in values", pairs: []string{"username", "user\"with\\quotes"}, verify: func(t *testing.T, result string) { var m map[string]string if err := json.Unmarshal([]byte(result), &m); err != nil { t.Fatalf("invalid JSON for special chars: %v", err) } if m["username"] != "user\"with\\quotes" { t.Fatalf("unexpected value: %s", m["username"]) } }, }, { name: "unicode edge cases", pairs: []string{"username", "user\u2028line\u2029sep"}, verify: func(t *testing.T, result string) { var m map[string]string if err := json.Unmarshal([]byte(result), &m); err != nil { t.Fatalf("invalid JSON for unicode: %v", err) } if m["username"] != "user\u2028line\u2029sep" { t.Fatalf("unexpected value: %s", m["username"]) } }, }, { name: "null bytes in value", pairs: []string{"data", "before\x00after"}, verify: func(t *testing.T, result string) { var m map[string]string if err := json.Unmarshal([]byte(result), &m); err != nil { t.Fatalf("invalid JSON for null bytes: %v", err) } if m["data"] != "before\x00after" { t.Fatalf("unexpected value: %q", m["data"]) } }, }, { name: "odd number of args returns empty object", pairs: []string{"key"}, verify: func(t *testing.T, result string) { if result != "{}" { t.Fatalf("expected {}, got %s", result) } }, }, { name: "no args returns empty object", pairs: nil, verify: func(t *testing.T, result string) { if result != "{}" { t.Fatalf("expected {}, got %s", result) } }, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { result := JSON(tc.pairs...) tc.verify(t, result) }) } } func TestJSONWithRoles(t *testing.T) { tests := []struct { verify func(t *testing.T, result string) name string roles []string }{ { name: "multiple roles", roles: []string{"admin", "editor"}, verify: func(t *testing.T, result string) { var m map[string][]string if err := json.Unmarshal([]byte(result), &m); err != nil { t.Fatalf("invalid JSON: %v", err) } if len(m["roles"]) != 2 || m["roles"][0] != "admin" || m["roles"][1] != "editor" { t.Fatalf("unexpected roles: %v", m["roles"]) } }, }, { name: "empty roles", roles: []string{}, verify: func(t *testing.T, result string) { var m map[string][]string if err := json.Unmarshal([]byte(result), &m); err != nil { t.Fatalf("invalid JSON: %v", err) } if len(m["roles"]) != 0 { t.Fatalf("expected empty roles, got %v", m["roles"]) } }, }, { name: "roles with special characters", roles: []string{"role\"special"}, verify: func(t *testing.T, result string) { var m map[string][]string if err := json.Unmarshal([]byte(result), &m); err != nil { t.Fatalf("invalid JSON: %v", err) } if m["roles"][0] != "role\"special" { t.Fatalf("unexpected role: %s", m["roles"][0]) } }, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { result := JSONWithRoles(tc.roles) tc.verify(t, result) }) } }