socky-server 0.4.1 → 0.5.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. data/.gitignore +0 -4
  2. data/.travis.yml +6 -0
  3. data/CHANGELOG.md +11 -5
  4. data/Gemfile +2 -0
  5. data/README.md +47 -68
  6. data/Rakefile +5 -7
  7. data/config.ru +19 -0
  8. data/example/config.yml +4 -0
  9. data/lib/socky/server.rb +23 -0
  10. data/lib/socky/server/application.rb +51 -0
  11. data/lib/socky/server/channel.rb +30 -0
  12. data/lib/socky/server/channel/base.rb +80 -0
  13. data/lib/socky/server/channel/presence.rb +49 -0
  14. data/lib/socky/server/channel/private.rb +44 -0
  15. data/lib/socky/server/channel/public.rb +43 -0
  16. data/lib/socky/server/channel/stub.rb +17 -0
  17. data/lib/socky/server/config.rb +52 -0
  18. data/lib/socky/server/connection.rb +66 -0
  19. data/lib/socky/server/http.rb +95 -0
  20. data/lib/socky/server/logger.rb +24 -0
  21. data/lib/socky/server/message.rb +35 -0
  22. data/lib/socky/server/misc.rb +18 -0
  23. data/lib/socky/server/version.rb +5 -0
  24. data/lib/socky/server/websocket.rb +43 -0
  25. data/socky-server.gemspec +5 -7
  26. data/spec/fixtures/example_config.yml +3 -0
  27. data/spec/integration/ws_channels_spec.rb +144 -0
  28. data/spec/integration/ws_connection_spec.rb +48 -0
  29. data/spec/integration/ws_presence_spec.rb +118 -0
  30. data/spec/integration/ws_rights_spec.rb +133 -0
  31. data/spec/spec_helper.rb +24 -2
  32. data/spec/support/websocket_application.rb +14 -0
  33. data/spec/unit/socky/server/application_spec.rb +54 -0
  34. data/spec/unit/socky/server/config_spec.rb +50 -0
  35. data/spec/unit/socky/server/connection_spec.rb +67 -0
  36. data/spec/unit/socky/server/message_spec.rb +64 -0
  37. metadata +93 -126
  38. data/bin/socky +0 -5
  39. data/lib/em-websocket_hacks.rb +0 -15
  40. data/lib/socky.rb +0 -75
  41. data/lib/socky/connection.rb +0 -137
  42. data/lib/socky/connection/authentication.rb +0 -99
  43. data/lib/socky/connection/finders.rb +0 -67
  44. data/lib/socky/message.rb +0 -85
  45. data/lib/socky/misc.rb +0 -74
  46. data/lib/socky/net_request.rb +0 -27
  47. data/lib/socky/options.rb +0 -39
  48. data/lib/socky/options/config.rb +0 -79
  49. data/lib/socky/options/parser.rb +0 -93
  50. data/lib/socky/runner.rb +0 -95
  51. data/spec/em-websocket_spec.rb +0 -36
  52. data/spec/files/default.yml +0 -18
  53. data/spec/files/invalid.yml +0 -1
  54. data/spec/socky/connection/authentication_spec.rb +0 -183
  55. data/spec/socky/connection/finders_spec.rb +0 -188
  56. data/spec/socky/connection_spec.rb +0 -151
  57. data/spec/socky/message_spec.rb +0 -102
  58. data/spec/socky/misc_spec.rb +0 -74
  59. data/spec/socky/net_request_spec.rb +0 -42
  60. data/spec/socky/options/config_spec.rb +0 -72
  61. data/spec/socky/options/parser_spec.rb +0 -76
  62. data/spec/socky/options_spec.rb +0 -60
  63. data/spec/socky/runner_spec.rb +0 -88
  64. data/spec/socky_spec.rb +0 -89
  65. data/spec/support/stallion.rb +0 -96
@@ -1,5 +1,27 @@
1
1
  require 'rubygems'
2
2
  require 'rspec'
3
3
 
