summaryrefslogtreecommitdiff
path: root/vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit
diff options
context:
space:
mode:
authorBenjamin Sanders <ben@Benjamins-MacBook-Pro.local>2025-10-11 10:34:24 -0400
committerBenjamin Sanders <ben@Benjamins-MacBook-Pro.local>2025-10-11 10:34:24 -0400
commit5571dc766e2143e39762ff0b47c41d1c2e154f4c (patch)
treef4f124d314a7e76c04484515aa0fd1f2e271a601 /vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit
parent359f3309c97fc894b63e0a295c76ab298504d635 (diff)
Vendor bundled gems for deployment
Diffstat (limited to 'vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit')
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/framing_spec.rb298
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/handshake_spec.rb216
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/em-websocket-0.5.3/spec/unit/masking_spec.rb29
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