diff --git a/http_transport.gd b/http_transport.gd index d63be82..32589a0 100644 --- a/http_transport.gd +++ b/http_transport.gd @@ -4,6 +4,10 @@ extends RefCounted ## ## Tests subclass this to answer requests without a network connection. +## Seconds before a request is given up and reported as failed. This covers the whole +## download, so it is generous enough for long songs on a slow connection. +var timeout_seconds: float = 120.0 + var _owner: Node @@ -12,10 +16,11 @@ func _init(owner: Node) -> void: ## Requests [param url] and calls [param on_complete] with -## [code](response_code: int, body: PackedByteArray)[/code]. Connection errors are -## reported with response code 0. +## [code](response_code: int, body: PackedByteArray)[/code]. Connection errors and +## timeouts are reported with response code 0. func request(url: String, method: int, on_complete: Callable) -> void: var http_request: HTTPRequest = HTTPRequest.new() + http_request.timeout = timeout_seconds _owner.add_child(http_request) http_request.request_completed.connect( func( diff --git a/tests/unit/test_http_transport.gd b/tests/unit/test_http_transport.gd new file mode 100644 index 0000000..f3e5f25 --- /dev/null +++ b/tests/unit/test_http_transport.gd @@ -0,0 +1,48 @@ +extends GdUnitTestSuite +## Uses a local TCP server that accepts connections but never answers, like a hung +## MusicServer. + +var _server: TCPServer +var _connections: Array[StreamPeerTCP] = [] +var _owner: Node + + +func before_test() -> void: + _server = TCPServer.new() + assert_int(_server.listen(0, "127.0.0.1")).is_equal(OK) + _owner = auto_free(Node.new()) + add_child(_owner) + + +func after_test() -> void: + for connection: StreamPeerTCP in _connections: + connection.disconnect_from_host() + _server.stop() + + +func _accept_connections() -> void: + while _server.is_connection_available(): + _connections.append(_server.take_connection()) + + +func test_request_to_silent_server_times_out_as_failed() -> void: + var transport: HttpTransport = HttpTransport.new(_owner) + transport.timeout_seconds = 0.5 + var response_codes: Array[int] = [] + + transport.request("http://127.0.0.1:%d/music/rand" % _server.get_local_port(), + HTTPClient.METHOD_GET, + func(response_code: int, _body: PackedByteArray) -> void: + response_codes.append(response_code)) + for i: int in 40: + _accept_connections() + await await_millis(50) + if !response_codes.is_empty(): + break + + assert_bool(_connections.is_empty()).is_false() + assert_array(response_codes).contains_exactly([0]) + + +func test_default_timeout_is_set() -> void: + assert_float(HttpTransport.new(_owner).timeout_seconds).is_greater(0.0) diff --git a/tests/unit/test_http_transport.gd.uid b/tests/unit/test_http_transport.gd.uid new file mode 100644 index 0000000..d3c0ab7 --- /dev/null +++ b/tests/unit/test_http_transport.gd.uid @@ -0,0 +1 @@ +uid://3ubc73vxxqir