Skip to content

Commit 579778e

Browse files
committed
Migrate tests from rspec -> sus.
1 parent f9450cb commit 579778e

File tree

15 files changed

+332
-387
lines changed

15 files changed

+332
-387
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# frozen_string_literal: true
2+
3+
# Released under the MIT License.
4+
# Copyright, 2023, by Samuel Williams.
5+
6+
require 'protocol/http/body/deflate'
7+
require 'sus/fixtures'
8+
9+
module Sus::Fixtures
10+
module Async
11+
module HTTP
12+
module Body
13+
AWritableBody = Sus::Shared("a writable body") do
14+
it "can write and read data" do
15+
3.times do |i|
16+
body.write("Hello World #{i}")
17+
expect(body.read).to be == "Hello World #{i}"
18+
end
19+
end
20+
21+
it "can buffer data in order" do
22+
3.times do |i|
23+
body.write("Hello World #{i}")
24+
end
25+
26+
3.times do |i|
27+
expect(body.read).to be == "Hello World #{i}"
28+
end
29+
end
30+
31+
with '#join' do
32+
it "can join chunks" do
33+
3.times do |i|
34+
body.write("#{i}")
35+
end
36+
37+
body.close
38+
39+
expect(body.join).to be == "012"
40+
end
41+
end
42+
43+
with '#each' do
44+
it "can read all data in order" do
45+
3.times do |i|
46+
body.write("Hello World #{i}")
47+
end
48+
49+
body.close
50+
51+
3.times do |i|
52+
chunk = body.read
53+
expect(chunk).to be == "Hello World #{i}"
54+
end
55+
end
56+
57+
it "can propagate failures" do
58+
reactor.async do
59+
expect do
60+
body.each do |chunk|
61+
raise RuntimeError.new("It was too big!")
62+
end
63+
end.to raise_exception(RuntimeError, message: be =~ /big/)
64+
end
65+
66+
expect{
67+
body.write("Beep boop") # This will cause a failure.
68+
::Async::Task.current.yield
69+
body.write("Beep boop") # This will fail.
70+
}.to raise_exception(RuntimeError, message: be =~ /big/)
71+
end
72+
73+
it "can propagate failures in nested bodies" do
74+
nested = Protocol::HTTP::Body::Deflate.for(body)
75+
76+
reactor.async do
77+
expect do
78+
nested.each do |chunk|
79+
raise RuntimeError.new("It was too big!")
80+
end
81+
end.to raise_exception(RuntimeError, message: be =~ /big/)
82+
end
83+
84+
expect{
85+
body.write("Beep boop") # This will cause a failure.
86+
::Async::Task.current.yield
87+
body.write("Beep boop") # This will fail.
88+
}.to raise_exception(RuntimeError, message: be =~ /big/)
89+
end
90+
91+
it "will stop after finishing" do
92+
output_task = reactor.async do
93+
body.each do |chunk|
94+
expect(chunk).to be == "Hello World!"
95+
end
96+
end
97+
98+
body.write("Hello World!")
99+
body.close
100+
101+
expect(body).not.to be(:empty?)
102+
103+
::Async::Task.current.yield
104+
105+
expect(output_task).to be(:finished?)
106+
expect(body).to be(:empty?)
107+
end
108+
end
109+
end
110+
end
111+
end
112+
end
113+
end

gems.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
gem "covered"
2929
gem "sus"
3030
gem "sus-fixtures-async"
31+
gem "sus-fixtures-async-http", "~> 0.5"
32+
gem "sus-fixtures-openssl"
3133

3234
gem "bake"
3335
gem "bake-test"

test/async/http/body.rb

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,15 @@
55

66
require 'async/http/body'
77

8-
require 'async/http/server'
9-
require 'async/http/client'
10-
require 'async/http/endpoint'
11-
12-
require 'async/io/ssl_socket'
13-
14-
require_relative 'server_context'
15-
8+
require 'sus/fixtures/async'
9+
require 'sus/fixtures/openssl'
10+
require 'sus/fixtures/async/http'
1611
require 'localhost/authority'
1712

