spec/stream_spec.rb in http-2-0.6.3 vs spec/stream_spec.rb in http-2-0.7.0

- old
+ new

@@ -10,12 +10,12 @@ it "should initiliaze all streams to IDLE" do @stream.state.should eq :idle end it "should set custom stream priority" do - stream = @client.new_stream(priority: 3) - stream.priority.should eq 3 + stream = @client.new_stream(weight: 3, dependency: 2, exclusive: true) + stream.weight.should eq 3 end context "reserved (local)" do before(:each) { @stream.send PUSH_PROMISE } @@ -53,12 +53,12 @@ @stream.receive RST_STREAM @stream.state.should eq :closed end it "should reprioritize stream on PRIORITY" do - @stream.receive PRIORITY.merge({priority: 30}) - @stream.priority.should eq 30 + expect { @stream.receive PRIORITY }.to_not raise_error + @stream.weight.should eq 20 end end context "reserved (remote)" do before(:each) { @stream.receive PUSH_PROMISE } @@ -93,12 +93,12 @@ @stream.receive RST_STREAM @stream.state.should eq :closed end it "should reprioritize stream on PRIORITY" do - @stream.send PRIORITY - @stream.priority.should eq 15 + expect { @stream.send PRIORITY }.to_not raise_error + @stream.weight.should eq 20 end end context "open" do before(:each) { @stream.receive HEADERS } @@ -114,21 +114,21 @@ expect { @stream.dup.receive type }.to_not raise_error end end it "should transition to half closed (local) if sending END_STREAM" do - [DATA, HEADERS, CONTINUATION].each do |frame| + [DATA, HEADERS].each do |frame| s, f = @stream.dup, frame.dup f[:flags] = [:end_stream] s.send f s.state.should eq :half_closed_local end end it "should transition to half closed (remote) if receiving END_STREAM" do - [DATA, HEADERS, CONTINUATION].each do |frame| + [DATA, HEADERS].each do |frame| s, f = @stream.dup, frame.dup f[:flags] = [:end_stream] s.receive f s.state.should eq :half_closed_remote @@ -171,12 +171,12 @@ sr.on(:active) { openr = true } sp.receive HEADERS sr.send HEADERS - openp.should be_true - openr.should be_true + openp.should be_truthy + openr.should be_truthy end it "should not emit :active on transition from open" do order, stream = [], @client.new_stream @@ -200,12 +200,12 @@ sr.on(:close) { closer = true } sp.receive RST_STREAM sr.close - closep.should be_true - closer.should be_true + closep.should be_truthy + closer.should be_truthy end it "should emit :close after frame is processed" do order, stream = [], @client.new_stream @@ -234,11 +234,11 @@ context "half closed (local)" do before(:each) { @stream.send HEADERS_END_STREAM } it "should raise error on attempt to send frames" do - (FRAME_TYPES - [RST_STREAM]).each do |frame| + (FRAME_TYPES - [PRIORITY, RST_STREAM]).each do |frame| expect { @stream.dup.send frame }.to raise_error StreamError end end it "should transition to closed on receipt of END_STREAM flag" do @@ -265,10 +265,15 @@ expect { @stream.receive WINDOW_UPDATE }.to_not raise_error expect { @stream.receive PRIORITY }.to_not raise_error @stream.state.should eq :half_closed_local end + it "should reprioritize stream on PRIORITY" do + expect { @stream.send PRIORITY }.to_not raise_error + @stream.weight.should eq 20 + end + it "should emit :half_close event on transition" do order = [] stream = @client.new_stream stream.on(:active) { order << :active } stream.on(:half_close) { order << :half_close } @@ -284,27 +289,27 @@ closed = false @stream.on(:close) { closed = true } @stream.receive RST_STREAM @stream.state.should eq :closed - closed.should be_true + closed.should be_truthy end end context "half closed (remote)" do before(:each) { @stream.receive HEADERS_END_STREAM } it "should raise STREAM_CLOSED error on reciept of frames" do - (FRAME_TYPES - [RST_STREAM, WINDOW_UPDATE]).each do |frame| + (FRAME_TYPES - [PRIORITY, RST_STREAM, WINDOW_UPDATE]).each do |frame| expect { @stream.dup.receive frame }.to raise_error(StreamClosed) end end it "should transition to closed if END_STREAM flag is sent" do - [DATA, HEADERS, CONTINUATION].each do |frame| + [DATA, HEADERS].each do |frame| s, f = @stream.dup, frame.dup f[:flags] = [:end_stream] s.on(:close) { s.state.should eq :closed } s.send f @@ -325,10 +330,15 @@ it "should ignore received WINDOW_UPDATE frames" do expect { @stream.receive WINDOW_UPDATE }.to_not raise_error @stream.state.should eq :half_closed_remote end + it "should reprioritize stream on PRIORITY" do + expect { @stream.receive PRIORITY }.to_not raise_error + @stream.weight.should eq 20 + end + it "should emit :half_close event on transition" do order = [] stream = @client.new_stream stream.on(:active) { order << :active } stream.on(:half_close) { order << :half_close } @@ -344,11 +354,11 @@ closed = false @stream.on(:close) { closed = true } @stream.close @stream.state.should eq :closed - closed.should be_true + closed.should be_truthy end end context "closed" do context "remote closed stream" do @@ -356,32 +366,40 @@ @stream.send HEADERS_END_STREAM # half closed local @stream.receive HEADERS_END_STREAM # closed by remote end it "should raise STREAM_CLOSED on attempt to send frames" do - (FRAME_TYPES - [RST_STREAM]).each do |frame| + (FRAME_TYPES - [PRIORITY, RST_STREAM]).each do |frame| expect { @stream.dup.send frame }.to raise_error(StreamClosed) end end it "should raise STREAM_CLOSED on receipt of frame" do - (FRAME_TYPES - [RST_STREAM]).each do |frame| + (FRAME_TYPES - [PRIORITY, RST_STREAM, WINDOW_UPDATE]).each do |frame| expect { @stream.dup.receive frame }.to raise_error(StreamClosed) end end - it "should allow RST_STREAM to be sent" do + it "should allow PRIORITY, RST_STREAM to be sent" do + expect { @stream.send PRIORITY }.to_not raise_error expect { @stream.send RST_STREAM }.to_not raise_error end - it "should not send RST_STREAM on receipt of RST_STREAM" do + it "should allow PRIORITY, RST_STREAM to be received" do + expect { @stream.receive PRIORITY }.to_not raise_error expect { @stream.receive RST_STREAM }.to_not raise_error end + + it "should reprioritize stream on PRIORITY" do + expect { @stream.receive PRIORITY }.to_not raise_error + @stream.weight.should eq 20 + end + end context "local closed via RST_STREAM frame" do before(:each) do @stream.send HEADERS # open @@ -405,96 +423,101 @@ # RST_STREAM. PUSH_PROMISE causes a stream to become "reserved". # ... # We're auto RST'ing PUSH streams in connection class, hence # skipping this transition for now. #end + end - context "local closed via END_STREAM flag" do - before(:each) do - @stream.send HEADERS # open - @stream.send DATA # contains end_stream flag - end + # FIXME: Isn't this test same as "half closed (local)"? + # context "local closed via END_STREAM flag" do + # before(:each) do + # @stream.send HEADERS # open + # @stream.send DATA # contains end_stream flag + # end - it "should ignore received frames" do - FRAME_TYPES.each do |frame| - expect { @stream.dup.receive frame }.to_not raise_error - end - end - end + # it "should ignore received frames" do + # FRAME_TYPES.each do |frame| + # expect { @stream.dup.receive frame }.to_not raise_error + # end + # end + # end + end end # end stream states + # TODO: add test cases to ensure on(:priority) emitted after close + context "flow control" do it "should initialize to default flow control window" do - @stream.window.should eq DEFAULT_FLOW_WINDOW + @stream.remote_window.should eq DEFAULT_FLOW_WINDOW end it "should update window size on DATA frames only" do @stream.send HEADERS # go to open - @stream.window.should eq DEFAULT_FLOW_WINDOW + @stream.remote_window.should eq DEFAULT_FLOW_WINDOW (FRAME_TYPES - [DATA,PING,GOAWAY,SETTINGS]).each do |frame| s = @stream.dup s.send frame - s.window.should eq DEFAULT_FLOW_WINDOW + s.remote_window.should eq DEFAULT_FLOW_WINDOW end @stream.send DATA - @stream.window.should eq DEFAULT_FLOW_WINDOW - DATA[:payload].bytesize + @stream.remote_window.should eq DEFAULT_FLOW_WINDOW - DATA[:payload].bytesize end it "should update window size on receipt of WINDOW_UPDATE" do @stream.send HEADERS @stream.send DATA @stream.receive WINDOW_UPDATE - @stream.window.should eq ( + @stream.remote_window.should eq ( DEFAULT_FLOW_WINDOW - DATA[:payload].bytesize + WINDOW_UPDATE[:increment] ) end it "should observe session flow control" do settings, data = SETTINGS.dup, DATA.dup - settings[:payload] = { settings_initial_window_size: 1000 } + settings[:payload] = [[:settings_initial_window_size, 1000]] settings[:stream] = 0 framer = Framer.new @client << framer.generate(settings) s1 = @client.new_stream s1.send HEADERS s1.send data.merge({payload: "x" * 900, flags: []}) - s1.window.should eq 100 + s1.remote_window.should eq 100 s1.send data.merge({payload: "x" * 200}) - s1.window.should eq 0 + s1.remote_window.should eq 0 s1.buffered_amount.should eq 100 @client << framer.generate(WINDOW_UPDATE.merge({ stream: s1.id, increment: 1000 })) s1.buffered_amount.should eq 0 - s1.window.should eq 900 + s1.remote_window.should eq 900 end end context "client API" do it ".reprioritize should emit PRIORITY frame" do @stream.should_receive(:send) do |frame| frame[:type].should eq :priority - frame[:priority].should eq 30 + frame[:weight].should eq 30 end - @stream.reprioritize 30 + @stream.reprioritize weight: 30 end it ".reprioritize should raise error if invoked by server" do srv = Server.new stream = srv.new_stream - expect { stream.reprioritize(10) }.to raise_error(StreamError) + expect { stream.reprioritize(weight: 10) }.to raise_error(StreamError) end it ".headers should emit HEADERS frames" do payload = { ':method' => 'GET', @@ -526,11 +549,11 @@ end @stream.data("text") end it ".data should split large DATA frames" do - data = "x" * HTTP2::MAX_FRAME_SIZE * 2 + data = "x" * 16384 * 2 @stream.stub(:send) @stream.should_receive(:send).exactly(3).times @stream.data(data + "x") end @@ -562,11 +585,11 @@ @client.on(:frame) {|bytes| @srv << bytes } @client_stream = @client.new_stream end it "should emit received headers via on(:headers)" do - headers, recv = {"header" => "value"}, nil + headers, recv = [["header", "value"]], nil @srv.on(:stream) do |stream| stream.on(:headers) {|h| recv = h} end @client_stream.headers(headers) @@ -583,30 +606,34 @@ @client_stream.headers({"key" => "value"}) @client_stream.data(payload) end - it "should emit received priority via on(:priority)" do - new_priority, recv = 15, 0 + it "should emit received priority parameters via on(:priority)" do + new_weight, new_dependency = 15, @client_stream.id + 2 + callback_called = false @srv.on(:stream) do |stream| stream.on(:priority) do |pri| - pri.should eq new_priority + callback_called = true + pri.is_a?(Hash).should be + pri[:weight].should eq new_weight + pri[:dependency].should eq new_dependency end end @client_stream.headers({"key" => "value"}) - @client_stream.reprioritize(new_priority) + @client_stream.reprioritize(weight: new_weight, dependency: new_dependency) + callback_called.should be end context "push" do before(:each) do @srv.on(:frame) {|bytes| @client << bytes } @srv.on(:stream) do |stream| @server_stream = stream end - # @srv << @frm.generate(SETTINGS) @client_stream.headers({"key" => "value"}) end it ".promise should emit server initiated stream" do push = nil @@ -641,32 +668,32 @@ order.should eq [:reserved, :active, :half_close, :close] end it "client: headers > active > headers > .. > data > close" do - order, headers = [], {} + order, headers = [], [] @client.on(:promise) do |push| order << :reserved push.on(:active) { order << :active } push.on(:data) { order << :data } push.on(:half_close){ order << :half_close } push.on(:close) { order << :close } push.on(:headers) do |h| order << :headers - headers.merge!(h) + headers += h end push.id.should be_even end @server_stream.promise({"key" => "val"}) do |push| push.headers("key2" => "val2") push.data("somedata") end - headers.should eq({"key" => "val", "key2" => "val2"}) + headers.should eq([["key", "val"], ["key2", "val2"]]) order.should eq [:reserved, :headers, :active, :headers, :half_close, :data, :close] end end