4
- require 'socky'
5
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
4
+ require 'socky/server'
5
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
6
+
7
+ def mock_websocket(application)
8
+ env = {}
9
+ env['PATH_INFO'] = '/websocket/' + application
10
+ connection = Socky::Server::WebSocket.new.call(env)
11
+ connection.stub!(:send_data)
12
+ connection
13
+ end
14
+
15
+ def mock_connection(application)
16
+ websocket = mock_websocket(application)
17
+
18
+ env = { 'PATH_INFO' => '/websocket/' + application }
19
+ websocket.on_open(env)
20
+ end
21
+
22
+ def auth_token(socket, channel_name, remains = {})
23
+ Socky::Authenticator.authenticate({
24
+ 'connection_id' => socket.connection.id,
25
+ 'channel' => channel_name
26
+ }.merge(remains), :allow_changing_rights => true, :secret => 'test_secret')['auth']
27
+ end
@@ -0,0 +1,14 @@
1
+ Rack::WebSocket::Application.class_eval do
2
+ def call(env)
3
+ @env = env
4
+ return self
5
+ end
6
+
7
+ def send_data(data)
8
+ true
9
+ end
10
+
11
+ def close_websocket
12
+ on_close(@env)
13
+ end
14
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Socky::Server::Application do
4
+
5
+ context "#find" do
6
+ it "should return nil if provided application doesn't exists" do
7
+ described_class.find('invalid').should be_nil
8
+ end
9
+ it "should return application if exists" do
10
+ begin
11
+ instance = described_class.new('some_app', 'some_secret')
12
+ described_class.find('some_app').should equal(instance)
13
+ ensure
14
+ described_class.list.delete('some_app')
15
+ end
16
+ end
17
+ end
18
+
19
+ context "#new" do
20
+ it "should save gived application on list" do
21
+ described_class.list.delete('some_app') # Strange bugs in ree
22
+ instance = described_class.new('some_app', 'some_secret')
23
+ described_class.list.delete('some_app').should equal(instance)
24
+ end
25
+ it "should not duplicate already exisiting apps" do
26
+ instance1 = described_class.new('some_app', 'some_secret')
27
+ instance2 = described_class.new('some_app', 'some_other_secret')
28
+ described_class.list.delete('some_app').should equal(instance1)
29
+ described_class.list.keys.should be_empty
30
+ end
31
+ end
32
+
33
+ context "instance" do
34
+ subject { described_class.new('some_app', 'some_secret') }
35
+
36
+ its(:name) { should eql('some_app') }
37
+ its(:secret) { should eql('some_secret') }
38
+ its(:connections) { should eql({}) }
39
+
40
+ let(:connection) { mock(Socky::Server::Connection, :id => 'some_id') }
41
+
42
+ it "should be able to add connection to list" do
43
+ subject.add_connection(connection)
44
+ subject.connections[connection.id].should equal(connection)
45
+ end
46
+ it "should be able to remove connection from list" do
47
+ subject.add_connection(connection)
48
+ subject.connections[connection.id].should equal(connection)
49
+ subject.remove_connection(connection)
50
+ subject.connections[connection.id].should be_nil
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe Socky::Server::Config do
4
+
5
+ context "#debug" do
6
+ it "should enable logger when true provided" do
7
+ Socky::Server::Logger.should_receive(:enabled=).with(true)
8
+ described_class.new(:debug => true)
9
+ end
10
+ it "should disable logger when false provided" do
11
+ Socky::Server::Logger.should_receive(:enabled=).with(false)
12
+ described_class.new(:debug => false)
13
+ end
14
+ end
15
+
16
+ context "#applications" do
17
+ it "should raise if param is not hash" do
18
+ lambda { described_class.new(:applications => "invalid") }.should raise_error ArgumentError, 'expected Hash'
19
+ end
20
+ it "should create application if hash provided" do
21
+ Socky::Server::Application.should_receive(:new).with('test_app','test_secret')
22
+ described_class.new(:applications => {'test_app' => 'test_secret'})
23
+ end
24
+ it "should convert application name to string if provided in other type" do
25
+ Socky::Server::Application.should_receive(:new).with('1','test_secret')
26
+ described_class.new(:applications => {1 => 'test_secret'})
27
+ end
28
+ it "should convert application secret to string if provided in other type" do
29
+ Socky::Server::Application.should_receive(:new).with('test_app','1')
30
+ described_class.new(:applications => {'test_app' => 1})
31
+ end
32
+ end
33
+
34
+ context "#config_file" do
35
+ it "should raise if non-string provided" do
36
+ lambda { described_class.new(:config_file => 123) }.should raise_error ArgumentError, 'expected String'
37
+ end
38
+ it "should raise if provided file doesn't exists" do
39
+ lambda { described_class.new(:config_file => 'invalid.yml') }.should raise_error ArgumentError, 'config file not found: invalid.yml'
40
+ end
41
+ it "should raise on invalid config file" do
42
+ lambda { described_class.new(:config_file => File.expand_path(__FILE__)) }.should raise_error ArgumentError, 'invalid config file'
43
+ end
44
+ it "should read example config file and set attributes" do
45
+ Socky::Server::Logger.should_receive(:enabled=).with(true)
46
+ Socky::Server::Application.should_receive(:new).with('some_test_app','some_test_secret')
47
+ described_class.new(:config_file => File.expand_path(File.dirname(__FILE__)) + '/../../../fixtures/example_config.yml')
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Socky::Server::Connection do
4
+
5
+ let(:websocket) { mock_websocket('test_app') }
6
+ before { @application = Socky::Server::Application.new('test_app', 'test_secret') }
7
+ after { Socky::Server::Application.list.delete(@application.name) }
8
+
9
+ context "#new" do
10
+ it "should assign valid application" do
11
+ instance = described_class.new(websocket, @application.name)
12
+ instance.application.should eql(@application)
13
+ end
14
+ it "should not assign application if not known" do
15
+ instance = described_class.new(websocket, 'unknown_app')
16
+ instance.application.should eql(nil)
17
+ end
18
+ it "should assign id" do
19
+ instance = described_class.new(websocket, @application.name)
20
+ instance.id.should_not be_nil
21
+ end
22
+ it "should add itself to application connection list" do
23
+ instance = described_class.new(websocket, @application.name)
24
+ @application.connections[instance.id].should equal(instance)
25
+ end
26
+ it "should send initialiation status" do
27
+ websocket.should_receive(:send_data)
28
+ instance = described_class.new(websocket, @application.name)
29
+ end
30
+ end
31
+
32
+ context "instance" do
33
+ subject { described_class.new(websocket, @application.name) }
34
+
35
+ its(:channels) { should eql({}) }
36
+
37
+ context "#initialization_status" do
38
+ it "should return confirmation when application is set" do
39
+ subject.initialization_status.should eql({ 'event' => 'socky:connection:established', 'connection_id' => subject.id })
40
+ end
41
+ it "should return 'unknown app' when application is not set" do
42
+ subject.application = nil
43
+ subject.initialization_status.should eql({ 'event' => 'socky:connection:error', 'reason' => 'refused' })
44
+ end
45
+ end
46
+
47
+ it "#send_data should send using provided websocket" do
48
+ websocket.should_receive(:send_data).with({:some => 'data'})
49
+ subject.send_data(:some => 'data')
50
+ end
51
+
52
+ context "#destroy" do
53
+ it "should remove itself from application connection list" do
54
+ subject.destroy
55
+ @application.connections[subject.id].should be_nil
56
+ end
57
+ it "should remove itself from channels list" do
58
+ channels = subject.channels.dup
59
+ subject.destroy
60
+ channels.each do |channel|
61
+ channel.subscribers[subject.id].should be_nil
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Socky::Server::Message do
4
+
5
+ let(:application) { Socky::Server::Application.new('some_app', 'some_secret') }
6
+ let(:connection) { mock_connection(application.name) }
7
+ let(:channel) { mock(Socky::Server::Channel::Base, :subscribe => nil, :unsubscribe => nil, :deliver => nil) }
8
+ before { Socky::Server::Channel.stub!(:find_or_create).and_return(channel)}
9
+
10
+ context "#new" do
11
+ it "should get valid instance when json provided" do
12
+ instance = described_class.new(connection, {'event' => 'some_event'}.to_json)
13
+ instance.event.should eql('some_event')
14
+ end
15
+ it "should get empty instance when non-json provided" do
16
+ instance = described_class.new(connection, 'event=some_event')
17
+ instance.event.should eql('')
18
+ end
19
+ end
20
+
21
+ context "instance" do
22
+ subject { described_class.new( connection, {
23
+ 'event' => 'some_event',
24
+ 'channel' => 'some_channel',
25
+ 'data' => 'some_user_data',
26
+ 'auth' => 'some_auth',
27
+ 'read' => 'read_value',
28
+ 'write' => 'write_value',
29
+ 'hide' => 'hide_value'
30
+ }.to_json)}
31
+
32
+ its(:event) { should eql('some_event') }
33
+ its(:channel) { should eql('some_channel') }
34
+ its(:user_data) { should eql('some_user_data') }
35
+ its(:auth) { should eql('some_auth') }
36
+ its(:read) { should eql('read_value') }
37
+ its(:write) { should eql('write_value') }
38
+ its(:hide) { should eql('hide_value') }
39
+
40
+ context "#dispath" do
41
+ it "should call channel.subscribe when 'socky:subscribe' event received" do
42
+ subject.instance_variable_get('@data')['event'] = 'socky:subscribe'
43
+ channel.should_receive(:subscribe).with(connection, subject)
44
+ subject.dispath
45
+ end
46
+ it "should call channel.unsubscribe when 'socky:unsubscribe' event received" do
47
+ subject.instance_variable_get('@data')['event'] = 'socky:unsubscribe'
48
+ channel.should_receive(:unsubscribe).with(connection, subject)
49
+ subject.dispath
50
+ end
51
+ it "should call channel.deliver when normal event received" do
52
+ subject.instance_variable_get('@data')['event'] = 'some_event'
53
+ channel.should_receive(:deliver).with(connection, subject)
54
+ subject.dispath
55
+ end
56
+ it "should not call channel.deliver when unknown socky event received" do
57
+ subject.instance_variable_get('@data')['event'] = 'socky:unknown'
58
+ channel.should_not_receive(:deliver).with(connection, subject)
59
+ subject.dispath
60
+ end
61
+ end
62
+ end
63
+
64
+ end
metadata CHANGED
@@ -1,171 +1,138 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: socky-server
3
- version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.4.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0.beta1
5
+ prerelease: 6
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Bernard Potocki
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-05-12 00:00:00 +02:00
12
+ date: 2011-08-01 00:00:00.000000000 +02:00
14
13
  default_executable:
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
17
- name: em-websocket
18
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: websocket-rack
17
+ requirement: &70321806627380 !ruby/object:Gem::Requirement
20
18
  none: false
