TestTokenizer_InputSizeLimit tests the DoS protection for maximum input size
(t *testing.T)
| 24 | |
| 25 | // TestTokenizer_InputSizeLimit tests the DoS protection for maximum input size |
| 26 | func TestTokenizer_InputSizeLimit(t *testing.T) { |
| 27 | tokenizer, err := New() |
| 28 | if err != nil { |
| 29 | t.Fatalf("New() error = %v", err) |
| 30 | } |
| 31 | |
| 32 | t.Run("ValidLargeInput", func(t *testing.T) { |
| 33 | // Test with a moderately large but valid input (5KB - large enough to demonstrate |
| 34 | // protection works, but small enough to complete quickly with race detection) |
| 35 | // Note: 100KB test was too slow with -race (10+ minutes), reduced to 5KB for CI |
| 36 | pattern := []byte("SELECT * FROM users WHERE id = 1; ") |
| 37 | input := make([]byte, 5*1024) // 5KB |
| 38 | for i := 0; i < len(input); i++ { |
| 39 | input[i] = pattern[i%len(pattern)] |
| 40 | } |
| 41 | |
| 42 | tokens, err := tokenizer.Tokenize(input) |
| 43 | if err != nil { |
| 44 | t.Errorf("Tokenize() should succeed for valid large input, got error: %v", err) |
| 45 | } |
| 46 | if tokens == nil { |
| 47 | t.Error("Tokenize() should return tokens for valid large input") |
| 48 | } |
| 49 | t.Logf("Successfully tokenized %d bytes into %d tokens", len(input), len(tokens)) |
| 50 | }) |
| 51 | |
| 52 | t.Run("JustOverLimit", func(t *testing.T) { |
| 53 | // Create input just over the limit (10MB + 1 byte) |
| 54 | input := make([]byte, MaxInputSize+1) |
| 55 | copy(input, []byte("SELECT * FROM users")) |
| 56 | |
| 57 | _, err := tokenizer.Tokenize(input) |
| 58 | if err == nil { |
| 59 | t.Fatal("Tokenize() should fail just over limit") |
| 60 | } |
| 61 | |
| 62 | // Check for structured error with correct code |
| 63 | if !errors.IsCode(err, errors.ErrCodeInputTooLarge) { |
| 64 | t.Fatalf("expected ErrCodeInputTooLarge, got %T with error: %v", err, err) |
| 65 | } |
| 66 | |
| 67 | // Verify error message contains expected information |
| 68 | if !strings.Contains(err.Error(), "input size") || !strings.Contains(err.Error(), "exceeds limit") { |
| 69 | t.Errorf("wrong error message, got %q", err.Error()) |
| 70 | } |
| 71 | t.Logf("Correctly rejected oversized input: %d bytes", len(input)) |
| 72 | }) |
| 73 | |
| 74 | t.Run("VeryLargeInput", func(t *testing.T) { |
| 75 | // Create a very large input (20MB) to test fail-fast behavior |
| 76 | input := make([]byte, MaxInputSize*2) |
| 77 | copy(input, []byte("SELECT * FROM users")) |
| 78 | |
| 79 | _, err := tokenizer.Tokenize(input) |
| 80 | if err == nil { |
| 81 | t.Fatal("Tokenize() should fail for very large input") |
| 82 | } |
| 83 |