package fuzz import ( "encoding/json" "fmt" "net/http" "net/http/httptest" "net/url" "strings" "testing" "unicode/utf8" ) func TestNewFuzzTestHelper(t *testing.T) { helper := NewFuzzTestHelper() if helper == nil { t.Fatal("NewFuzzTestHelper returned nil") } } func TestRunBasicFuzzTest(t *testing.T) { helper := NewFuzzTestHelper() if helper == nil { t.Fatal("helper should not be nil") } } func TestRunValidationFuzzTest(t *testing.T) { helper := NewFuzzTestHelper() if helper == nil { t.Fatal("helper should not be nil") } validateFunc := func(input string) error { if len(input) > 100 { return fmt.Errorf("input too long") } return nil } err := validateFunc("test") if err != nil { t.Errorf("short input should not error: %v", err) } } func TestRunSanitizationFuzzTest(t *testing.T) { helper := NewFuzzTestHelper() if helper == nil { t.Fatal("helper should not be nil") } sanitizeFunc := func(input string) string { result := "" for _, char := range input { if char != ' ' { result += string(char) } } return result } result := sanitizeFunc("hello world") if result != "helloworld" { t.Errorf("expected 'helloworld', got '%s'", result) } } func TestRunSanitizationFuzzTestWithValidation(t *testing.T) { helper := NewFuzzTestHelper() if helper == nil { t.Fatal("helper should not be nil") } sanitizeFunc := func(input string) string { result := "" for _, char := range input { if char != ' ' { result += string(char) } } return result } validateFunc := func(input string) bool { return len(input) > 0 } result := sanitizeFunc("hello world") if !validateFunc(result) { t.Error("validation should pass for non-empty result") } } func TestRunJSONFuzzTest(t *testing.T) { helper := NewFuzzTestHelper() if helper == nil { t.Fatal("helper should not be nil") } testCases := []map[string]any{ { "body": `{"username":"FUZZED_INPUT","email":"test@example.com"}`, }, { "body": `{"title":"FUZZED_INPUT","content":"test"}`, }, } if len(testCases) != 2 { t.Errorf("expected 2 test cases, got %d", len(testCases)) } } func TestRunHTTPFuzzTest(t *testing.T) { helper := NewFuzzTestHelper() if helper == nil { t.Fatal("helper should not be nil") } testCases := []HTTPFuzzTestCase{ { Name: "test_request", Method: "GET", URL: "/api/test?param=FUZZED_INPUT", Headers: map[string]string{ "Content-Type": "application/json", }, Body: "", }, } if len(testCases) != 1 { t.Errorf("expected 1 test case, got %d", len(testCases)) } if testCases[0].Method != "GET" { t.Errorf("expected GET method, got %s", testCases[0].Method) } } func TestRunIntegrationFuzzTest(t *testing.T) { helper := NewFuzzTestHelper() if helper == nil { t.Fatal("helper should not be nil") } } func TestSanitizeForURL(t *testing.T) { helper := NewFuzzTestHelper() testCases := []struct { input string expected string }{ {"hello world", "hello%20world"}, {"test\nwith\nnewlines", "testwithnewlines"}, {"test&with=special?chars#here", "test%26with%3Dspecial%3Fchars%23here"}, {"", ""}, {"a very long string that should be truncated because it exceeds the maximum length allowed for URLs in this test case", "a%20very%20long%20string%20that%20should%20be%20truncated%20because%20it%20exceeds%20the%20maximum%20length%20allowed%20for%20URLs%20in%20this%20test%20case"}, } for _, tc := range testCases { result := helper.sanitizeForURL(tc.input) if len(result) > 100 { t.Errorf("Sanitized URL too long: %d characters", len(result)) } } } func TestGetCommonAuthTestCases(t *testing.T) { helper := NewFuzzTestHelper() testCases := helper.GetCommonAuthTestCases("test_input") if len(testCases) == 0 { t.Fatal("GetCommonAuthTestCases returned empty slice") } for _, tc := range testCases { if tc.Name == "" { t.Error("Test case name is empty") } if tc.Method == "" { t.Error("Test case method is empty") } if tc.URL == "" { t.Error("Test case URL is empty") } } } func TestGetCommonPostTestCases(t *testing.T) { helper := NewFuzzTestHelper() testCases := helper.GetCommonPostTestCases("test_input") if len(testCases) == 0 { t.Fatal("GetCommonPostTestCases returned empty slice") } for _, tc := range testCases { if tc.Name == "" { t.Error("Test case name is empty") } if tc.Method == "" { t.Error("Test case method is empty") } if tc.URL == "" { t.Error("Test case URL is empty") } } } func TestGetCommonVoteTestCases(t *testing.T) { helper := NewFuzzTestHelper() testCases := helper.GetCommonVoteTestCases("test_input") if len(testCases) == 0 { t.Fatal("GetCommonVoteTestCases returned empty slice") } for _, tc := range testCases { if tc.Name == "" { t.Error("Test case name is empty") } if tc.Method == "" { t.Error("Test case method is empty") } if tc.URL == "" { t.Error("Test case URL is empty") } } } func TestHTTPFuzzTestCaseStructure(t *testing.T) { tc := HTTPFuzzTestCase{ Name: "test_case", Method: "GET", URL: "/api/test", Headers: map[string]string{ "Content-Type": "application/json", }, Body: "test body", } if tc.Name != "test_case" { t.Error("Name field not set correctly") } if tc.Method != "GET" { t.Error("Method field not set correctly") } if tc.URL != "/api/test" { t.Error("URL field not set correctly") } if tc.Headers["Content-Type"] != "application/json" { t.Error("Headers field not set correctly") } if tc.Body != "test body" { t.Error("Body field not set correctly") } } func TestRunBasicFuzzTestLogic(t *testing.T) { testFunc := func(t *testing.T, input string) { if !utf8.ValidString(input) { t.Fatal("Input should be valid UTF-8") } } testFunc(t, "valid input") testFunc(t, "测试中文") testFunc(t, "🚀 emoji test") } func TestRunValidationFuzzTestLogic(t *testing.T) { validateFunc := func(input string) error { if len(input) > 100 { return fmt.Errorf("input too long") } return nil } err := validateFunc("short input") if err != nil { t.Errorf("Expected no error for short input, got: %v", err) } err = validateFunc(strings.Repeat("a", 150)) if err == nil { t.Error("Expected error for long input") } } func TestRunSanitizationFuzzTestLogic(t *testing.T) { sanitizeFunc := func(input string) string { result := strings.ReplaceAll(input, " ", "") result = strings.ReplaceAll(result, "\n", "") result = strings.ReplaceAll(result, "\r", "") return result } testCases := []struct { input string expected string }{ {"hello world", "helloworld"}, {"test\nwith\nnewlines", "testwithnewlines"}, {"", ""}, {"🚀 test emoji", "🚀testemoji"}, } for _, tc := range testCases { result := sanitizeFunc(tc.input) if result != tc.expected { t.Errorf("Expected '%s', got '%s'", tc.expected, result) } if !utf8.ValidString(result) { t.Errorf("Sanitized result contains invalid UTF-8: %s", result) } } } func TestRunSanitizationFuzzTestWithValidationLogic(t *testing.T) { sanitizeFunc := func(input string) string { return strings.TrimSpace(input) } validateFunc := func(input string) bool { return len(input) > 0 } testCases := []struct { input string shouldPass bool }{ {" valid input ", true}, {"", false}, {" ", false}, {"test", true}, } for _, tc := range testCases { result := sanitizeFunc(tc.input) valid := validateFunc(result) if valid != tc.shouldPass { t.Errorf("For input '%s', expected validation %v, got %v", tc.input, tc.shouldPass, valid) } } } func TestRunJSONFuzzTestLogic(t *testing.T) { testCases := []map[string]any{ { "body": `{"username":"FUZZED_INPUT","email":"test@example.com"}`, }, { "body": `{"title":"FUZZED_INPUT","content":"test"}`, }, } for _, tc := range testCases { body, ok := tc["body"].(string) if !ok { t.Error("Expected body to be string") continue } replaced := strings.ReplaceAll(body, "FUZZED_INPUT", "test_input") if strings.Contains(replaced, "FUZZED_INPUT") { t.Error("FUZZED_INPUT should be replaced") } var result map[string]any err := json.Unmarshal([]byte(replaced), &result) if err != nil { t.Errorf("Expected valid JSON, got error: %v", err) } } } func TestRunHTTPFuzzTestLogic(t *testing.T) { helper := NewFuzzTestHelper() testCases := []HTTPFuzzTestCase{ { Name: "test_request", Method: "GET", URL: "/api/test?param=FUZZED_INPUT", Headers: map[string]string{ "Content-Type": "application/json", }, Body: "", }, { Name: "post_request", Method: "POST", URL: "/api/posts", Headers: map[string]string{ "Content-Type": "application/json", }, Body: `{"title":"FUZZED_INPUT","content":"test"}`, }, } for _, tc := range testCases { sanitized := helper.sanitizeForURL("test input with spaces") url := strings.ReplaceAll(tc.URL, "FUZZED_INPUT", sanitized) body := strings.ReplaceAll(tc.Body, "FUZZED_INPUT", sanitized) req := httptest.NewRequest(tc.Method, url, strings.NewReader(body)) for name, value := range tc.Headers { req.Header.Set(name, value) } helper.validateHTTPRequest(t, req) } } func TestValidateHTTPRequest(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?param=value", nil) req.Header.Set("Content-Type", "application/json") helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithInvalidUTF8(t *testing.T) { helper := NewFuzzTestHelper() req := &http.Request{ Method: "GET", URL: &url.URL{Path: "/api/test"}, Header: make(http.Header), } req.URL.RawQuery = "param=test%20value" req.Header.Set("Content-Type", "application/json") helper.validateHTTPRequest(t, req) } func TestRunIntegrationFuzzTestLogic(t *testing.T) { testFunc := func(t *testing.T, input string) { if len(input) > 1000 { t.Fatal("Input should be limited to 1000 characters") } } testFunc(t, "short input") longInput := strings.Repeat("a", 2000) if len(longInput) > 1000 { longInput = longInput[:1000] } testFunc(t, longInput) } func TestSanitizeForURLEdgeCases(t *testing.T) { helper := NewFuzzTestHelper() testCases := []struct { input string maxLen int expectedMaxLen int }{ {"", 100, 0}, {"short", 100, 5}, {strings.Repeat("a", 50), 100, 50}, {strings.Repeat("a", 150), 100, 100}, {"test with spaces", 100, 100}, {"test\nwith\nnewlines", 100, 100}, {"test&with=special?chars#here", 100, 100}, } for _, tc := range testCases { result := helper.sanitizeForURL(tc.input) if len(result) > tc.expectedMaxLen { t.Errorf("Expected max length %d, got %d for input '%s'", tc.expectedMaxLen, len(result), tc.input) } if !utf8.ValidString(result) { t.Errorf("Sanitized URL contains invalid UTF-8: %s", result) } } } func TestGetCommonAuthTestCasesWithInput(t *testing.T) { helper := NewFuzzTestHelper() inputs := []string{"", "test", "test@example.com", "very_long_username_that_might_cause_issues"} for _, input := range inputs { testCases := helper.GetCommonAuthTestCases(input) if len(testCases) == 0 { t.Fatal("GetCommonAuthTestCases returned empty slice") } for _, tc := range testCases { if tc.Name == "" { t.Error("Test case name is empty") } if tc.Method == "" { t.Error("Test case method is empty") } if tc.URL == "" { t.Error("Test case URL is empty") } } } } func TestGetCommonPostTestCasesWithInput(t *testing.T) { helper := NewFuzzTestHelper() inputs := []string{"", "test", "test title", "very_long_title_that_might_cause_issues"} for _, input := range inputs { testCases := helper.GetCommonPostTestCases(input) if len(testCases) == 0 { t.Fatal("GetCommonPostTestCases returned empty slice") } for _, tc := range testCases { if tc.Name == "" { t.Error("Test case name is empty") } if tc.Method == "" { t.Error("Test case method is empty") } if tc.URL == "" { t.Error("Test case URL is empty") } } } } func TestGetCommonVoteTestCasesWithInput(t *testing.T) { helper := NewFuzzTestHelper() inputs := []string{"", "up", "down", "invalid_vote_type"} for _, input := range inputs { testCases := helper.GetCommonVoteTestCases(input) if len(testCases) == 0 { t.Fatal("GetCommonVoteTestCases returned empty slice") } for _, tc := range testCases { if tc.Name == "" { t.Error("Test case name is empty") } if tc.Method == "" { t.Error("Test case method is empty") } if tc.URL == "" { t.Error("Test case URL is empty") } } } } func TestHTTPFuzzTestCaseEdgeCases(t *testing.T) { tc := HTTPFuzzTestCase{ Name: "", Method: "", URL: "", Headers: nil, Body: "", } if tc.Name != "" { t.Error("Empty name should be preserved") } if tc.Method != "" { t.Error("Empty method should be preserved") } if tc.URL != "" { t.Error("Empty URL should be preserved") } if tc.Headers != nil { t.Error("Nil headers should be preserved") } if tc.Body != "" { t.Error("Empty body should be preserved") } tc.Headers = make(map[string]string) if tc.Headers == nil { t.Error("Headers should not be nil after initialization") } } func TestFuzzTestHelperMethodsWithNilInput(t *testing.T) { helper := NewFuzzTestHelper() result := helper.sanitizeForURL("") if result != "" { t.Errorf("Expected empty string, got '%s'", result) } result = helper.sanitizeForURL(" \n\t\r ") if result == "" { t.Error("Whitespace should be sanitized but not completely removed") } } func TestValidateHTTPRequestWithComplexQuery(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?param1=value1¶m2=value2¶m3=value%20with%20spaces", nil) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer token123") helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmptyHeaders(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithSpecialCharacters(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test-path?param=value%20with%20spaces&special=chars%26symbols", nil) req.Header.Set("Content-Type", "application/json") req.Header.Set("User-Agent", "Test-Agent/1.0") helper.validateHTTPRequest(t, req) } func TestSanitizeForURLWithSpecialCharacters(t *testing.T) { helper := NewFuzzTestHelper() testCases := []struct { input string contains string }{ {"test with spaces", "%20"}, {"test\nwith\nnewlines", ""}, {"test&with=special?chars#here", "%26"}, {"test/with/slashes", "%2F"}, {"test\\with\\backslashes", "%5C"}, {"test with unicode 🚀", "%F0%9F%9A%80"}, } for _, tc := range testCases { result := helper.sanitizeForURL(tc.input) if !utf8.ValidString(result) { t.Errorf("Sanitized URL contains invalid UTF-8: %s", result) } if len(result) > 100 { t.Errorf("Sanitized URL too long: %d characters", len(result)) } if tc.contains != "" && !strings.Contains(result, tc.contains) { t.Errorf("Expected result to contain '%s', got '%s'", tc.contains, result) } } } func TestSanitizeForURLWithLongInput(t *testing.T) { helper := NewFuzzTestHelper() longInput := strings.Repeat("a", 200) result := helper.sanitizeForURL(longInput) if len(result) > 100 { t.Errorf("Expected max 100 characters, got %d", len(result)) } if !utf8.ValidString(result) { t.Errorf("Sanitized URL contains invalid UTF-8: %s", result) } } func TestHTTPFuzzTestCaseWithNilHeaders(t *testing.T) { tc := HTTPFuzzTestCase{ Name: "test_case", Method: "GET", URL: "/api/test", Headers: nil, Body: "test body", } if tc.Headers != nil { t.Error("Headers should be nil") } tc.Headers = make(map[string]string) tc.Headers["Content-Type"] = "application/json" if tc.Headers["Content-Type"] != "application/json" { t.Error("Headers not set correctly") } } func TestGetCommonTestCasesConsistency(t *testing.T) { helper := NewFuzzTestHelper() authCases := helper.GetCommonAuthTestCases("test") if len(authCases) != 2 { t.Errorf("Expected 2 auth test cases, got %d", len(authCases)) } postCases := helper.GetCommonPostTestCases("test") if len(postCases) != 2 { t.Errorf("Expected 2 post test cases, got %d", len(postCases)) } voteCases := helper.GetCommonVoteTestCases("test") if len(voteCases) != 1 { t.Errorf("Expected 1 vote test case, got %d", len(voteCases)) } } func TestValidateHTTPRequestWithInvalidPath(t *testing.T) { helper := NewFuzzTestHelper() req := &http.Request{ Method: "GET", URL: &url.URL{Path: "/api/test"}, Header: make(http.Header), } helper.validateHTTPRequest(t, req) req.URL.Path = "" helper.validateHTTPRequest(t, req) req.URL.Path = "/" helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithComplexHeaders(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer token123") req.Header.Set("User-Agent", "Test-Agent/1.0") req.Header.Set("X-Custom-Header", "custom-value") req.Header.Set("Accept", "application/json, text/plain, */*") helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmptyQuery(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) req.URL.RawQuery = "" helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithSingleQueryParam(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?param=value", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithMultipleQueryParams(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?param1=value1¶m2=value2¶m3=value3", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmptyValues(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?param1=¶m2=value¶m3=", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithDuplicateQueryParams(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?param=value1¶m=value2¶m=value3", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmptyHeaderValues(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) req.Header.Set("Empty-Header", "") req.Header.Set("Another-Header", "value") helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithMultipleHeaderValues(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) req.Header.Add("Multi-Value-Header", "value1") req.Header.Add("Multi-Value-Header", "value2") req.Header.Add("Multi-Value-Header", "value3") helper.validateHTTPRequest(t, req) } func TestSanitizeForURLWithEmptyString(t *testing.T) { helper := NewFuzzTestHelper() result := helper.sanitizeForURL("") if result != "" { t.Errorf("Expected empty string, got '%s'", result) } } func TestSanitizeForURLWithOnlyWhitespace(t *testing.T) { helper := NewFuzzTestHelper() testCases := []string{ " ", "\n", "\r", "\t", " ", "\n\n\n", "\r\r\r", "\t\t\t", " \n\r\t ", } for _, input := range testCases { result := helper.sanitizeForURL(input) if len(result) > 0 && !strings.Contains(result, "%20") && !strings.Contains(result, "%0A") && !strings.Contains(result, "%0D") && !strings.Contains(result, "%09") { t.Errorf("Unexpected result for input '%s': '%s'", input, result) } } } func TestSanitizeForURLWithUnicodeCharacters(t *testing.T) { helper := NewFuzzTestHelper() testCases := []string{ "🚀", "测试", "café", "naïve", "résumé", "测试中文", "🚀🚀🚀", "test🚀test", } for _, input := range testCases { result := helper.sanitizeForURL(input) if !utf8.ValidString(result) { t.Errorf("Result contains invalid UTF-8 for input '%s': '%s'", input, result) } if len(result) > 100 { t.Errorf("Result too long for input '%s': %d characters", input, len(result)) } } } func TestSanitizeForURLWithControlCharacters(t *testing.T) { helper := NewFuzzTestHelper() testCases := []string{ "test\x00null", "test\x01control", "test\x1funit_separator", "test\x7fdelete", "test\x80high_bit", "test\xffmax_byte", } for _, input := range testCases { result := helper.sanitizeForURL(input) if len(result) > 100 { t.Errorf("Result too long for input '%s': %d characters", input, len(result)) } } } func TestSanitizeForURLWithExactLengthLimit(t *testing.T) { helper := NewFuzzTestHelper() input := strings.Repeat("a", 100) result := helper.sanitizeForURL(input) if len(result) != 100 { t.Errorf("Expected length 100, got %d for input of length 100", len(result)) } if result != input { t.Errorf("Expected unchanged input, got '%s'", result) } } func TestSanitizeForURLWithJustOverLengthLimit(t *testing.T) { helper := NewFuzzTestHelper() input := strings.Repeat("a", 101) result := helper.sanitizeForURL(input) if len(result) != 100 { t.Errorf("Expected length 100, got %d for input of length 101", len(result)) } expected := strings.Repeat("a", 100) if result != expected { t.Errorf("Expected '%s', got '%s'", expected, result) } } func TestSanitizeForURLWithMixedSpecialCharacters(t *testing.T) { helper := NewFuzzTestHelper() input := "test with spaces & symbols = values ? query # fragment / path \\ backslash" result := helper.sanitizeForURL(input) if !utf8.ValidString(result) { t.Errorf("Result contains invalid UTF-8: '%s'", result) } if len(result) > 100 { t.Errorf("Result too long: %d characters", len(result)) } expectedEncodings := []string{"%20", "%26", "%3D", "%3F", "%23", "%2F"} for _, encoding := range expectedEncodings { if !strings.Contains(result, encoding) { t.Errorf("Expected result to contain '%s', got '%s'", encoding, result) } } if strings.Contains(result, "%5C") { } else if strings.Contains(result, "%5") { t.Logf("Backslash encoding may be truncated due to length limit: '%s'", result) } } func TestRunJSONFuzzTestWithInvalidJSON(t *testing.T) { testCases := []map[string]any{ { "body": `{"username":"FUZZED_INPUT","email":"test@example.com"`, }, { "body": `{"title":"FUZZED_INPUT","content":"test"`, }, { "body": `invalid json`, }, { "body": `{"username":"FUZZED_INPUT","email":}`, }, } for _, tc := range testCases { body, ok := tc["body"].(string) if !ok { t.Error("Expected body to be string") continue } replaced := strings.ReplaceAll(body, "FUZZED_INPUT", "test_input") if strings.Contains(replaced, "FUZZED_INPUT") { t.Error("FUZZED_INPUT should be replaced") } var result map[string]any err := json.Unmarshal([]byte(replaced), &result) if err == nil { t.Errorf("Expected JSON parsing error for invalid JSON: %s", replaced) } } } func TestRunJSONFuzzTestWithValidJSON(t *testing.T) { testCases := []map[string]any{ { "body": `{"username":"FUZZED_INPUT","email":"test@example.com"}`, }, { "body": `{"title":"FUZZED_INPUT","content":"test"}`, }, { "body": `{"id":123,"name":"FUZZED_INPUT","active":true}`, }, { "body": `{"data":{"value":"FUZZED_INPUT","count":42}}`, }, } for _, tc := range testCases { body, ok := tc["body"].(string) if !ok { t.Error("Expected body to be string") continue } replaced := strings.ReplaceAll(body, "FUZZED_INPUT", "test_input") if strings.Contains(replaced, "FUZZED_INPUT") { t.Error("FUZZED_INPUT should be replaced") } var result map[string]any err := json.Unmarshal([]byte(replaced), &result) if err != nil { t.Errorf("Expected valid JSON, got error: %v", err) } } } func TestRunJSONFuzzTestWithEmptyBody(t *testing.T) { testCases := []map[string]any{ { "body": "", }, { "body": "{}", }, { "body": "null", }, } for _, tc := range testCases { body, ok := tc["body"].(string) if !ok { t.Error("Expected body to be string") continue } replaced := strings.ReplaceAll(body, "FUZZED_INPUT", "test_input") if strings.Contains(replaced, "FUZZED_INPUT") { t.Error("FUZZED_INPUT should be replaced") } var result map[string]any err := json.Unmarshal([]byte(replaced), &result) if body == "" && err == nil { t.Error("Expected JSON parsing error for empty string") } else if body != "" && err != nil { t.Errorf("Expected valid JSON, got error: %v", err) } } } func TestRunJSONFuzzTestWithNonStringBody(t *testing.T) { testCases := []map[string]any{ { "body": 123, }, { "body": true, }, { "body": nil, }, { "body": []string{"test"}, }, } for _, tc := range testCases { _, ok := tc["body"].(string) if ok { t.Error("Expected body to not be string") } } } func TestRunHTTPFuzzTestWithEmptyTestCases(t *testing.T) { testCases := []HTTPFuzzTestCase{} for _, tc := range testCases { _ = tc } } func TestRunHTTPFuzzTestWithNilHeaders(t *testing.T) { helper := NewFuzzTestHelper() testCases := []HTTPFuzzTestCase{ { Name: "test_request", Method: "GET", URL: "/api/test?param=FUZZED_INPUT", Headers: nil, Body: "", }, } for _, tc := range testCases { sanitized := helper.sanitizeForURL("test input") url := strings.ReplaceAll(tc.URL, "FUZZED_INPUT", sanitized) body := strings.ReplaceAll(tc.Body, "FUZZED_INPUT", sanitized) req := httptest.NewRequest(tc.Method, url, strings.NewReader(body)) if tc.Headers != nil { for name, value := range tc.Headers { req.Header.Set(name, value) } } helper.validateHTTPRequest(t, req) } } func TestRunHTTPFuzzTestWithEmptyHeaders(t *testing.T) { helper := NewFuzzTestHelper() testCases := []HTTPFuzzTestCase{ { Name: "test_request", Method: "GET", URL: "/api/test?param=FUZZED_INPUT", Headers: make(map[string]string), Body: "", }, } for _, tc := range testCases { sanitized := helper.sanitizeForURL("test input") url := strings.ReplaceAll(tc.URL, "FUZZED_INPUT", sanitized) body := strings.ReplaceAll(tc.Body, "FUZZED_INPUT", sanitized) req := httptest.NewRequest(tc.Method, url, strings.NewReader(body)) for name, value := range tc.Headers { req.Header.Set(name, value) } helper.validateHTTPRequest(t, req) } } func TestRunHTTPFuzzTestWithDifferentMethods(t *testing.T) { helper := NewFuzzTestHelper() testCases := []HTTPFuzzTestCase{ { Name: "get_request", Method: "GET", URL: "/api/test?param=FUZZED_INPUT", Headers: map[string]string{"Content-Type": "application/json"}, Body: "", }, { Name: "post_request", Method: "POST", URL: "/api/test", Headers: map[string]string{"Content-Type": "application/json"}, Body: `{"param":"FUZZED_INPUT"}`, }, { Name: "put_request", Method: "PUT", URL: "/api/test", Headers: map[string]string{"Content-Type": "application/json"}, Body: `{"param":"FUZZED_INPUT"}`, }, { Name: "delete_request", Method: "DELETE", URL: "/api/test?param=FUZZED_INPUT", Headers: map[string]string{"Content-Type": "application/json"}, Body: "", }, { Name: "patch_request", Method: "PATCH", URL: "/api/test", Headers: map[string]string{"Content-Type": "application/json"}, Body: `{"param":"FUZZED_INPUT"}`, }, } for _, tc := range testCases { sanitized := helper.sanitizeForURL("test input") url := strings.ReplaceAll(tc.URL, "FUZZED_INPUT", sanitized) body := strings.ReplaceAll(tc.Body, "FUZZED_INPUT", sanitized) req := httptest.NewRequest(tc.Method, url, strings.NewReader(body)) for name, value := range tc.Headers { req.Header.Set(name, value) } helper.validateHTTPRequest(t, req) } } func TestRunHTTPFuzzTestWithComplexURLs(t *testing.T) { helper := NewFuzzTestHelper() testCases := []HTTPFuzzTestCase{ { Name: "complex_query", Method: "GET", URL: "/api/test?param1=FUZZED_INPUT¶m2=value2¶m3=value3", Headers: map[string]string{"Content-Type": "application/json"}, Body: "", }, { Name: "path_with_params", Method: "GET", URL: "/api/posts/123/comments?filter=FUZZED_INPUT&sort=date", Headers: map[string]string{"Content-Type": "application/json"}, Body: "", }, { Name: "nested_path", Method: "GET", URL: "/api/v1/users/123/posts/456/votes?type=FUZZED_INPUT", Headers: map[string]string{"Content-Type": "application/json"}, Body: "", }, } for _, tc := range testCases { sanitized := helper.sanitizeForURL("test input with spaces & symbols") url := strings.ReplaceAll(tc.URL, "FUZZED_INPUT", sanitized) body := strings.ReplaceAll(tc.Body, "FUZZED_INPUT", sanitized) req := httptest.NewRequest(tc.Method, url, strings.NewReader(body)) for name, value := range tc.Headers { req.Header.Set(name, value) } helper.validateHTTPRequest(t, req) } } func TestRunIntegrationFuzzTestWithLongInput(t *testing.T) { testFunc := func(t *testing.T, input string) { if len(input) > 1000 { t.Fatal("Input should be limited to 1000 characters") } } testCases := []struct { input string expected bool }{ {"short", true}, {strings.Repeat("a", 500), true}, {strings.Repeat("a", 1000), true}, {strings.Repeat("a", 1500), false}, {strings.Repeat("a", 2000), false}, } for _, tc := range testCases { input := tc.input if len(input) > 1000 { input = input[:1000] } testFunc(t, input) } } func TestRunIntegrationFuzzTestWithUnicodeInput(t *testing.T) { testFunc := func(t *testing.T, input string) { if !utf8.ValidString(input) { t.Fatal("Input should be valid UTF-8") } if len(input) > 1000 { t.Fatal("Input should be limited to 1000 characters") } } testCases := []string{ "测试中文", "🚀 emoji test", "café naïve résumé", "测试🚀emoji测试", strings.Repeat("🚀", 100), strings.Repeat("测试", 200), } for _, input := range testCases { limitedInput := input if len(limitedInput) > 1000 { limitedInput = limitedInput[:1000] } if utf8.ValidString(limitedInput) { testFunc(t, limitedInput) } else { t.Logf("Input truncated to invalid UTF-8 (expected): %s", limitedInput) } } } func TestRunIntegrationFuzzTestWithEmptyInput(t *testing.T) { testFunc := func(t *testing.T, input string) { if len(input) > 1000 { t.Fatal("Input should be limited to 1000 characters") } } testFunc(t, "") } func TestRunIntegrationFuzzTestWithControlCharacters(t *testing.T) { testFunc := func(t *testing.T, input string) { if !utf8.ValidString(input) { t.Fatal("Input should be valid UTF-8") } if len(input) > 1000 { t.Fatal("Input should be limited to 1000 characters") } } testCases := []string{ "test\x00null", "test\x01control", "test\x1funit_separator", "test\x7fdelete", "test\x80high_bit", "test\xffmax_byte", } for _, input := range testCases { limitedInput := input if len(limitedInput) > 1000 { limitedInput = limitedInput[:1000] } if utf8.ValidString(limitedInput) { testFunc(t, limitedInput) } } } func TestValidateHTTPRequestWithNilURL(t *testing.T) { helper := NewFuzzTestHelper() req := &http.Request{ Method: "GET", URL: nil, Header: make(http.Header), } defer func() { if r := recover(); r != nil { t.Logf("Expected panic due to nil URL: %v", r) } }() helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmptyPath(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/", nil) req.URL.Path = "" helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithRootPath(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithSinglePathSegment(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithMultiplePathSegments(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/v1/users/123/posts", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmptyPathSegments(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api//users//123", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithTrailingSlash(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/users/", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithLeadingSlash(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/users", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithNoSlash(t *testing.T) { helper := NewFuzzTestHelper() req := &http.Request{ Method: "GET", URL: &url.URL{Path: "api/users"}, Header: make(http.Header), } helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithOnlySlash(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithComplexPath(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/v1/users/123/posts/456/comments/789", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithUnicodePath(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/测试/用户", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmojiPath(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/🚀/test", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithSpecialCharactersInPath(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test-path_with.underscores~and~tildes", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithNumbersInPath(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/v1/users/123/posts/456", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithMixedCasePath(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/Users/Posts/Comments", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithLongPath(t *testing.T) { helper := NewFuzzTestHelper() longPath := "/api/" + strings.Repeat("very-long-path-segment/", 20) req := httptest.NewRequest("GET", longPath, nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmptyQueryString(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithOnlyQuestionMark(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithAmpersandOnly(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?&", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEqualsOnly(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?=", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithMultipleEquals(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?param=value=another", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithUnicodeQueryParam(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?param=测试&value=用户", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmojiQueryParam(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?param=🚀&value=test", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithSpecialCharactersInQuery(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test?param=value+with+spaces&other=value%20encoded", nil) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmptyHeaderName(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) req.Header.Set("", "value") helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmptyHeaderValue(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) req.Header.Set("Test-Header", "") helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithUnicodeHeader(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) req.Header.Set("测试-Header", "测试-Value") helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithEmojiHeader(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) req.Header.Set("🚀-Header", "🚀-Value") helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithSpecialCharactersInHeader(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) req.Header.Set("Test-Header-With-Special-Chars", "value with spaces & symbols") helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithLongHeader(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) longValue := strings.Repeat("very-long-header-value-", 50) req.Header.Set("Long-Header", longValue) helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithManyHeaders(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) for i := 0; i < 20; i++ { req.Header.Set(fmt.Sprintf("Header-%d", i), fmt.Sprintf("Value-%d", i)) } helper.validateHTTPRequest(t, req) } func TestValidateHTTPRequestWithMixedCaseHeaders(t *testing.T) { helper := NewFuzzTestHelper() req := httptest.NewRequest("GET", "/api/test", nil) req.Header.Set("Content-Type", "application/json") req.Header.Set("content-type", "text/plain") req.Header.Set("CONTENT-TYPE", "application/xml") helper.validateHTTPRequest(t, req) } func TestGetFuzzDB(t *testing.T) { db, err := GetFuzzDB() if err != nil { t.Fatalf("GetFuzzDB failed: %v", err) } if db == nil { t.Fatal("GetFuzzDB returned nil database") } db2, err2 := GetFuzzDB() if err2 != nil { t.Fatalf("Second GetFuzzDB call failed: %v", err2) } if db2 != db { t.Fatal("GetFuzzDB should return the same database instance") } } func TestGetFuzzDBMigrations(t *testing.T) { db, err := GetFuzzDB() if err != nil { t.Fatalf("GetFuzzDB failed: %v", err) } var count int64 db.Table("users").Count(&count) db.Table("posts").Count(&count) db.Table("votes").Count(&count) db.Table("account_deletion_requests").Count(&count) db.Table("refresh_tokens").Count(&count) }