21
- requirements:
22
- - - ~>
23
- - !ruby/object:Gem::Version
24
- version: 0.3.0
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.2.1
25
23
  type: :runtime
26
- version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
28
- name: em-http-request
29
24
  prerelease: false
30
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: *70321806627380
26
+ - !ruby/object:Gem::Dependency
27
+ name: socky-authenticator
28
+ requirement: &70321806626880 !ruby/object:Gem::Requirement
31
29
  none: false
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
- version: "0"
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 0.5.0.beta5
36
34
  type: :runtime
37
- version_requirements: *id002
38
- - !ruby/object:Gem::Dependency
39
- name: json
40
35
  prerelease: false
41
- requirement: &id003 !ruby/object:Gem::Requirement
36
+ version_requirements: *70321806626880
37
+ - !ruby/object:Gem::Dependency
38
+ name: json
39
+ requirement: &70321806626500 !ruby/object:Gem::Requirement
42
40
  none: false
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: "0"
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
47
45
  type: :runtime
48
- version_requirements: *id003
49
- - !ruby/object:Gem::Dependency
50
- name: rspec
51
46
  prerelease: false
52
- requirement: &id004 !ruby/object:Gem::Requirement
47
+ version_requirements: *70321806626500
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ requirement: &70321806625940 !ruby/object:Gem::Requirement
53
51
  none: false
