@@ -158,16 +158,97 @@ end # @testitem
158
158
import Sockets
159
159
160
160
max_retries = 2
161
- retry_timeout_secs = 2
161
+ retry_timeout_secs = 10
162
+ request_timeout_secs = 1
163
+ region = " us-east-1"
164
+ container = " mybucket"
165
+ dummy_access_key_id = " qUwJPLlmEtlCDXJ1OUzF"
166
+ dummy_secret_access_key = " Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
167
+
168
+ function test_tcp_error (method)
169
+ @assert method === :GET || method === :PUT
170
+ nrequests = Ref (0 )
171
+
172
+ (port, tcp_server) = Sockets. listenany (8082 )
173
+ @async begin
174
+ while true
175
+ sock = Sockets. accept (tcp_server)
176
+ _ = read (sock, 4 )
177
+ close (sock)
178
+ nrequests[] += 1
179
+ end
180
+ end
181
+
182
+ baseurl = " http://127.0.0.1:$port "
183
+ conf = AWSConfig (;
184
+ region= region,
185
+ bucket_name= container,
186
+ access_key_id= dummy_access_key_id,
187
+ secret_access_key= dummy_secret_access_key,
188
+ host= baseurl,
189
+ opts= ClientOptions (;
190
+ max_retries= max_retries,
191
+ retry_timeout_secs= retry_timeout_secs
192
+ )
193
+ )
194
+
195
+ try
196
+ method === :GET && get_object! (zeros (UInt8, 5 ), " blob" , conf)
197
+ method === :PUT && put_object (codeunits (" a,b,c" ), " blob" , conf)
198
+ @test false # Should have thrown an error
199
+ catch e
200
+ method === :GET && @test e isa RustyObjectStore. GetException
201
+ method === :PUT && @test e isa RustyObjectStore. PutException
202
+ @test occursin (" connection closed" , e. msg)
203
+ finally
204
+ close (tcp_server)
205
+ end
206
+ return nrequests[]
207
+ end
208
+
209
+ function test_get_stream_error ()
210
+ nrequests = Ref (0 )
211
+
212
+ (port, tcp_server) = Sockets. listenany (8083 )
213
+ http_server = HTTP. listen! (tcp_server) do http:: HTTP.Stream
214
+ nrequests[] += 1
215
+ HTTP. setstatus (http, 200 )
216
+ HTTP. setheader (http, " Content-Length" => " 20" )
217
+ HTTP. startwrite (http)
218
+ write (http, " not enough" )
219
+ close (http. stream)
220
+ end
221
+
222
+ baseurl = " http://127.0.0.1:$port "
223
+ conf = AWSConfig (;
224
+ region= region,
225
+ bucket_name= container,
226
+ access_key_id= dummy_access_key_id,
227
+ secret_access_key= dummy_secret_access_key,
228
+ host= baseurl,
229
+ opts= ClientOptions (;
230
+ max_retries= max_retries,
231
+ retry_timeout_secs= retry_timeout_secs
232
+ )
233
+ )
234
+
235
+ try
236
+ get_object! (zeros (UInt8, 20 ), " blob" , conf)
237
+ @test false # Should have thrown an error
238
+ catch e
239
+ @test e isa RustyObjectStore. GetException
240
+ @test occursin (" end of file before message length reached" , e. msg)
241
+ finally
242
+ close (http_server)
243
+ end
244
+ wait (http_server)
245
+ return nrequests[]
246
+ end
162
247
163
248
function test_status (method, response_status, headers= nothing )
164
249
@assert method === :GET || method === :PUT
165
250
nrequests = Ref (0 )
166
251
response_body = " response body from the dummy server"
167
- region = " us-east-1"
168
- container = " mybucket"
169
- dummy_access_key_id = " qUwJPLlmEtlCDXJ1OUzF"
170
- dummy_secret_access_key = " Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
171
252
172
253
(port, tcp_server) = Sockets. listenany (8081 )
173
254
http_server = HTTP. serve! (tcp_server) do request:: HTTP.Request
@@ -209,6 +290,53 @@ end # @testitem
209
290
return nrequests[]
210
291
end
211
292
293
+ function test_timeout (method, message, wait_secs:: Int = 60 )
294
+ @assert method === :GET || method === :PUT
295
+ nrequests = Ref (0 )
296
+ response_body = " response body from the dummy server"
297
+
298
+ (port, tcp_server) = Sockets. listenany (8081 )
299
+ http_server = HTTP. serve! (tcp_server) do request:: HTTP.Request
300
+ if request. method == " GET" && request. target == " /$container /_this_file_does_not_exist"
301
+ # This is the exploratory ping from connect_and_test in lib.rs
302
+ return HTTP. Response (404 , " Yup, still doesn't exist" )
303
+ end
304
+ nrequests[] += 1
305
+ if wait_secs > 0
306
+ sleep (wait_secs)
307
+ end
308
+ return HTTP. Response (200 , response_body)
309
+ end
310
+
311
+ baseurl = " http://127.0.0.1:$port "
312
+ conf = AWSConfig (;
313
+ region= region,
314
+ bucket_name= container,
315
+ access_key_id= dummy_access_key_id,
316
+ secret_access_key= dummy_secret_access_key,
317
+ host= baseurl,
318
+ opts= ClientOptions (;
319
+ max_retries= max_retries,
320
+ retry_timeout_secs= retry_timeout_secs,
321
+ request_timeout_secs
322
+ )
323
+ )
324
+
325
+ try
326
+ method === :GET && get_object! (zeros (UInt8, 5 ), " blob" , conf)
327
+ method === :PUT && put_object (codeunits (" a,b,c" ), " blob" , conf)
328
+ @test false # Should have thrown an error
329
+ catch e
330
+ method === :GET && @test e isa RustyObjectStore. GetException
331
+ method === :PUT && @test e isa RustyObjectStore. PutException
332
+ @test occursin (string (message), e. msg)
333
+ finally
334
+ close (http_server)
335
+ end
336
+ wait (http_server)
337
+ return nrequests[]
338
+ end
339
+
212
340
@testset " 400: Bad Request" begin
213
341
# Returned when there's an error in the request URI, headers, or body. The response body
214
342
# contains an error message explaining what the specific problem is.
@@ -326,4 +454,23 @@ end # @testitem
326
454
nrequests = test_status (:PUT , 504 )
327
455
@test nrequests == 1 + max_retries
328
456
end
457
+
458
+ @testset " Timeout" begin
459
+ nrequests = test_timeout (:GET , " timed out" , 2 )
460
+ @test nrequests == 1 + max_retries
461
+ nrequests = test_timeout (:PUT , " timed out" , 2 )
462
+ @test nrequests == 1 + max_retries
463
+ end
464
+
465
+ @testset " TCP Closed" begin
466
+ nrequests = test_tcp_error (:GET )
467
+ @test nrequests == 1 + max_retries
468
+ nrequests = test_tcp_error (:PUT )
469
+ @test nrequests == 1 + max_retries
470
+ end
471
+
472
+ @testset " Incomplete GET body" begin
473
+ nrequests = test_get_stream_error ()
474
+ @test nrequests == 1 + max_retries
475
+ end
329
476
end
0 commit comments