| 846 | } |
| 847 | |
| 848 | func TestStatusErrorEdgeCases(t *testing.T) { |
| 849 | t.Parallel() |
| 850 | |
| 851 | t.Run("empty JSON object falls back to underlying", func(t *testing.T) { |
| 852 | t.Parallel() |
| 853 | inner := errors.New(`POST "/v1/x": 400 Bad Request {}`) |
| 854 | se := &StatusError{StatusCode: 400, Err: inner} |
| 855 | assert.Equal(t, `HTTP 400: POST "/v1/x": 400 Bad Request {}`, se.Error()) |
| 856 | }) |
| 857 | |
| 858 | t.Run("malformed JSON falls back to underlying", func(t *testing.T) { |
| 859 | t.Parallel() |
| 860 | inner := errors.New(`POST "/v1/x": 400 Bad Request {"error":{"message":"test"`) |
| 861 | se := &StatusError{StatusCode: 400, Err: inner} |
| 862 | assert.Equal(t, `HTTP 400: POST "/v1/x": 400 Bad Request {"error":{"message":"test"`, se.Error()) |
| 863 | }) |
| 864 | |
| 865 | t.Run("multiple JSON objects extracts first", func(t *testing.T) { |
| 866 | t.Parallel() |
| 867 | inner := errors.New(`POST "/v1/x": 400 Bad Request {"message":"First"} {"message":"Second"}`) |
| 868 | se := &StatusError{StatusCode: 400, Err: inner} |
| 869 | assert.Equal(t, "HTTP 400: First", se.Error()) |
| 870 | }) |
| 871 | |
| 872 | t.Run("unicode in error message", func(t *testing.T) { |
| 873 | t.Parallel() |
| 874 | inner := errors.New(`POST "/v1/x": 400 Bad Request {"message":"Invalid emoji: 😀"}`) |
| 875 | se := &StatusError{StatusCode: 400, Err: inner} |
| 876 | assert.Equal(t, "HTTP 400: Invalid emoji: 😀", se.Error()) |
| 877 | }) |
| 878 | |
| 879 | t.Run("very large number in code field", func(t *testing.T) { |
| 880 | t.Parallel() |
| 881 | inner := errors.New(`{"error":{"code":9007199254740992,"message":"test"}}`) |
| 882 | se := &StatusError{StatusCode: 400, Err: inner} |
| 883 | // Large float64 that exceeds int64 range should still format |
| 884 | assert.Contains(t, se.Error(), "test") |
| 885 | assert.Contains(t, se.Error(), "code=") |
| 886 | }) |
| 887 | |
| 888 | t.Run("request-id with special characters", func(t *testing.T) { |
| 889 | t.Parallel() |
| 890 | inner := errors.New(`POST "/v1/x": 400 Bad Request (Request-ID: req_abc-123_XYZ) {"message":"test"}`) |
| 891 | se := &StatusError{StatusCode: 400, Err: inner} |
| 892 | assert.Equal(t, "HTTP 400: test (Request-ID: req_abc-123_XYZ)", se.Error()) |
| 893 | }) |
| 894 | |
| 895 | t.Run("brace in URL before JSON", func(t *testing.T) { |
| 896 | t.Parallel() |
| 897 | // Ensure we don't mistake a '{' in the URL for the start of JSON |
| 898 | inner := errors.New(`POST "https://api.example.com/v1/messages?param={value}": 400 Bad Request {"message":"test"}`) |
| 899 | se := &StatusError{StatusCode: 400, Err: inner} |
| 900 | assert.Equal(t, "HTTP 400: test", se.Error()) |
| 901 | }) |
| 902 | |
| 903 | t.Run("nested JSON in message field", func(t *testing.T) { |
| 904 | t.Parallel() |
| 905 | // The message field itself contains JSON-like text |