18-
RSpec.shared_examples Async::HTTP::Body do
19-
let(:client) {Async::HTTP::Client.new(client_endpoint, protocol: described_class)}
20-
21-
context 'with echo server' do
22-
let(:server) do
23-
Async::HTTP::Server.for(@bound_endpoint, protocol: described_class) do |request|
13+
ABody = Sus::Shared("a body") do
14+
with 'echo server' do
15+
let(:app) do
16+
Protocol::HTTP::Middleware.for do |request|
2417
input = request.body
2518
output = Async::HTTP::Body::Writable.new
2619

@@ -46,16 +39,16 @@
4639

4740
response = client.post("/", {}, output)
4841

49-
expect(response).to be_success
42+
expect(response).to be(:success?)
5043
expect(response.read).to be == "!dlroW olleH"
5144
end
5245
end
5346

54-
context "with streaming server" do
47+
with "streaming server" do
5548
let(:notification) {Async::Notification.new}
5649

57-
let(:server) do
58-
Async::HTTP::Server.for(@bound_endpoint, protocol: described_class) do |request|
50+
let(:app) do
51+
Protocol::HTTP::Middleware.for do |request|
5952
body = Async::HTTP::Body::Writable.new
6053

6154
Async::Task.current.async do |task|
@@ -74,7 +67,7 @@
7467
it "can stream response" do
7568
response = client.get("/")
7669

77-
expect(response).to be_success
70+
expect(response).to be(:success?)
7871

7972
j = 0
8073
# This validates interleaving
@@ -88,23 +81,28 @@
8881
end
8982
end
9083

91-
RSpec.describe Async::HTTP::Protocol::HTTP1 do
92-
include_context Async::HTTP::Server
84+
describe Async::HTTP::Protocol::HTTP1 do
85+
include Sus::Fixtures::Async::HTTP::ServerContext
9386

94-
it_should_behave_like Async::HTTP::Body
87+
it_behaves_like ABody
9588
end
9689

97-
RSpec.describe Async::HTTP::Protocol::HTTPS do
98-
include_context Async::HTTP::Server
90+
describe Async::HTTP::Protocol::HTTPS do
91+
include Sus::Fixtures::Async::HTTP::ServerContext
92+
include Sus::Fixtures::OpenSSL::ValidCertificateContext
9993

10094
let(:authority) {Localhost::Authority.new}
10195

10296
let(:server_context) {authority.server_context}
10397
let(:client_context) {authority.client_context}
10498

105-
# Shared port for localhost network tests.
106-
let(:server_endpoint) {Async::HTTP::Endpoint.parse("https://localhost:0", ssl_context: server_context, reuse_port: true)}
107-
let(:client_endpoint) {Async::HTTP::Endpoint.parse("https://localhost:0", ssl_context: client_context, reuse_port: true)}
99+
def make_server_endpoint(bound_endpoint)
100+
Async::IO::SSLEndpoint.new(super, ssl_context: server_context)
101+
end
102+
103+
def make_client_endpoint(bound_endpoint)
104+
Async::IO::SSLEndpoint.new(super, ssl_context: client_context)
105+
end
108106

109-
it_should_behave_like Async::HTTP::Body
107+
it_behaves_like ABody
110108
end

test/async/http/body/hijack.rb

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,44 @@
55

66
require 'async/http/body/hijack'
77

8-
RSpec.describe Async::HTTP::Body::Hijack do
9-
include_context Async::RSpec::Reactor
8+
require 'sus/fixtures/async'
9+
10+
describe Async::HTTP::Body::Hijack do
11+
include Sus::Fixtures::Async::ReactorContext
12+
13+
let(:body) do
14+
subject.wrap do |stream|
15+
3.times do
16+
stream.write(content)
17+
end
18+
stream.close
19+
end
20+
end
1021

