Skip to content

Commit 5df17c4

Browse files
Tests for new retry logic (#26)
--------- Co-authored-by: Justin Funston <[email protected]>
1 parent 0fba7a2 commit 5df17c4

File tree

2 files changed

+154
-7
lines changed

2 files changed

+154
-7
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "RustyObjectStore"
22
uuid = "1b5eed3d-1f46-4baa-87f3-a4a892b23610"
3-
version = "0.3.0"
3+
version = "0.3.1"
44

55
[deps]
66
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
@@ -16,7 +16,7 @@ ReTestItems = "1"
1616
Sockets = "1"
1717
Test = "1"
1818
julia = "1.8"
19-
object_store_ffi_jll = "0.4"
19+
object_store_ffi_jll = "0.4.2"
2020

2121
[extras]
2222
CloudBase = "85eb1798-d7c4-4918-bb13-c944d38e27ed"

test/aws_s3_exception_tests.jl

Lines changed: 152 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,16 +158,97 @@ end # @testitem
158158
import Sockets
159159

160160
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
162247

163248
function test_status(method, response_status, headers=nothing)
164249
@assert method === :GET || method === :PUT
165250
nrequests = Ref(0)
166251
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=="
171252

172253
(port, tcp_server) = Sockets.listenany(8081)
173254
http_server = HTTP.serve!(tcp_server) do request::HTTP.Request
@@ -209,6 +290,53 @@ end # @testitem
209290
return nrequests[]
210291
end
211292

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+
212340
@testset "400: Bad Request" begin
213341
# Returned when there's an error in the request URI, headers, or body. The response body
214342
# contains an error message explaining what the specific problem is.
@@ -326,4 +454,23 @@ end # @testitem
326454
nrequests = test_status(:PUT, 504)
327455
@test nrequests == 1 + max_retries
328456
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
329476
end

0 commit comments

Comments
 (0)