54
- requirements:
52
+ requirements:
55
53
  - - ~>
56
- - !ruby/object:Gem::Version
57
- version: "2.0"
58
- type: :development
59
- version_requirements: *id004
60
- - !ruby/object:Gem::Dependency
61
- name: rack
62
- prerelease: false
63
- requirement: &id005 !ruby/object:Gem::Requirement
64
- none: false
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: "0"
54
+ - !ruby/object:Gem::Version
55
+ version: '2.0'
69
56
  type: :development
70
- version_requirements: *id005
71
- - !ruby/object:Gem::Dependency
72
- name: mongrel
73
57
  prerelease: false
74
- requirement: &id006 !ruby/object:Gem::Requirement
75
- none: false
76
- requirements:
77
- - - ">="
78
- - !ruby/object:Gem::Version
79
- version: "0"
80
- type: :development
81
- version_requirements: *id006
58
+ version_requirements: *70321806625940
82
59
  description: Socky is a WebSocket server and client for Ruby
83
- email:
60
+ email:
84
61
  - bernard.potocki@imanel.org
85
- executables:
86
- - socky
62
+ executables: []
87
63
  extensions: []
88
-
89
64
  extra_rdoc_files: []
90
-
91
- files:
65
+ files:
92
66
  - .gitignore
67
+ - .travis.yml
93
68
  - CHANGELOG.md
94
69
  - Gemfile
95
70
  - README.md
96
71
  - Rakefile
