require "test_helper" using Plum::BinaryString class ClientTest < Minitest::Test def test_request_async res2 = nil client = nil server_thread = start_tls_server Client.start("127.0.0.1", LISTEN_PORT, https: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) { |c| client = c res1 = client.request({ ":path" => "/", ":method" => "GET", ":scheme" => "https", "header" => "ccc" }, nil) { |res1| assert(res1.headers) } assert_nil(res1.headers) res2 = client.get("/", headers: { "header" => "ccc" }) assert_nil(res2.headers) } assert(res2.headers) assert_equal("GETccc", res2.body) ensure server_thread.join if server_thread end def test_verify client = nil server_thread = start_tls_server assert_raises(OpenSSL::SSL::SSLError) { client = Client.start("127.0.0.1", LISTEN_PORT, https: true, verify_mode: OpenSSL::SSL::VERIFY_PEER) } ensure server_thread.join if server_thread end def test_raise_error_async_seq_resume server_thread = start_tls_server client = Client.start("127.0.0.1", LISTEN_PORT, https: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) res = client.get("/error_in_data") assert_raises(LocalConnectionError) { client.resume } client.close ensure server_thread.join if server_thread end def test_raise_error_async_block client = nil server_thread = start_tls_server assert_raises(LocalConnectionError) { Client.start("127.0.0.1", LISTEN_PORT, https: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) { |c| client = c client.get("/connection_error") { |res| flunk "success??" } } # resume } ensure server_thread.join if server_thread end def test_session_socket_http2_https sock = StringSocket.new client = Client.start(sock, nil, https: true) assert(client.session.class == ClientSession) end def test_session_socket_http2_http sock = StringSocket.new("HTTP/1.1 100\r\n\r\n") client = Client.start(sock, nil, https: false) assert(client.session.class == UpgradeClientSession) end private def start_tls_server(&block) ctx = OpenSSL::SSL::SSLContext.new ctx.alpn_select_cb = -> protocols { "h2" } ctx.cert = TLS_CERT ctx.key = TLS_KEY tcp_server = TCPServer.new("127.0.0.1", LISTEN_PORT) ssl_server = OpenSSL::SSL::SSLServer.new(tcp_server, ctx) server_thread = Thread.new { plum = nil begin Timeout.timeout(1) { sock = ssl_server.accept plum = ServerConnection.new(sock.method(:write)) plum.on(:stream) { |stream| headers = data = nil stream.on(:headers) { |h| headers = h.to_h } stream.on(:data) { |d| data = d } stream.on(:end_stream) { case headers[":path"] when "/connection_error" plum.goaway(:protocol_error) when "/error_in_data" stream.send_headers({ ":status" => 200 }, end_stream: false) stream.send_data("a", end_stream: false) raise ExampleError, "example error" else stream.send_headers({ ":status" => 200 }, end_stream: false) stream.send_data(headers.to_h[":method"] + headers.to_h["header"].to_s + data.to_s, end_stream: true) end } } yield plum if block_given? begin while !sock.closed? && !sock.eof? plum << sock.readpartial(1024) end rescue Errno::ECONNABORTED # Ignore, this happens only when running on mingw64(?) end } rescue OpenSSL::SSL::SSLError rescue Timeout::Error flunk "server timeout" rescue ExampleError => e plum.goaway(:internal_error) if plum ensure tcp_server.close end } end end