Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f67783f

Browse files
committedJun 23, 2024
Support for mocked client requests.
1 parent 1591f3f commit f67783f

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed
 

‎lib/async/http/mock.rb

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# frozen_string_literal: true
2+
#
3+
# Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
23+
require_relative 'mock/endpoint'

‎lib/async/http/mock/endpoint.rb

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# frozen_string_literal: true
2+
#
3+
# Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
23+
require_relative '../protocol'
24+
25+
require 'async/queue'
26+
27+
module Async
28+
module HTTP
29+
module Mock
30+
# This is an endpoint which bridges a client with a local server.
31+
class Endpoint
32+
def initialize(protocol = Protocol::HTTP2, scheme = "http", authority = "localhost", queue: Queue.new)
33+
@protocol = protocol
34+
@scheme = scheme
35+
@authority = authority
36+
37+
@queue = queue
38+
end
39+
40+
attr :protocol
41+
attr :scheme
42+
attr :authority
43+
44+
# Processing incoming connections
45+
# @yield [::HTTP::Protocol::Request] the requests as they come in.
46+
def run(parent: Task.current, &block)
47+
while peer = @queue.dequeue
48+
server = @protocol.server(peer)
49+
50+
parent.async do
51+
server.each(&block)
52+
end
53+
end
54+
end
55+
56+
def connect
57+
local, remote = ::Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM)
58+
59+
@queue.enqueue(remote)
60+
61+
return local
62+
end
63+
64+
def wrap(endpoint)
65+
self.class.new(@protocol, endpoint.scheme, endpoint.authority, queue: @queue)
66+
end
67+
end
68+
end
69+
end
70+
end

‎test/async/http/mock.rb

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
2+
#
3+
# Permission is hereby granted, free of charge, to any person obtaining a copy
4+
# of this software and associated documentation files (the "Software"), to deal
5+
# in the Software without restriction, including without limitation the rights
6+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
# copies of the Software, and to permit persons to whom the Software is
8+
# furnished to do so, subject to the following conditions:
9+
#
10+
# The above copyright notice and this permission notice shall be included in
11+
# all copies or substantial portions of the Software.
12+
#
13+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
# THE SOFTWARE.
20+
21+
require 'async/http/mock'
22+
require 'async/http/endpoint'
23+
require 'async/http/client'
24+
25+
require 'sus/fixtures/async/reactor_context'
26+
27+
describe Async::HTTP::Mock do
28+
include Sus::Fixtures::Async::ReactorContext
29+
30+
let(:endpoint) {Async::HTTP::Mock::Endpoint.new}
31+
32+
it "can respond to requests" do
33+
server = Async do
34+
endpoint.run do |request|
35+
::Protocol::HTTP::Response[200, [], ["Hello World"]]
36+
end
37+
end
38+
39+
client = Async::HTTP::Client.new(endpoint)
40+
41+
response = client.get("/index")
42+
43+
expect(response).to be(:success?)
44+
expect(response.read).to be == "Hello World"
45+
end
46+
47+
with 'mocked client' do
48+
it "can mock a client" do
49+
server = Async do
50+
endpoint.run do |request|
51+
::Protocol::HTTP::Response[200, [], ["Authority: #{request.authority}"]]
52+
end
53+
end
54+
55+
mock(Async::HTTP::Client) do |mock|
56+
replacement_endpoint = self.endpoint
57+
58+
mock.wrap(:new) do |original, original_endpoint, **options|
59+
original.call(replacement_endpoint.wrap(original_endpoint), **options)
60+
end
61+
end
62+
63+
google_endpoint = Async::HTTP::Endpoint.parse("https://www.google.com")
64+
client = Async::HTTP::Client.new(google_endpoint)
65+
66+
response = client.get("/search?q=hello")
67+
68+
expect(response).to be(:success?)
69+
expect(response.read).to be == "Authority: www.google.com"
70+
ensure
71+
response&.close
72+
end
73+
end
74+
end

0 commit comments

Comments
 (0)