socky-server 0.4.1 → 0.5.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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