error_test.go
1package graphhopper
2
3import (
4 "errors"
5 "testing"
6)
7
8func TestParseAPIError_TooFar(t *testing.T) {
9 body := `{"message": "Points are too far apart"}`
10 err := ParseAPIError(400, body)
11
12 if !IsNonRetryable(err) {
13 t.Errorf("expected non-retryable error, got %T: %v", err, err)
14 }
15 if !errors.Is(err, &RouteTooFarError{}) {
16 t.Errorf("expected RouteTooFarError, got %T: %v", err, err)
17 }
18}
19
20func TestParseAPIError_PointNotFound(t *testing.T) {
21 body := `{"message": "Cannot find point 0: 27.584537,88.468692"}`
22 err := ParseAPIError(400, body)
23
24 if !IsNonRetryable(err) {
25 t.Errorf("expected non-retryable error, got %T: %v", err, err)
26 }
27 if !errors.Is(err, &PointNotFoundError{}) {
28 t.Errorf("expected PointNotFoundError, got %T: %v", err, err)
29 }
30}
31
32func TestParseAPIError_Other400(t *testing.T) {
33 body := `{"message": "Invalid parameter"}`
34 err := ParseAPIError(400, body)
35
36 if !IsNonRetryable(err) {
37 t.Errorf("expected non-retryable error for 400, got retryable: %T: %v", err, err)
38 }
39}
40
41func TestParseAPIError_404(t *testing.T) {
42 body := `{"message": "Not found"}`
43 err := ParseAPIError(404, body)
44
45 if !IsNonRetryable(err) {
46 t.Errorf("expected non-retryable error for 404, got retryable: %T: %v", err, err)
47 }
48}
49
50func TestParseAPIError_500(t *testing.T) {
51 body := `{"message": "Internal server error"}`
52 err := ParseAPIError(500, body)
53
54 if IsNonRetryable(err) {
55 t.Errorf("expected retryable error for 500, got non-retryable: %T: %v", err, err)
56 }
57}
58
59func TestIsNonRetryable_Nil(t *testing.T) {
60 if IsNonRetryable(nil) {
61 t.Errorf("expected false for nil error")
62 }
63}
64
65func TestParseAPIError_CaseInsensitive_TooFar(t *testing.T) {
66 testCases := []struct {
67 name string
68 message string
69 expected bool
70 }{
71 {"lowercase", "points are too far from each other", true},
72 {"uppercase", "Points are TOO FAR apart", true},
73 {"mixed case", "Too Far away", true},
74 {"no match", "other error message", false},
75 }
76
77 for _, tc := range testCases {
78 t.Run(tc.name, func(t *testing.T) {
79 body := `{"message": "` + tc.message + `"}`
80 err := ParseAPIError(400, body)
81 if tc.expected {
82 if !errors.Is(err, &RouteTooFarError{}) {
83 t.Errorf("expected RouteTooFarError for message %q", tc.message)
84 }
85 } else {
86 // Should still be non-retryable (generic client error)
87 if !IsNonRetryable(err) {
88 t.Errorf("expected non-retryable for message %q", tc.message)
89 }
90 }
91 })
92 }
93}
94
95func TestParseAPIError_CaseInsensitive_PointNotFound(t *testing.T) {
96 testCases := []struct {
97 name string
98 message string
99 expected bool
100 }{
101 {"lowercase", "cannot find point 0: 27.584537,88.468692", true},
102 {"uppercase", "Cannot find Point 1: 12.34,56.78", true},
103 {"mixed case", "Cannot Find Point", true},
104 {"no match", "other error message", false},
105 }
106
107 for _, tc := range testCases {
108 t.Run(tc.name, func(t *testing.T) {
109 body := `{"message": "` + tc.message + `"}`
110 err := ParseAPIError(400, body)
111 if tc.expected {
112 if !errors.Is(err, &PointNotFoundError{}) {
113 t.Errorf("expected PointNotFoundError for message %q, got %T", tc.message, err)
114 }
115 }
116 })
117 }
118}
119
120func TestRouteTooFarError_Error(t *testing.T) {
121 err := &RouteTooFarError{Message: "test message"}
122 expected := "route too far: test message"
123 if err.Error() != expected {
124 t.Errorf("expected %q, got %q", expected, err.Error())
125 }
126}
127
128func TestPointNotFoundError_Error(t *testing.T) {
129 err := &PointNotFoundError{Message: "test message"}
130 expected := "point not found: test message"
131 if err.Error() != expected {
132 t.Errorf("expected %q, got %q", expected, err.Error())
133 }
134}
135
136func TestClientError_Error(t *testing.T) {
137 err := &clientError{StatusCode: 400, Message: "bad request"}
138 expected := "routing API client error (status 400): bad request"
139 if err.Error() != expected {
140 t.Errorf("expected %q, got %q", expected, err.Error())
141 }
142}