97
- - bin/socky
98
- - lib/em-websocket_hacks.rb
99
- - lib/socky.rb
100
- - lib/socky/connection.rb
101
- - lib/socky/connection/authentication.rb
102
- - lib/socky/connection/finders.rb
103
- - lib/socky/message.rb
104
- - lib/socky/misc.rb
105
- - lib/socky/net_request.rb
106
- - lib/socky/options.rb
107
- - lib/socky/options/config.rb
108
- - lib/socky/options/parser.rb
109
- - lib/socky/runner.rb
72
+ - config.ru
73
+ - example/config.yml
74
+ - lib/socky/server.rb
75
+ - lib/socky/server/application.rb
76
+ - lib/socky/server/channel.rb
77
+ - lib/socky/server/channel/base.rb
78
+ - lib/socky/server/channel/presence.rb
79
+ - lib/socky/server/channel/private.rb
80
+ - lib/socky/server/channel/public.rb
81
+ - lib/socky/server/channel/stub.rb
82
+ - lib/socky/server/config.rb
83
+ - lib/socky/server/connection.rb
84
+ - lib/socky/server/http.rb
85
+ - lib/socky/server/logger.rb
86
+ - lib/socky/server/message.rb
87
+ - lib/socky/server/misc.rb
88
+ - lib/socky/server/version.rb
89
+ - lib/socky/server/websocket.rb
110
90
  - socky-server.gemspec
111
- - spec/em-websocket_spec.rb
112
- - spec/files/default.yml
113
- - spec/files/invalid.yml
114
- - spec/socky/connection/authentication_spec.rb
115
- - spec/socky/connection/finders_spec.rb
116
- - spec/socky/connection_spec.rb
117
- - spec/socky/message_spec.rb
118
- - spec/socky/misc_spec.rb
119
- - spec/socky/net_request_spec.rb
120
- - spec/socky/options/config_spec.rb
121
- - spec/socky/options/parser_spec.rb
122
- - spec/socky/options_spec.rb
123
- - spec/socky/runner_spec.rb
124
- - spec/socky_spec.rb
91
+ - spec/fixtures/example_config.yml
92
+ - spec/integration/ws_channels_spec.rb
93
+ - spec/integration/ws_connection_spec.rb
94
+ - spec/integration/ws_presence_spec.rb
95
+ - spec/integration/ws_rights_spec.rb
125
96
  - spec/spec_helper.rb
126
- - spec/support/stallion.rb
97
+ - spec/support/websocket_application.rb
98
+ - spec/unit/socky/server/application_spec.rb
99
+ - spec/unit/socky/server/config_spec.rb
100
+ - spec/unit/socky/server/connection_spec.rb
101
+ - spec/unit/socky/server/message_spec.rb
127
102
  has_rdoc: true
128
103
  homepage: http://socky.org
129
104
  licenses: []
130
-
131
105
  post_install_message:
132
106
  rdoc_options: []
133
-
134
- require_paths:
107
+ require_paths:
135
108
  - lib
136
- required_ruby_version: !ruby/object:Gem::Requirement
109
+ required_ruby_version: !ruby/object:Gem::Requirement
137
110
  none: false
138
- requirements:
139
- - - ">="
140
- - !ruby/object:Gem::Version
141
- version: "0"
142
- required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
116
  none: false
144
- requirements:
145
- - - ">="
146
- - !ruby/object:Gem::Version
147
- version: "0"
117
+ requirements:
118
+ - - ! '>'
119
+ - !ruby/object:Gem::Version
120
+ version: 1.3.1
148
121
  requirements: []
149
-
150
122
  rubyforge_project:
151
- rubygems_version: 1.6.1
123
+ rubygems_version: 1.6.2
152
124
  signing_key:
153
125
  specification_version: 3
154
126
  summary: Socky is a WebSocket server and client for Ruby
155
- test_files:
156
- - spec/em-websocket_spec.rb
157
- - spec/files/default.yml
158
- - spec/files/invalid.yml
159
- - spec/socky/connection/authentication_spec.rb
160
- - spec/socky/connection/finders_spec.rb
161
- - spec/socky/connection_spec.rb
162
- - spec/socky/message_spec.rb
163
- - spec/socky/misc_spec.rb
164
- - spec/socky/net_request_spec.rb
165
- - spec/socky/options/config_spec.rb
166
- - spec/socky/options/parser_spec.rb
167
- - spec/socky/options_spec.rb
168
- - spec/socky/runner_spec.rb
169
- - spec/socky_spec.rb
127
+ test_files:
128
+ - spec/fixtures/example_config.yml
129
+ - spec/integration/ws_channels_spec.rb
130
+ - spec/integration/ws_connection_spec.rb
131
+ - spec/integration/ws_presence_spec.rb
132
+ - spec/integration/ws_rights_spec.rb
170
133
  - spec/spec_helper.rb
171
- - spec/support/stallion.rb
134
+ - spec/support/websocket_application.rb
135
+ - spec/unit/socky/server/application_spec.rb
136
+ - spec/unit/socky/server/config_spec.rb
137
+ - spec/unit/socky/server/connection_spec.rb
138
+ - spec/unit/socky/server/message_spec.rb