1122
let(:content) {"Hello World!"}
1223

13-
describe '#call' do
24+
with '#call' do
1425
let(:stream) {Async::HTTP::Body::Writable.new}
1526

16-
subject do
17-
described_class.wrap do |stream|
18-
3.times do
19-
stream.write(content)
20-
end
21-
stream.close
22-
end
23-
end
24-
2527
it "should generate body using direct invocation" do
26-
subject.call(stream)
28+
body.call(stream)
2729

2830
3.times do
2931
expect(stream.read).to be == content
3032
end
3133

3234
expect(stream.read).to be_nil
33-
expect(stream).to be_empty
35+
expect(stream).to be(:empty?)
3436
end
3537

3638
it "should generate body using stream" do
3739
3.times do
38-
expect(subject.read).to be == content
40+
expect(body.read).to be == content
3941
end
4042

41-
expect(subject.read).to be_nil
43+
expect(body.read).to be_nil
4244

43-
expect(subject).to be_empty
45+
expect(body).to be(:empty?)
4446
end
4547
end
4648
end

test/async/http/body/pipe.rb

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,25 @@
88
require 'async/http/body/pipe'
99
require 'async/http/body/writable'
1010

11-
RSpec.describe Async::HTTP::Body::Pipe do
12-
let(:input) { Async::HTTP::Body::Writable.new }
13-
let(:pipe) { described_class.new(input) }
11+
require 'sus/fixtures/async'
12+
13+
describe Async::HTTP::Body::Pipe do
14+
let(:input) {Async::HTTP::Body::Writable.new}
15+
let(:pipe) {subject.new(input)}
1416

15-
let(:data) { 'Hello World!' }
17+
let(:data) {'Hello World!'}
1618

17-
describe '#to_io' do
18-
include_context Async::RSpec::Reactor
19+
with '#to_io' do
20+
include Sus::Fixtures::Async::ReactorContext
1921

22+
let(:input_write_duration) {0}
2023
let(:io) { pipe.to_io }
2124

22-
before do
23-
Async::Task.current.async do |task| # input writer task
25+
def before
26+
super
27+
28+
# input writer task
29+
Async do |task|
2430
first, second = data.split(' ')
2531
input.write("#{first} ")
2632
task.sleep(input_write_duration) if input_write_duration > 0
@@ -29,38 +35,35 @@
2935
end
3036
end
3137

32-
after { io.close }
33-
34-
shared_examples :returns_io_socket do
35-
it 'returns an io socket' do
36-
expect(io).to be_a(Async::IO::Socket)
37-
expect(io.read).to eq data
38-
end
38+
def aftrer
39+
io.close
40+
41+
super
3942
end
4043

41-
context 'when reading blocks' do
42-
let(:input_write_duration) { 0.01 }
43-
44-
include_examples :returns_io_socket
44+
it "returns an io socket" do
45+
expect(io).to be_a(Async::IO::Socket)
46+
expect(io.read).to be == data
4547
end
4648

47-
context 'when reading does not block' do
48-
let(:input_write_duration) { 0 }
49+
with 'blocking reads' do
50+
let(:input_write_duration) {0.01}
4951

50-
include_examples :returns_io_socket
52+
it 'returns an io socket' do
53+
expect(io.read).to be == data
54+
end
5155
end
5256
end
5357

54-
describe 'going out of reactor scope' do
55-
context 'when pipe is closed' do
56-
it 'finishes' do
57-
Async { pipe.close }
58-
end
58+
with 'reactor going out of scope' do
59+
it 'finishes' do
60+
# ensures pipe background tasks are transient
61+
Async{pipe}
5962
end
6063

61-
context 'when pipe is not closed' do
62-
it 'finishes' do # ensures pipe background tasks are transient
63-
Async { pipe }
64+
with 'closed pipe' do
65+
it 'finishes' do
66+
Async{pipe.close}
6467
end
6568
end
6669
end

0 commit comments

Comments
 (0)