|
3 | 3 | importresponses |
4 | 4 |
|
5 | 5 | fromgitlabimportGitlabHttpError,GitlabList,GitlabParsingError,RedirectError |
| 6 | +fromgitlab.clientimportRETRYABLE_TRANSIENT_ERROR_CODES |
6 | 7 | fromtests.unitimporthelpers |
7 | 8 |
|
8 | 9 | MATCH_EMPTY_QUERY_PARAMS= [responses.matchers.query_param_matcher({})] |
@@ -51,7 +52,7 @@ def test_http_request_404(gl): |
51 | 52 |
|
52 | 53 |
|
53 | 54 | @responses.activate |
54 | | -@pytest.mark.parametrize("status_code",[500,502,503,504]) |
| 55 | +@pytest.mark.parametrize("status_code",RETRYABLE_TRANSIENT_ERROR_CODES) |
55 | 56 | deftest_http_request_with_only_failures(gl,status_code): |
56 | 57 | url="http://localhost/api/v4/projects" |
57 | 58 | responses.add( |
@@ -97,6 +98,37 @@ def request_callback(request): |
97 | 98 | assertlen(responses.calls)==calls_before_success |
98 | 99 |
|
99 | 100 |
|
| 101 | +@responses.activate |
| 102 | +deftest_http_request_with_retry_on_method_for_transient_network_failures(gl): |
| 103 | +call_count=0 |
| 104 | +calls_before_success=3 |
| 105 | + |
| 106 | +url="http://localhost/api/v4/projects" |
| 107 | + |
| 108 | +defrequest_callback(request): |
| 109 | +nonlocalcall_count |
| 110 | +call_count+=1 |
| 111 | +status_code=200 |
| 112 | +headers= {} |
| 113 | +body="[]" |
| 114 | + |
| 115 | +ifcall_count>=calls_before_success: |
| 116 | +return (status_code,headers,body) |
| 117 | +raiserequests.ConnectionError("Connection aborted.") |
| 118 | + |
| 119 | +responses.add_callback( |
| 120 | +method=responses.GET, |
| 121 | +url=url, |
| 122 | +callback=request_callback, |
| 123 | +content_type="application/json", |
| 124 | + ) |
| 125 | + |
| 126 | +http_r=gl.http_request("get","/projects",retry_transient_errors=True) |
| 127 | + |
| 128 | +asserthttp_r.status_code==200 |
| 129 | +assertlen(responses.calls)==calls_before_success |
| 130 | + |
| 131 | + |
100 | 132 | @responses.activate |
101 | 133 | deftest_http_request_with_retry_on_class_for_transient_failures(gl_retry): |
102 | 134 | call_count=0 |
@@ -126,6 +158,37 @@ def request_callback(request: requests.models.PreparedRequest): |
126 | 158 | assertlen(responses.calls)==calls_before_success |
127 | 159 |
|
128 | 160 |
|
| 161 | +@responses.activate |
| 162 | +deftest_http_request_with_retry_on_class_for_transient_network_failures(gl_retry): |
| 163 | +call_count=0 |
| 164 | +calls_before_success=3 |
| 165 | + |
| 166 | +url="http://localhost/api/v4/projects" |
| 167 | + |
| 168 | +defrequest_callback(request:requests.models.PreparedRequest): |
| 169 | +nonlocalcall_count |
| 170 | +call_count+=1 |
| 171 | +status_code=200 |
| 172 | +headers= {} |
| 173 | +body="[]" |
| 174 | + |
| 175 | +ifcall_count>=calls_before_success: |
| 176 | +return (status_code,headers,body) |
| 177 | +raiserequests.ConnectionError("Connection aborted.") |
| 178 | + |
| 179 | +responses.add_callback( |
| 180 | +method=responses.GET, |
| 181 | +url=url, |
| 182 | +callback=request_callback, |
| 183 | +content_type="application/json", |
| 184 | + ) |
| 185 | + |
| 186 | +http_r=gl_retry.http_request("get","/projects",retry_transient_errors=True) |
| 187 | + |
| 188 | +asserthttp_r.status_code==200 |
| 189 | +assertlen(responses.calls)==calls_before_success |
| 190 | + |
| 191 | + |
129 | 192 | @responses.activate |
130 | 193 | deftest_http_request_with_retry_on_class_and_method_for_transient_failures(gl_retry): |
131 | 194 | call_count=0 |
@@ -155,6 +218,39 @@ def request_callback(request): |
155 | 218 | assertlen(responses.calls)==1 |
156 | 219 |
|
157 | 220 |
|
| 221 | +@responses.activate |
| 222 | +deftest_http_request_with_retry_on_class_and_method_for_transient_network_failures( |
| 223 | +gl_retry, |
| 224 | +): |
| 225 | +call_count=0 |
| 226 | +calls_before_success=3 |
| 227 | + |
| 228 | +url="http://localhost/api/v4/projects" |
| 229 | + |
| 230 | +defrequest_callback(request): |
| 231 | +nonlocalcall_count |
| 232 | +call_count+=1 |
| 233 | +status_code=200 |
| 234 | +headers= {} |
| 235 | +body="[]" |
| 236 | + |
| 237 | +ifcall_count>=calls_before_success: |
| 238 | +return (status_code,headers,body) |
| 239 | +raiserequests.ConnectionError("Connection aborted.") |
| 240 | + |
| 241 | +responses.add_callback( |
| 242 | +method=responses.GET, |
| 243 | +url=url, |
| 244 | +callback=request_callback, |
| 245 | +content_type="application/json", |
| 246 | + ) |
| 247 | + |
| 248 | +withpytest.raises(requests.ConnectionError): |
| 249 | +gl_retry.http_request("get","/projects",retry_transient_errors=False) |
| 250 | + |
| 251 | +assertlen(responses.calls)==1 |
| 252 | + |
| 253 | + |
158 | 254 | defcreate_redirect_response( |
159 | 255 | *,response:requests.models.Response,http_method:str,api_path:str |
160 | 256 | )->requests.models.Response: |
|