TestErrorPropagation_TokenizerToParser tests that errors from the tokenizer propagate correctly with error codes intact through the parsing pipeline.
(t *testing.T)
| 25 | // TestErrorPropagation_TokenizerToParser tests that errors from the tokenizer |
| 26 | // propagate correctly with error codes intact through the parsing pipeline. |
| 27 | func TestErrorPropagation_TokenizerToParser(t *testing.T) { |
| 28 | tests := []struct { |
| 29 | name string |
| 30 | sql string |
| 31 | expectedCode errors.ErrorCode |
| 32 | expectedInMsg string |
| 33 | checkTokenizer bool // if true, we expect tokenizer to catch the error |
| 34 | }{ |
| 35 | { |
| 36 | name: "unterminated string literal", |
| 37 | sql: "SELECT * FROM users WHERE name = 'unterminated", |
| 38 | expectedCode: errors.ErrCodeUnterminatedString, |
| 39 | expectedInMsg: "unterminated", |
| 40 | }, |
| 41 | { |
| 42 | name: "unexpected token in SELECT", |
| 43 | sql: "SELECT * FROM", |
| 44 | expectedCode: errors.ErrCodeExpectedToken, // Expects table name after FROM |
| 45 | expectedInMsg: "expected", |
| 46 | }, |
| 47 | { |
| 48 | name: "incomplete SQL statement", |
| 49 | sql: "", |
| 50 | expectedCode: errors.ErrCodeIncompleteStatement, |
| 51 | expectedInMsg: "incomplete", |
| 52 | }, |
| 53 | { |
| 54 | name: "invalid syntax - missing table name", |
| 55 | sql: "INSERT INTO VALUES (1, 2)", |
| 56 | expectedCode: errors.ErrCodeExpectedToken, // Parser expects table name after INSERT INTO |
| 57 | expectedInMsg: "expected", |
| 58 | }, |
| 59 | { |
| 60 | name: "unexpected keyword usage", |
| 61 | sql: "SELECT FROM users", |
| 62 | expectedCode: errors.ErrCodeExpectedToken, |
| 63 | expectedInMsg: "expected", |
| 64 | }, |
| 65 | } |
| 66 | |
| 67 | for _, tt := range tests { |
| 68 | t.Run(tt.name, func(t *testing.T) { |
| 69 | // Get tokenizer from pool |
| 70 | tkz := tokenizer.GetTokenizer() |
| 71 | defer tokenizer.PutTokenizer(tkz) |
| 72 | |
| 73 | // Tokenize the input |
| 74 | tokens, tokenErr := tkz.Tokenize([]byte(tt.sql)) |
| 75 | |
| 76 | // If tokenizer caught an error with a code, verify it |
| 77 | if tokenErr != nil { |
| 78 | if err, ok := tokenErr.(*errors.Error); ok { |
| 79 | if err.Code != "" { |
| 80 | t.Logf("Tokenizer caught error with code: %s", err.Code) |
| 81 | // Verify the error code is what we expected |
| 82 | if tt.checkTokenizer && err.Code != tt.expectedCode { |
| 83 | t.Errorf("Tokenizer error code mismatch: expected %s, got %s", tt.expectedCode, err.Code) |
| 84 | } |
nothing calls this directly
no test coverage detected