alondra 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +166 -0
- data/MIT-LICENSE +20 -0
- data/README.md +177 -0
- data/Rakefile +34 -0
- data/alondra.gemspec +23 -0
- data/app/assets/javascripts/alondra-client.js.coffee.erb +71 -0
- data/app/assets/javascripts/moz_websocket.js +5 -0
- data/app/assets/javascripts/vendor/jquery.json-2.2.js +178 -0
- data/app/assets/javascripts/vendor/json2.js +480 -0
- data/app/assets/javascripts/vendor/swfobject.js +4 -0
- data/app/assets/javascripts/vendor/web_socket.js +379 -0
- data/app/assets/swf/WebSocketMain.swf +0 -0
- data/app/helpers/alondra_helper.rb +24 -0
- data/lib/alondra/changes_callbacks.rb +52 -0
- data/lib/alondra/changes_push.rb +23 -0
- data/lib/alondra/channel.rb +84 -0
- data/lib/alondra/command.rb +38 -0
- data/lib/alondra/command_dispatcher.rb +22 -0
- data/lib/alondra/connection.rb +52 -0
- data/lib/alondra/event.rb +74 -0
- data/lib/alondra/event_listener.rb +86 -0
- data/lib/alondra/event_router.rb +27 -0
- data/lib/alondra/listener_callback.rb +37 -0
- data/lib/alondra/message.rb +35 -0
- data/lib/alondra/message_queue.rb +70 -0
- data/lib/alondra/message_queue_client.rb +71 -0
- data/lib/alondra/push_controller.rb +53 -0
- data/lib/alondra/pushing.rb +14 -0
- data/lib/alondra/server.rb +44 -0
- data/lib/alondra/session_parser.rb +57 -0
- data/lib/alondra.rb +80 -0
- data/lib/generators/alondra/USAGE +8 -0
- data/lib/generators/alondra/alondra_generator.rb +7 -0
- data/lib/generators/alondra/templates/alondra +33 -0
- data/lib/tasks/alondra_tasks.rake +4 -0
- data/script/rails +6 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +9 -0
- data/test/dummy/app/assets/stylesheets/application.css +7 -0
- data/test/dummy/app/controllers/application_controller.rb +14 -0
- data/test/dummy/app/controllers/chats_controller.rb +85 -0
- data/test/dummy/app/controllers/messages_controller.rb +12 -0
- data/test/dummy/app/controllers/sessions_controller.rb +20 -0
- data/test/dummy/app/controllers/users_controller.rb +30 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/helpers/chats_helper.rb +6 -0
- data/test/dummy/app/helpers/error_messages_helper.rb +23 -0
- data/test/dummy/app/helpers/layout_helper.rb +22 -0
- data/test/dummy/app/mailers/.gitkeep +0 -0
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/app/models/chat.rb +5 -0
- data/test/dummy/app/models/message.rb +4 -0
- data/test/dummy/app/models/user.rb +37 -0
- data/test/dummy/app/views/chats/_form.html.erb +21 -0
- data/test/dummy/app/views/chats/edit.html.erb +6 -0
- data/test/dummy/app/views/chats/index.html.erb +23 -0
- data/test/dummy/app/views/chats/new.html.erb +5 -0
- data/test/dummy/app/views/chats/show.html.erb +49 -0
- data/test/dummy/app/views/layouts/application.html.erb +19 -0
- data/test/dummy/app/views/sessions/new.html.erb +15 -0
- data/test/dummy/app/views/shared/_message.js.erb +1 -0
- data/test/dummy/app/views/users/_form.html.erb +20 -0
- data/test/dummy/app/views/users/edit.html.erb +3 -0
- data/test/dummy/app/views/users/index.html.erb +25 -0
- data/test/dummy/app/views/users/new.html.erb +5 -0
- data/test/dummy/app/views/users/show.html.erb +15 -0
- data/test/dummy/config/application.rb +42 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +31 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +27 -0
- data/test/dummy/config/environments/production.rb +54 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +10 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +9 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +12 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +19 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/migrate/20110719090458_create_chats.rb +9 -0
- data/test/dummy/db/migrate/20110719090538_create_messages.rb +10 -0
- data/test/dummy/db/migrate/20110720193249_create_users.rb +16 -0
- data/test/dummy/db/schema.rb +38 -0
- data/test/dummy/lib/controller_authentication.rb +48 -0
- data/test/dummy/log/.gitkeep +0 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/public/stylesheets/application.css +75 -0
- data/test/dummy/script/rails +6 -0
- data/test/integration/push_changes_test.rb +41 -0
- data/test/integration/push_messages_test.rb +40 -0
- data/test/models/channel_test.rb +49 -0
- data/test/models/command_test.rb +29 -0
- data/test/models/configuration_test.rb +22 -0
- data/test/models/connection_test.rb +18 -0
- data/test/models/event_listener_test.rb +217 -0
- data/test/models/event_router_test.rb +7 -0
- data/test/models/message_queue_client_test.rb +26 -0
- data/test/models/message_queue_test.rb +70 -0
- data/test/models/pushing_test.rb +34 -0
- data/test/performance/message_queue_performance.rb +66 -0
- data/test/support/factories.rb +19 -0
- data/test/support/integration_helper.rb +18 -0
- data/test/support/integration_test.rb +6 -0
- data/test/support/mocks/bogus_event.rb +15 -0
- data/test/support/mocks/mock_connection.rb +24 -0
- data/test/support/mocks/mock_event_router.rb +12 -0
- data/test/support/mocks/mock_listener.rb +9 -0
- data/test/test_helper.rb +14 -0
- metadata +316 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Alondra
|
4
|
+
|
5
|
+
class ChannelTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@connection = MockConnection.new
|
9
|
+
end
|
10
|
+
|
11
|
+
test "it has a name" do
|
12
|
+
channel = Channel.new('test name channel')
|
13
|
+
assert_equal 'test name channel', channel.name
|
14
|
+
end
|
15
|
+
|
16
|
+
test "can fetch channel by name" do
|
17
|
+
channel = Channel['dummy channel']
|
18
|
+
assert_equal 'dummy channel', channel.name
|
19
|
+
end
|
20
|
+
|
21
|
+
test "allow clients to subscribe" do
|
22
|
+
channel = Channel.new('test subscriptions channel')
|
23
|
+
assert_equal 0, channel.connections.size
|
24
|
+
|
25
|
+
channel.subscribe @connection
|
26
|
+
|
27
|
+
assert_equal 1, channel.connections.size
|
28
|
+
assert channel.connections.keys.include? @connection
|
29
|
+
end
|
30
|
+
|
31
|
+
test "deliver events to all subscribed connections" do
|
32
|
+
channel = Channel.new('test deliver events channel')
|
33
|
+
channel.subscribe @connection
|
34
|
+
|
35
|
+
assert @connection.channels.include?(channel)
|
36
|
+
|
37
|
+
event = Event.new :event => :created, :resource => Chat.new, :channel => 'test deliver events channel'
|
38
|
+
|
39
|
+
channel.receive event
|
40
|
+
|
41
|
+
assert EM.reactor_running?
|
42
|
+
|
43
|
+
sleep(0.5) # Leave event machine to catch up
|
44
|
+
|
45
|
+
last_message = @connection.messages.last
|
46
|
+
assert_equal event.to_json, last_message
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Alondra
|
4
|
+
|
5
|
+
class CommandTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@connection = MockConnection.new
|
9
|
+
end
|
10
|
+
|
11
|
+
test "it is created with a connection and a hash" do
|
12
|
+
command = Command.new @connection, :command => 'subscribe', :channel => 'test'
|
13
|
+
|
14
|
+
assert_equal :subscribe, command.name
|
15
|
+
assert_equal 'test', command.channel.name
|
16
|
+
end
|
17
|
+
|
18
|
+
test "subscribe to channel when subscribe command is executed" do
|
19
|
+
channel = Channel['test']
|
20
|
+
assert_equal 0, channel.connections.size
|
21
|
+
|
22
|
+
command = Command.new @connection, :command => 'subscribe', :channel => 'test'
|
23
|
+
command.execute!
|
24
|
+
|
25
|
+
assert_equal 1, channel.connections.size
|
26
|
+
assert channel.connections.keys.include? @connection
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Alondra
|
4
|
+
|
5
|
+
class ConfigurationTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
test "it has default values" do
|
8
|
+
assert_equal 12346, Alondra.config.port
|
9
|
+
end
|
10
|
+
|
11
|
+
test "it allows to override default values" do
|
12
|
+
assert_equal 'localhost', Alondra.config.host
|
13
|
+
Alondra.config.host = 'www.example.com'
|
14
|
+
assert_equal 'www.example.com', Alondra.config.host
|
15
|
+
end
|
16
|
+
|
17
|
+
test "it allows to define new variables" do
|
18
|
+
Alondra.config.test_variable = 'something'
|
19
|
+
assert_equal 'something', Alondra.config.test_variable
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Alondra
|
4
|
+
|
5
|
+
class ConnectionTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
test "it is assigned an UUI on creation" do
|
8
|
+
assert MockConnection.new.uuid.present?
|
9
|
+
end
|
10
|
+
|
11
|
+
test "can find if there is a session" do
|
12
|
+
session = {:user_id => 10}
|
13
|
+
connection = MockConnection.new(session)
|
14
|
+
|
15
|
+
assert_equal session, connection.session
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Alondra
|
4
|
+
|
5
|
+
class ChatListener < EventListener
|
6
|
+
|
7
|
+
def self.created_chat_ids
|
8
|
+
@created_chat_ids ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.subscribed_user_ids
|
12
|
+
@subscribed_user_ids ||= []
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.subscribed_to_collection
|
16
|
+
@subscribed_to_collection ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.subscribed_to_member
|
20
|
+
@subscribed_to_member ||= []
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.custom_events
|
24
|
+
@custom_events ||= []
|
25
|
+
end
|
26
|
+
|
27
|
+
on :created do |event|
|
28
|
+
ChatListener.created_chat_ids << event.resource.id
|
29
|
+
end
|
30
|
+
|
31
|
+
on :destroyed do |event|
|
32
|
+
chat = event.resource
|
33
|
+
ChatListener.created_chat_ids.delete(chat.id)
|
34
|
+
end
|
35
|
+
|
36
|
+
on :subscribed do |event|
|
37
|
+
ChatListener.subscribed_user_ids << session[:user_id]
|
38
|
+
end
|
39
|
+
|
40
|
+
on :unsubscribed do |event|
|
41
|
+
ChatListener.subscribed_user_ids.delete(session[:user_id])
|
42
|
+
end
|
43
|
+
|
44
|
+
on :subscribed, :to => :collection do |event|
|
45
|
+
ChatListener.subscribed_to_collection << session[:user_id]
|
46
|
+
end
|
47
|
+
|
48
|
+
on :unsubscribed, :to => :collection do |event|
|
49
|
+
ChatListener.subscribed_to_collection.delete(session[:user_id])
|
50
|
+
end
|
51
|
+
|
52
|
+
on :subscribed, :to => :member do |event|
|
53
|
+
ChatListener.subscribed_to_member << session[:user_id]
|
54
|
+
end
|
55
|
+
|
56
|
+
on :unsubscribed, :to => :member do |event|
|
57
|
+
ChatListener.subscribed_to_member.delete(session[:user_id])
|
58
|
+
end
|
59
|
+
|
60
|
+
on :custom do |event|
|
61
|
+
ChatListener.custom_events << event
|
62
|
+
end
|
63
|
+
|
64
|
+
on :boom do |event|
|
65
|
+
event.boom!
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
class EventListenerTest < ActiveSupport::TestCase
|
72
|
+
|
73
|
+
test "can listen to a specific channel providing a string pattern" do
|
74
|
+
class TextPatternListener < EventListener
|
75
|
+
listen_to 'string pattern'
|
76
|
+
end
|
77
|
+
|
78
|
+
assert TextPatternListener.listen_to?('string pattern')
|
79
|
+
assert TextPatternListener.listen_to?('string pattern and more')
|
80
|
+
assert !TextPatternListener.listen_to?('other string pattern')
|
81
|
+
end
|
82
|
+
|
83
|
+
test "can listen to specific channel providing a regexp as pattern" do
|
84
|
+
class RegexpPatternListener < EventListener
|
85
|
+
listen_to /man$/
|
86
|
+
end
|
87
|
+
|
88
|
+
assert RegexpPatternListener.listen_to?('Superman')
|
89
|
+
assert !RegexpPatternListener.listen_to?('Lex Luthor')
|
90
|
+
end
|
91
|
+
|
92
|
+
test "it has a default channel pattern" do
|
93
|
+
class DefaultPatternsListener < EventListener; end
|
94
|
+
|
95
|
+
assert DefaultPatternsListener.listen_to?('/default/patterns/')
|
96
|
+
assert DefaultPatternsListener.listen_to?('/default/patterns/1')
|
97
|
+
|
98
|
+
assert !DefaultPatternsListener.listen_to?('/default/other/')
|
99
|
+
assert !DefaultPatternsListener.listen_to?('/other/patterns/')
|
100
|
+
end
|
101
|
+
|
102
|
+
test "default channel pattern is ignored if explicit listen_to pattern is called" do
|
103
|
+
class OverwrittenDefaultPatternsListener < EventListener
|
104
|
+
listen_to '/others'
|
105
|
+
end
|
106
|
+
|
107
|
+
assert OverwrittenDefaultPatternsListener.listen_to?('/others')
|
108
|
+
assert OverwrittenDefaultPatternsListener.listen_to?('/others/1/')
|
109
|
+
assert !OverwrittenDefaultPatternsListener.listen_to?('/overwritten/default/patterns')
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
test 'receive created and destroyes events' do
|
114
|
+
ChatListener.listen_to '/chats/'
|
115
|
+
|
116
|
+
chat = Chat.create(:name => 'Observed chat')
|
117
|
+
|
118
|
+
sleep(0.1)
|
119
|
+
|
120
|
+
assert ChatListener.created_chat_ids.include?(chat.id)
|
121
|
+
|
122
|
+
chat.destroy
|
123
|
+
|
124
|
+
sleep(0.1)
|
125
|
+
|
126
|
+
assert !ChatListener.created_chat_ids.include?(chat.id)
|
127
|
+
end
|
128
|
+
|
129
|
+
test 'react to subscribed and unsubscribed events' do
|
130
|
+
session = {:user_id => 28 }
|
131
|
+
connection = MockConnection.new(session)
|
132
|
+
|
133
|
+
assert !ChatListener.subscribed_user_ids.include?(28)
|
134
|
+
|
135
|
+
Command.new(connection, :command => 'subscribe', :channel => '/chats/').execute!
|
136
|
+
|
137
|
+
sleep(0.1)
|
138
|
+
|
139
|
+
assert ChatListener.subscribed_user_ids.include?(28)
|
140
|
+
|
141
|
+
Command.new(connection, :command => 'unsubscribe', :channel => '/chats/').execute!
|
142
|
+
|
143
|
+
sleep(0.1)
|
144
|
+
|
145
|
+
assert !ChatListener.subscribed_user_ids.include?(28)
|
146
|
+
end
|
147
|
+
|
148
|
+
test 'react to subscribed and unsubscribed events on collection' do
|
149
|
+
session = {:user_id => 29 }
|
150
|
+
connection = MockConnection.new(session)
|
151
|
+
|
152
|
+
assert !ChatListener.subscribed_to_collection.include?(29)
|
153
|
+
assert !ChatListener.subscribed_to_member.include?(29)
|
154
|
+
|
155
|
+
Command.new(connection, :command => 'subscribe', :channel => '/chats/').execute!
|
156
|
+
|
157
|
+
sleep(0.1)
|
158
|
+
|
159
|
+
assert ChatListener.subscribed_to_collection.include?(29)
|
160
|
+
assert !ChatListener.subscribed_to_member.include?(29)
|
161
|
+
|
162
|
+
Command.new(connection, :command => 'unsubscribe', :channel => '/chats/').execute!
|
163
|
+
|
164
|
+
sleep(0.1)
|
165
|
+
|
166
|
+
assert !ChatListener.subscribed_to_collection.include?(29)
|
167
|
+
assert !ChatListener.subscribed_to_member.include?(29)
|
168
|
+
end
|
169
|
+
|
170
|
+
test 'react to subscribed and unsubscribed events on member' do
|
171
|
+
session = {:user_id => 30 }
|
172
|
+
connection = MockConnection.new(session)
|
173
|
+
|
174
|
+
chat = Factory.create :chat
|
175
|
+
|
176
|
+
chat_channel = "/chats/#{chat.id}"
|
177
|
+
|
178
|
+
assert !ChatListener.subscribed_to_collection.include?(30)
|
179
|
+
assert !ChatListener.subscribed_to_member.include?(30)
|
180
|
+
|
181
|
+
Command.new(connection, :command => 'subscribe', :channel => chat_channel).execute!
|
182
|
+
|
183
|
+
sleep(0.1)
|
184
|
+
|
185
|
+
assert !ChatListener.subscribed_to_collection.include?(30)
|
186
|
+
assert ChatListener.subscribed_to_member.include?(30)
|
187
|
+
|
188
|
+
Command.new(connection, :command => 'unsubscribe', :channel => chat_channel).execute!
|
189
|
+
|
190
|
+
sleep(0.1)
|
191
|
+
|
192
|
+
assert !ChatListener.subscribed_to_collection.include?(30)
|
193
|
+
assert !ChatListener.subscribed_to_member.include?(30)
|
194
|
+
end
|
195
|
+
|
196
|
+
test 'receive customs events' do
|
197
|
+
event = Event.new :event => :custom, :resource => Chat.new, :channel => '/chats/'
|
198
|
+
EventRouter.new.process(event)
|
199
|
+
|
200
|
+
sleep(0.1)
|
201
|
+
|
202
|
+
assert_equal ChatListener.custom_events.last, event
|
203
|
+
end
|
204
|
+
|
205
|
+
test 'capture exceptions launched in event listener' do
|
206
|
+
boom = BogusEvent.new :event => :boom, :resource => Chat.new, :channel => '/chats/'
|
207
|
+
EventRouter.new.process(boom)
|
208
|
+
|
209
|
+
event = Event.new :event => :custom, :resource => Chat.new, :channel => '/chats/'
|
210
|
+
EventRouter.new.process(event)
|
211
|
+
|
212
|
+
sleep(0.1)
|
213
|
+
|
214
|
+
assert_equal ChatListener.custom_events.last, event
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Alondra
|
4
|
+
|
5
|
+
class MessageQueueClientTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
test "a sync client uses a sync zeromq context" do
|
8
|
+
context = SyncMessageQueueClient.new.send :context
|
9
|
+
assert context.class == ZMQ::Context
|
10
|
+
end
|
11
|
+
|
12
|
+
test "an async client uses an async zeromq context" do
|
13
|
+
context = nil
|
14
|
+
|
15
|
+
assert EM.reactor_running?
|
16
|
+
|
17
|
+
EM.schedule do
|
18
|
+
context = MessageQueueClient.instance.send :context
|
19
|
+
end
|
20
|
+
|
21
|
+
sleep(0.1)
|
22
|
+
|
23
|
+
assert context.class == EM::ZeroMQ::Context
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Alondra
|
4
|
+
|
5
|
+
class MessageQueueTest < ActiveSupport::TestCase
|
6
|
+
setup do
|
7
|
+
@original_event_router = MessageQueue.instance.send :event_router
|
8
|
+
@router = MockEventRouter.new
|
9
|
+
|
10
|
+
@chat = Chat.create(:name => 'Silly chat')
|
11
|
+
|
12
|
+
MessageQueue.instance.instance_variable_set :@event_router, @router
|
13
|
+
@event = Event.new :event => :custom, :resource => @chat, :channel => '/chats/'
|
14
|
+
end
|
15
|
+
|
16
|
+
teardown do
|
17
|
+
MessageQueue.instance.instance_variable_set :@event_router, @original_event_router
|
18
|
+
end
|
19
|
+
|
20
|
+
test "a message pushed asynchronously to the queue is received by the event router" do
|
21
|
+
assert MessageQueueClient.instance.class == AsyncMessageQueueClient
|
22
|
+
|
23
|
+
MessageQueueClient.push @event
|
24
|
+
|
25
|
+
sleep(0.1)
|
26
|
+
|
27
|
+
assert received(@event)
|
28
|
+
end
|
29
|
+
|
30
|
+
test "a message pushed synchronously to the queue is received by the event router" do
|
31
|
+
|
32
|
+
client = MessageQueueClient.sync_instance
|
33
|
+
context = client.send :context
|
34
|
+
assert context.class == ZMQ::Context
|
35
|
+
|
36
|
+
client.send_message(@event)
|
37
|
+
|
38
|
+
sleep(0.1)
|
39
|
+
|
40
|
+
assert received(@event)
|
41
|
+
end
|
42
|
+
|
43
|
+
test "message queue still works when an exception is thrown while processing an event" do
|
44
|
+
3.times do
|
45
|
+
bogus = BogusEvent.new :event => :custom, :resource => @chat, :channel => '/chats/'
|
46
|
+
|
47
|
+
begin
|
48
|
+
MessageQueueClient.push bogus
|
49
|
+
rescue BogusException
|
50
|
+
puts "rescued exception"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
MessageQueueClient.push @event
|
55
|
+
|
56
|
+
sleep(0.1)
|
57
|
+
|
58
|
+
assert received(@event)
|
59
|
+
end
|
60
|
+
|
61
|
+
def received(event)
|
62
|
+
@router.received_events.find do |matching_event|
|
63
|
+
matching_event.type == event.type &&
|
64
|
+
matching_event.resource_type == event.resource_type &&
|
65
|
+
matching_event.resource.id == event.resource.id &&
|
66
|
+
matching_event.channel_name == event.channel_name
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Alondra
|
4
|
+
|
5
|
+
class PushingTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
test "publish created events to the specified channel" do
|
8
|
+
chat = Factory.create :chat
|
9
|
+
connection = MockConnection.new
|
10
|
+
message = chat.messages.build(:text => 'test message')
|
11
|
+
|
12
|
+
channel_name = Channel.default_name_for(chat)
|
13
|
+
assert channel_name =~ /chats\/\d+/
|
14
|
+
|
15
|
+
channel = Channel[channel_name]
|
16
|
+
channel.subscribe connection
|
17
|
+
|
18
|
+
sleep(0.1)
|
19
|
+
|
20
|
+
message.save!
|
21
|
+
|
22
|
+
sleep(0.1)
|
23
|
+
|
24
|
+
assert connection.messages.last, "should publish a message"
|
25
|
+
|
26
|
+
last_event = ActiveSupport::JSON.decode(connection.messages.last)
|
27
|
+
resource = last_event['resource']
|
28
|
+
|
29
|
+
assert_equal 'created', last_event['event']
|
30
|
+
assert_equal 'Message', last_event['resource_type']
|
31
|
+
assert_equal message.id, resource['id']
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Alondra
|
4
|
+
|
5
|
+
class MessageQueuePerformanceTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
NUM_MESSAGES = 1_000
|
8
|
+
|
9
|
+
setup do
|
10
|
+
@event = Event.new :event => :custom, :resource => Chat.new, :channel => '/chats/'
|
11
|
+
|
12
|
+
# Initialize queue
|
13
|
+
MessageQueueClient.push @event
|
14
|
+
|
15
|
+
@original_event_router = MessageQueue.instance.send :event_router
|
16
|
+
@router = MockEventRouter.new
|
17
|
+
|
18
|
+
MessageQueue.instance.instance_variable_set :@event_router, @router
|
19
|
+
end
|
20
|
+
|
21
|
+
teardown do
|
22
|
+
MessageQueue.instance.instance_variable_set :@event_router, @original_event_router
|
23
|
+
end
|
24
|
+
|
25
|
+
test "message queue performance" do
|
26
|
+
puts "send #{NUM_MESSAGES} messages to queue"
|
27
|
+
|
28
|
+
time = Benchmark.measure do
|
29
|
+
NUM_MESSAGES.times do
|
30
|
+
MessageQueueClient.async_instance.send_message @event
|
31
|
+
end
|
32
|
+
|
33
|
+
while @router.received_events.size < NUM_MESSAGES
|
34
|
+
sleep(0.1)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
events_per_second = NUM_MESSAGES/time.total
|
39
|
+
|
40
|
+
puts "aprox. received events per second #{events_per_second}"
|
41
|
+
|
42
|
+
assert events_per_second >= 500
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
test "message queue performance with sync client" do
|
47
|
+
puts "send #{NUM_MESSAGES} messages to queue"
|
48
|
+
|
49
|
+
time = Benchmark.measure do
|
50
|
+
NUM_MESSAGES.times do
|
51
|
+
MessageQueueClient.sync_instance.send_message @event
|
52
|
+
end
|
53
|
+
|
54
|
+
while @router.received_events.size < NUM_MESSAGES
|
55
|
+
sleep(0.1)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
events_per_second = NUM_MESSAGES/time.total
|
60
|
+
|
61
|
+
puts "aprox. received events per second #{events_per_second}"
|
62
|
+
|
63
|
+
assert events_per_second >= 500
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Factory.define :chat do |f|
|
2
|
+
f.name 'Test chat'
|
3
|
+
end
|
4
|
+
|
5
|
+
Factory.define :message do |f|
|
6
|
+
f.association :chat
|
7
|
+
f.text 'Test message'
|
8
|
+
end
|
9
|
+
|
10
|
+
Factory.sequence :username do |i|
|
11
|
+
"user#{i}"
|
12
|
+
end
|
13
|
+
|
14
|
+
Factory.define :user do |f|
|
15
|
+
f.username { Factory.next(:username) }
|
16
|
+
f.email { |u| "#{u.username}@example.com" }
|
17
|
+
f.password 'secret'
|
18
|
+
f.password_confirmation 'secret'
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Alondra
|
2
|
+
module IntegrationHelper
|
3
|
+
def login_as(user)
|
4
|
+
visit new_session_path
|
5
|
+
fill_in "login", :with => user.username
|
6
|
+
fill_in "password", :with => "secret"
|
7
|
+
click_button "Log in"
|
8
|
+
end
|
9
|
+
|
10
|
+
def log_out
|
11
|
+
click_link _('logout')
|
12
|
+
end
|
13
|
+
|
14
|
+
def clean_db
|
15
|
+
[User, Chat, ::Message].each { |model| model.delete_all }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Alondra
|
2
|
+
class MockConnection < Connection
|
3
|
+
|
4
|
+
def initialize(session = {})
|
5
|
+
super UUIDTools::UUID.random_create, session
|
6
|
+
end
|
7
|
+
|
8
|
+
def send(message)
|
9
|
+
messages << message
|
10
|
+
end
|
11
|
+
|
12
|
+
def receive(event)
|
13
|
+
messages << event.to_json
|
14
|
+
end
|
15
|
+
|
16
|
+
def channels
|
17
|
+
@channels ||= []
|
18
|
+
end
|
19
|
+
|
20
|
+
def messages
|
21
|
+
@messages ||= []
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Configure Rails Environment
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
3
|
+
ENV["ALONDRA_SERVER"] = 'true'
|
4
|
+
|
5
|
+
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
6
|
+
require "rails/test_help"
|
7
|
+
require 'capybara/rails'
|
8
|
+
|
9
|
+
Alondra::Alondra.start_server_in_new_thread!
|
10
|
+
|
11
|
+
Rails.backtrace_cleaner.remove_silencers!
|
12
|
+
|
13
|
+
# Load support files
|
14
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|