1package elastic 2 3import ( 4 "bufio" 5 "fmt" 6 "net/http" 7 "strings" 8 "testing" 9) 10 11func TestResponseError(t *testing.T) { 12 raw := "HTTP/1.1 404 Not Found\r\n" + 13 "\r\n" + 14 `{"error":{"root_cause":[{"type":"index_missing_exception","reason":"no such index","index":"elastic-test"}],"type":"index_missing_exception","reason":"no such index","index":"elastic-test"},"status":404}` + "\r\n" 15 r := bufio.NewReader(strings.NewReader(raw)) 16 17 req, err := http.NewRequest("GET", "/", nil) 18 if err != nil { 19 t.Fatal(err) 20 } 21 22 resp, err := http.ReadResponse(r, nil) 23 if err != nil { 24 t.Fatal(err) 25 } 26 err = checkResponse(req, resp) 27 if err == nil { 28 t.Fatalf("expected error; got: %v", err) 29 } 30 31 // Check for correct error message 32 expected := fmt.Sprintf("elastic: Error %d (%s): no such index [type=index_missing_exception]", resp.StatusCode, http.StatusText(resp.StatusCode)) 33 got := err.Error() 34 if got != expected { 35 t.Fatalf("expected %q; got: %q", expected, got) 36 } 37 38 // Check that error is of type *elastic.Error, which contains additional information 39 e, ok := err.(*Error) 40 if !ok { 41 t.Fatal("expected error to be of type *elastic.Error") 42 } 43 if e.Status != resp.StatusCode { 44 t.Fatalf("expected status code %d; got: %d", resp.StatusCode, e.Status) 45 } 46 if e.Details == nil { 47 t.Fatalf("expected error details; got: %v", e.Details) 48 } 49 if got, want := e.Details.Index, "elastic-test"; got != want { 50 t.Fatalf("expected error details index %q; got: %q", want, got) 51 } 52 if got, want := e.Details.Type, "index_missing_exception"; got != want { 53 t.Fatalf("expected error details type %q; got: %q", want, got) 54 } 55 if got, want := e.Details.Reason, "no such index"; got != want { 56 t.Fatalf("expected error details reason %q; got: %q", want, got) 57 } 58 if got, want := len(e.Details.RootCause), 1; got != want { 59 t.Fatalf("expected %d error details root causes; got: %d", want, got) 60 } 61 62 if got, want := e.Details.RootCause[0].Index, "elastic-test"; got != want { 63 t.Fatalf("expected root cause index %q; got: %q", want, got) 64 } 65 if got, want := e.Details.RootCause[0].Type, "index_missing_exception"; got != want { 66 t.Fatalf("expected root cause type %q; got: %q", want, got) 67 } 68 if got, want := e.Details.RootCause[0].Reason, "no such index"; got != want { 69 t.Fatalf("expected root cause reason %q; got: %q", want, got) 70 } 71} 72 73func TestResponseErrorHTML(t *testing.T) { 74 raw := "HTTP/1.1 413 Request Entity Too Large\r\n" + 75 "\r\n" + 76 `<html> 77<head><title>413 Request Entity Too Large</title></head> 78<body bgcolor="white"> 79<center><h1>413 Request Entity Too Large</h1></center> 80<hr><center>nginx/1.6.2</center> 81</body> 82</html>` + "\r\n" 83 r := bufio.NewReader(strings.NewReader(raw)) 84 85 req, err := http.NewRequest("GET", "/", nil) 86 if err != nil { 87 t.Fatal(err) 88 } 89 90 resp, err := http.ReadResponse(r, nil) 91 if err != nil { 92 t.Fatal(err) 93 } 94 err = checkResponse(req, resp) 95 if err == nil { 96 t.Fatalf("expected error; got: %v", err) 97 } 98 99 // Check for correct error message 100 expected := fmt.Sprintf("elastic: Error %d (%s)", http.StatusRequestEntityTooLarge, http.StatusText(http.StatusRequestEntityTooLarge)) 101 got := err.Error() 102 if got != expected { 103 t.Fatalf("expected %q; got: %q", expected, got) 104 } 105} 106 107func TestResponseErrorWithIgnore(t *testing.T) { 108 raw := "HTTP/1.1 404 Not Found\r\n" + 109 "\r\n" + 110 `{"some":"response"}` + "\r\n" 111 r := bufio.NewReader(strings.NewReader(raw)) 112 113 req, err := http.NewRequest("HEAD", "/", nil) 114 if err != nil { 115 t.Fatal(err) 116 } 117 118 resp, err := http.ReadResponse(r, nil) 119 if err != nil { 120 t.Fatal(err) 121 } 122 err = checkResponse(req, resp) 123 if err == nil { 124 t.Fatalf("expected error; got: %v", err) 125 } 126 err = checkResponse(req, resp, 404) // ignore 404 errors 127 if err != nil { 128 t.Fatalf("expected no error; got: %v", err) 129 } 130} 131 132func TestIsNotFound(t *testing.T) { 133 if got, want := IsNotFound(nil), false; got != want { 134 t.Errorf("expected %v; got: %v", want, got) 135 } 136 if got, want := IsNotFound(""), false; got != want { 137 t.Errorf("expected %v; got: %v", want, got) 138 } 139 if got, want := IsNotFound(200), false; got != want { 140 t.Errorf("expected %v; got: %v", want, got) 141 } 142 if got, want := IsNotFound(404), true; got != want { 143 t.Errorf("expected %v; got: %v", want, got) 144 } 145 146 if got, want := IsNotFound(&Error{Status: 404}), true; got != want { 147 t.Errorf("expected %v; got: %v", want, got) 148 } 149 if got, want := IsNotFound(&Error{Status: 200}), false; got != want { 150 t.Errorf("expected %v; got: %v", want, got) 151 } 152 153 if got, want := IsNotFound(Error{Status: 404}), true; got != want { 154 t.Errorf("expected %v; got: %v", want, got) 155 } 156 if got, want := IsNotFound(Error{Status: 200}), false; got != want { 157 t.Errorf("expected %v; got: %v", want, got) 158 } 159 160 if got, want := IsNotFound(&http.Response{StatusCode: 404}), true; got != want { 161 t.Errorf("expected %v; got: %v", want, got) 162 } 163 if got, want := IsNotFound(&http.Response{StatusCode: 200}), false; got != want { 164 t.Errorf("expected %v; got: %v", want, got) 165 } 166} 167 168func TestIsTimeout(t *testing.T) { 169 if got, want := IsTimeout(nil), false; got != want { 170 t.Errorf("expected %v; got: %v", want, got) 171 } 172 if got, want := IsTimeout(""), false; got != want { 173 t.Errorf("expected %v; got: %v", want, got) 174 } 175 if got, want := IsTimeout(200), false; got != want { 176 t.Errorf("expected %v; got: %v", want, got) 177 } 178 if got, want := IsTimeout(408), true; got != want { 179 t.Errorf("expected %v; got: %v", want, got) 180 } 181 182 if got, want := IsTimeout(&Error{Status: 408}), true; got != want { 183 t.Errorf("expected %v; got: %v", want, got) 184 } 185 if got, want := IsTimeout(&Error{Status: 200}), false; got != want { 186 t.Errorf("expected %v; got: %v", want, got) 187 } 188 189 if got, want := IsTimeout(Error{Status: 408}), true; got != want { 190 t.Errorf("expected %v; got: %v", want, got) 191 } 192 if got, want := IsTimeout(Error{Status: 200}), false; got != want { 193 t.Errorf("expected %v; got: %v", want, got) 194 } 195 196 if got, want := IsTimeout(&http.Response{StatusCode: 408}), true; got != want { 197 t.Errorf("expected %v; got: %v", want, got) 198 } 199 if got, want := IsTimeout(&http.Response{StatusCode: 200}), false; got != want { 200 t.Errorf("expected %v; got: %v", want, got) 201 } 202} 203 204func TestIsConflict(t *testing.T) { 205 if got, want := IsConflict(nil), false; got != want { 206 t.Errorf("expected %v; got: %v", want, got) 207 } 208 if got, want := IsConflict(""), false; got != want { 209 t.Errorf("expected %v; got: %v", want, got) 210 } 211 if got, want := IsConflict(200), false; got != want { 212 t.Errorf("expected %v; got: %v", want, got) 213 } 214 if got, want := IsConflict(http.StatusConflict), true; got != want { 215 t.Errorf("expected %v; got: %v", want, got) 216 } 217 218 if got, want := IsConflict(&Error{Status: 409}), true; got != want { 219 t.Errorf("expected %v; got: %v", want, got) 220 } 221 if got, want := IsConflict(&Error{Status: 200}), false; got != want { 222 t.Errorf("expected %v; got: %v", want, got) 223 } 224 225 if got, want := IsConflict(Error{Status: 409}), true; got != want { 226 t.Errorf("expected %v; got: %v", want, got) 227 } 228 if got, want := IsConflict(Error{Status: 200}), false; got != want { 229 t.Errorf("expected %v; got: %v", want, got) 230 } 231 232 if got, want := IsConflict(&http.Response{StatusCode: 409}), true; got != want { 233 t.Errorf("expected %v; got: %v", want, got) 234 } 235 if got, want := IsConflict(&http.Response{StatusCode: 200}), false; got != want { 236 t.Errorf("expected %v; got: %v", want, got) 237 } 238} 239 240func TestIsStatusCode(t *testing.T) { 241 tests := []struct { 242 Error interface{} 243 Code int 244 Want bool 245 }{ 246 // #0 247 { 248 Error: nil, 249 Code: 200, 250 Want: false, 251 }, 252 // #1 253 { 254 Error: "", 255 Code: 200, 256 Want: false, 257 }, 258 // #2 259 { 260 Error: http.StatusConflict, 261 Code: 409, 262 Want: true, 263 }, 264 // #3 265 { 266 Error: http.StatusConflict, 267 Code: http.StatusInternalServerError, 268 Want: false, 269 }, 270 // #4 271 { 272 Error: &Error{Status: http.StatusConflict}, 273 Code: 409, 274 Want: true, 275 }, 276 // #5 277 { 278 Error: Error{Status: http.StatusConflict}, 279 Code: 409, 280 Want: true, 281 }, 282 // #6 283 { 284 Error: &http.Response{StatusCode: http.StatusConflict}, 285 Code: 409, 286 Want: true, 287 }, 288 } 289 290 for i, tt := range tests { 291 if have, want := IsStatusCode(tt.Error, tt.Code), tt.Want; have != want { 292 t.Errorf("#%d: have %v, want %v", i, have, want) 293 } 294 } 295} 296