diff options
Diffstat (limited to 'vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit')
3 files changed, 543 insertions, 0 deletions
diff --git a/vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/framing_spec.rb b/vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/framing_spec.rb new file mode 100644 index 0000000..b2a8d33 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/framing_spec.rb @@ -0,0 +1,298 @@ +# encoding: BINARY + +require 'helper' + +describe EM::WebSocket::Framing03 do + class FramingContainer + include EM::WebSocket::Framing03 + + def initialize + @connection = Object.new + def @connection.max_frame_size + 1000000 + end + end + + def <<(data) + @data << data + process_data + end + + def debug(*args); end + end + + before :each do + @f = FramingContainer.new + @f.initialize_framing + end + + describe "basic examples" do + it "connection close" do + @f.should_receive(:message).with(:close, '', '') + @f << 0b00000001 + @f << 0b00000000 + end + + it "ping" do + @f.should_receive(:message).with(:ping, '', '') + @f << 0b00000010 + @f << 0b00000000 + end + + it "pong" do + @f.should_receive(:message).with(:pong, '', '') + @f << 0b00000011 + @f << 0b00000000 + end + + it "text" do + @f.should_receive(:message).with(:text, '', 'foo') + @f << 0b00000100 + @f << 0b00000011 + @f << 'foo' + end + + it "Text in two frames" do + @f.should_receive(:message).with(:text, '', 'hello world') + @f << 0b10000100 + @f << 0b00000110 + @f << "hello " + @f << 0b00000000 + @f << 0b00000101 + @f << "world" + end + + it "2 byte extended payload length text frame" do + data = 'a' * 256 + @f.should_receive(:message).with(:text, '', data) + @f << 0b00000100 # Single frame, text + @f << 0b01111110 # Length 126 (so read 2 bytes) + @f << 0b00000001 # Two bytes in network byte order (256) + @f << 0b00000000 + @f << data + end + end + + # These examples are straight from the spec + # http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-03#section-4.6 + describe "examples from the spec" do + it "a single-frame text message" do + @f.should_receive(:message).with(:text, '', 'Hello') + @f << "\x04\x05Hello" + end + + it "a fragmented text message" do + @f.should_receive(:message).with(:text, '', 'Hello') + @f << "\x84\x03Hel" + @f << "\x00\x02lo" + end + + it "Ping request and response" do + @f.should_receive(:message).with(:ping, '', 'Hello') + @f << "\x02\x05Hello" + end + + it "256 bytes binary message in a single frame" do + data = "a"*256 + @f.should_receive(:message).with(:binary, '', data) + @f << "\x05\x7E\x01\x00" + data + end + + it "64KiB binary message in a single frame" do + data = "a"*65536 + @f.should_receive(:message).with(:binary, '', data) + @f << "\x05\x7F\x00\x00\x00\x00\x00\x01\x00\x00" + data + end + end + + describe "other tests" do + it "should accept a fragmented unmasked text message in 3 frames" do + @f.should_receive(:message).with(:text, '', 'Hello world') + @f << "\x84\x03Hel" + @f << "\x80\x02lo" + @f << "\x00\x06 world" + end + end + + describe "error cases" do + it "should raise an exception on continuation frame without preceeding more frame" do + lambda { + @f << 0b00000000 # Single frame, continuation + @f << 0b00000001 # Length 1 + @f << 'f' + }.should raise_error(EM::WebSocket::WebSocketError, 'Continuation frame not expected') + end + end +end + +# These examples are straight from the spec +# http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-03#section-4.6 +describe EM::WebSocket::Framing04 do + class FramingContainer04 + include EM::WebSocket::Framing04 + + def initialize + @connection = Object.new + def @connection.max_frame_size + 1000000 + end + end + + def <<(data) + @data << data + process_data + end + + def debug(*args); end + end + + before :each do + @f = FramingContainer04.new + @f.initialize_framing + end + + describe "examples from the spec" do + it "a single-frame text message" do + @f.should_receive(:message).with(:text, '', 'Hello') + @f << "\x84\x05\x48\x65\x6c\x6c\x6f" # "\x84\x05Hello" + end + + it "a fragmented text message" do + @f.should_receive(:message).with(:text, '', 'Hello') + @f << "\x04\x03Hel" + @f << "\x80\x02lo" + end + + it "Ping request" do + @f.should_receive(:message).with(:ping, '', 'Hello') + @f << "\x82\x05Hello" + end + + it "a pong response" do + @f.should_receive(:message).with(:pong, '', 'Hello') + @f << "\x83\x05Hello" + end + + it "256 bytes binary message in a single frame" do + data = "a"*256 + @f.should_receive(:message).with(:binary, '', data) + @f << "\x85\x7E\x01\x00" + data + end + + it "64KiB binary message in a single frame" do + data = "a"*65536 + @f.should_receive(:message).with(:binary, '', data) + @f << "\x85\x7F\x00\x00\x00\x00\x00\x01\x00\x00" + data + end + end + + describe "other tests" do + it "should accept a fragmented unmasked text message in 3 frames" do + @f.should_receive(:message).with(:text, '', 'Hello world') + @f << "\x04\x03Hel" + @f << "\x00\x02lo" + @f << "\x80\x06 world" + end + end +end + +describe EM::WebSocket::Framing07 do + class FramingContainer07 + include EM::WebSocket::Framing07 + + def initialize + @connection = Object.new + def @connection.max_frame_size + 1000000 + end + end + + def <<(data) + @data << data + process_data + end + + def debug(*args); end + end + + before :each do + @f = FramingContainer07.new + @f.initialize_framing + end + + # These examples are straight from the spec + # http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07#section-4.6 + describe "examples from the spec" do + it "a single-frame unmakedtext message" do + @f.should_receive(:message).with(:text, '', 'Hello') + @f << "\x81\x05\x48\x65\x6c\x6c\x6f" # "\x84\x05Hello" + end + + it "a single-frame masked text message" do + @f.should_receive(:message).with(:text, '', 'Hello') + @f << "\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58" # "\x84\x05Hello" + end + + it "a fragmented unmasked text message" do + @f.should_receive(:message).with(:text, '', 'Hello') + @f << "\x01\x03Hel" + @f << "\x80\x02lo" + end + + it "Ping request" do + @f.should_receive(:message).with(:ping, '', 'Hello') + @f << "\x89\x05Hello" + end + + it "a pong response" do + @f.should_receive(:message).with(:pong, '', 'Hello') + @f << "\x8a\x05Hello" + end + + it "256 bytes binary message in a single unmasked frame" do + data = "a"*256 + @f.should_receive(:message).with(:binary, '', data) + @f << "\x82\x7E\x01\x00" + data + end + + it "64KiB binary message in a single unmasked frame" do + data = "a"*65536 + @f.should_receive(:message).with(:binary, '', data) + @f << "\x82\x7F\x00\x00\x00\x00\x00\x01\x00\x00" + data + end + end + + describe "other tests" do + it "should raise a WSProtocolError if an invalid frame type is requested" do + lambda { + # Opcode 3 is not supported by this draft + @f << "\x83\x05Hello" + }.should raise_error(EventMachine::WebSocket::WSProtocolError, "Unknown opcode 3") + end + + it "should accept a fragmented unmasked text message in 3 frames" do + @f.should_receive(:message).with(:text, '', 'Hello world') + @f << "\x01\x03Hel" + @f << "\x00\x02lo" + @f << "\x80\x06 world" + end + + it "should raise if non-fin frame is followed by a non-continuation data frame (continuation frame would be expected)" do + lambda { + @f << 0b00000001 # Not fin, text + @f << 0b00000001 # Length 1 + @f << 'f' + @f << 0b10000001 # fin, text (continutation expected) + @f << 0b00000001 # Length 1 + @f << 'b' + }.should raise_error(EM::WebSocket::WebSocketError, 'Continuation frame expected') + end + + it "should raise on non-fin control frames (control frames must not be fragmented)" do + lambda { + @f << 0b00001010 # Not fin, pong (opcode 10) + @f << 0b00000000 # Length 1 + }.should raise_error(EM::WebSocket::WebSocketError, 'Control frames must not be fragmented') + end + end +end diff --git a/vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/handshake_spec.rb b/vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/handshake_spec.rb new file mode 100644 index 0000000..2754ba7 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/handshake_spec.rb @@ -0,0 +1,216 @@ +require 'helper' + +describe EM::WebSocket::Handshake do + def handshake(request, secure = false) + handshake = EM::WebSocket::Handshake.new(secure) + handshake.receive_data(format_request(request)) + handshake + end + + before :each do + @request = { + :port => 80, + :method => "GET", + :path => "/demo", + :headers => { + 'Host' => 'example.com', + 'Connection' => 'Upgrade', + 'Sec-WebSocket-Key2' => '12998 5 Y3 1 .P00', + 'Sec-WebSocket-Protocol' => 'sample', + 'Upgrade' => 'WebSocket', + 'Sec-WebSocket-Key1' => '4 @1 46546xW%0l 1 5', + 'Origin' => 'http://example.com' + }, + :body => '^n:ds[4U' + } + @secure_request = @request.merge(:port => 443) + + @response = { + :headers => { + "Upgrade" => "WebSocket", + "Connection" => "Upgrade", + "Sec-WebSocket-Location" => "ws://example.com/demo", + "Sec-WebSocket-Origin" => "http://example.com", + "Sec-WebSocket-Protocol" => "sample" + }, + :body => "8jKS\'y:G*Co,Wxa-" + } + @secure_response = @response.merge(:headers => @response[:headers].merge('Sec-WebSocket-Location' => "wss://example.com/demo")) + end + + it "should handle good request" do + handshake(@request).should succeed_with_upgrade(@response) + end + + it "should handle good request to secure default port if secure mode is enabled" do + handshake(@secure_request, true). + should succeed_with_upgrade(@secure_response) + end + + it "should not handle good request to secure default port if secure mode is disabled" do + handshake(@secure_request, false). + should_not succeed_with_upgrade(@secure_response) + end + + it "should handle good request on nondefault port" do + @request[:port] = 8081 + @request[:headers]['Host'] = 'example.com:8081' + @response[:headers]['Sec-WebSocket-Location'] = + 'ws://example.com:8081/demo' + + handshake(@request).should succeed_with_upgrade(@response) + end + + it "should handle good request to secure nondefault port" do + @secure_request[:port] = 8081 + @secure_request[:headers]['Host'] = 'example.com:8081' + @secure_response[:headers]['Sec-WebSocket-Location'] = 'wss://example.com:8081/demo' + + handshake(@secure_request, true). + should succeed_with_upgrade(@secure_response) + end + + it "should handle good request with no protocol" do + @request[:headers].delete('Sec-WebSocket-Protocol') + @response[:headers].delete("Sec-WebSocket-Protocol") + + handshake(@request).should succeed_with_upgrade(@response) + end + + it "should handle extra headers by simply ignoring them" do + @request[:headers]['EmptyValue'] = "" + @request[:headers]['AKey'] = "AValue" + + handshake(@request).should succeed_with_upgrade(@response) + end + + it "should raise error on HTTP request" do + @request[:headers] = { + 'Host' => 'www.google.com', + 'User-Agent' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 GTB6 GTBA', + 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Accept-Language' => 'en-us,en;q=0.5', + 'Accept-Encoding' => 'gzip,deflate', + 'Accept-Charset' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', + 'Keep-Alive' => '300', + 'Connection' => 'keep-alive', + } + + handshake(@request).should fail_with_error(EM::WebSocket::HandshakeError) + end + + it "should raise error on wrong method" do + @request[:method] = 'POST' + + handshake(@request).should fail_with_error(EM::WebSocket::HandshakeError) + end + + it "should raise error if upgrade header incorrect" do + @request[:headers]['Upgrade'] = 'NonWebSocket' + + handshake(@request).should fail_with_error(EM::WebSocket::HandshakeError) + end + + it "should raise error if Sec-WebSocket-Protocol is empty" do + @request[:headers]['Sec-WebSocket-Protocol'] = '' + + handshake(@request).should fail_with_error(EM::WebSocket::HandshakeError) + end + + %w[Sec-WebSocket-Key1 Sec-WebSocket-Key2].each do |header| + it "should raise error if #{header} has zero spaces" do + @request[:headers][header] = 'nospaces' + + handshake(@request). + should fail_with_error(EM::WebSocket::HandshakeError, 'Websocket Key1 or Key2 does not contain spaces - this is a symptom of a cross-protocol attack') + end + end + + it "should raise error if Sec-WebSocket-Key1 is missing" do + @request[:headers].delete("Sec-WebSocket-Key1") + + # The error message isn't correct since key1 is used to heuristically + # determine the protocol version in use, however this test at least checks + # that the handshake does correctly fail + handshake(@request). + should fail_with_error(EM::WebSocket::HandshakeError, 'Extra bytes after header') + end + + it "should raise error if Sec-WebSocket-Key2 is missing" do + @request[:headers].delete("Sec-WebSocket-Key2") + + handshake(@request). + should fail_with_error(EM::WebSocket::HandshakeError, 'WebSocket key1 or key2 is missing') + end + + it "should raise error if spaces do not divide numbers in Sec-WebSocket-Key* " do + @request[:headers]['Sec-WebSocket-Key2'] = '12998 5 Y3 1.P00' + + handshake(@request). + should fail_with_error(EM::WebSocket::HandshakeError, 'Invalid Key "12998 5 Y3 1.P00"') + end + + it "should raise error if the HTTP header is empty" do + handshake = EM::WebSocket::Handshake.new(false) + handshake.receive_data("\r\n\r\nfoobar") + + handshake. + should fail_with_error(EM::WebSocket::HandshakeError, 'Invalid HTTP header: Could not parse data entirely (4 != 10)') + end + + # This might seems crazy, but very occasionally we saw multiple "Upgrade: + # WebSocket" headers in the wild. RFC 4.2.1 isn't particularly clear on this + # point, so for now I have decided not to accept --@mloughran + it "should raise error on multiple upgrade headers" do + handshake = EM::WebSocket::Handshake.new(false) + + # Add a duplicate upgrade header + headers = format_request(@request) + upgrade_header = "Upgrade: WebSocket\r\n" + headers.gsub!(upgrade_header, "#{upgrade_header}#{upgrade_header}") + + handshake.receive_data(headers) + + handshake.errback { |e| + e.class.should == EM::WebSocket::HandshakeError + e.message.should == 'Invalid upgrade header: ["WebSocket", "WebSocket"]' + } + end + + it "should cope with requests where the header is split" do + request = format_request(@request) + incomplete_request = request[0...(request.length / 2)] + rest = request[(request.length / 2)..-1] + handshake = EM::WebSocket::Handshake.new(false) + handshake.receive_data(incomplete_request) + + handshake.instance_variable_get(:@deferred_status).should == nil + + # Send the remaining header + handshake.receive_data(rest) + + handshake(@request).should succeed_with_upgrade(@response) + end + + it "should cope with requests where the third key is split" do + request = format_request(@request) + # Removes last two bytes of the third key + incomplete_request = request[0..-3] + rest = request[-2..-1] + handshake = EM::WebSocket::Handshake.new(false) + handshake.receive_data(incomplete_request) + + handshake.instance_variable_get(:@deferred_status).should == nil + + # Send the remaining third key + handshake.receive_data(rest) + + handshake(@request).should succeed_with_upgrade(@response) + end + + it "should fail if the request URI is invalid" do + @request[:path] = "/%" + handshake(@request).should \ + fail_with_error(EM::WebSocket::HandshakeError, 'Invalid request URI: /%') + end +end diff --git a/vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/masking_spec.rb b/vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/masking_spec.rb new file mode 100644 index 0000000..065aa95 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/masking_spec.rb @@ -0,0 +1,29 @@ +# encoding: BINARY + +require 'helper' + +describe EM::WebSocket::MaskedString do + it "should allow reading 4 byte mask and unmasking byte / bytes" do + t = EM::WebSocket::MaskedString.new("\x00\x00\x00\x01\x00\x01\x00\x01") + t.read_mask + t.getbyte(3).should == 0x00 + t.getbytes(4, 4).should == "\x00\x01\x00\x00" + t.getbytes(5, 3).should == "\x01\x00\x00" + end + + it "should return nil from getbyte if index requested is out of range" do + t = EM::WebSocket::MaskedString.new("\x00\x00\x00\x00\x53") + t.read_mask + t.getbyte(4).should == 0x53 + t.getbyte(5).should == nil + end + + it "should allow switching masking on and off" do + t = EM::WebSocket::MaskedString.new("\x02\x00\x00\x00\x03") + t.getbyte(4).should == 0x03 + t.read_mask + t.getbyte(4).should == 0x01 + t.unset_mask + t.getbyte(4).should == 0x03 + end +end |
