lygneo-vines 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE +19 -0
  4. data/README.md +7 -0
  5. data/Rakefile +23 -0
  6. data/bin/vines +4 -0
  7. data/conf/certs/README +39 -0
  8. data/conf/certs/ca-bundle.crt +3895 -0
  9. data/conf/config.rb +42 -0
  10. data/lib/vines/cli.rb +132 -0
  11. data/lib/vines/cluster/connection.rb +26 -0
  12. data/lib/vines/cluster/publisher.rb +55 -0
  13. data/lib/vines/cluster/pubsub.rb +92 -0
  14. data/lib/vines/cluster/sessions.rb +125 -0
  15. data/lib/vines/cluster/subscriber.rb +108 -0
  16. data/lib/vines/cluster.rb +246 -0
  17. data/lib/vines/command/bcrypt.rb +12 -0
  18. data/lib/vines/command/cert.rb +50 -0
  19. data/lib/vines/command/init.rb +68 -0
  20. data/lib/vines/command/ldap.rb +38 -0
  21. data/lib/vines/command/restart.rb +12 -0
  22. data/lib/vines/command/schema.rb +24 -0
  23. data/lib/vines/command/start.rb +28 -0
  24. data/lib/vines/command/stop.rb +18 -0
  25. data/lib/vines/config/host.rb +125 -0
  26. data/lib/vines/config/port.rb +132 -0
  27. data/lib/vines/config/pubsub.rb +108 -0
  28. data/lib/vines/config.rb +223 -0
  29. data/lib/vines/daemon.rb +78 -0
  30. data/lib/vines/error.rb +150 -0
  31. data/lib/vines/follower.rb +111 -0
  32. data/lib/vines/jid.rb +95 -0
  33. data/lib/vines/kit.rb +23 -0
  34. data/lib/vines/log.rb +24 -0
  35. data/lib/vines/router.rb +179 -0
  36. data/lib/vines/stanza/iq/auth.rb +18 -0
  37. data/lib/vines/stanza/iq/disco_info.rb +45 -0
  38. data/lib/vines/stanza/iq/disco_items.rb +29 -0
  39. data/lib/vines/stanza/iq/error.rb +16 -0
  40. data/lib/vines/stanza/iq/ping.rb +16 -0
  41. data/lib/vines/stanza/iq/private_storage.rb +83 -0
  42. data/lib/vines/stanza/iq/query.rb +10 -0
  43. data/lib/vines/stanza/iq/result.rb +16 -0
  44. data/lib/vines/stanza/iq/roster.rb +140 -0
  45. data/lib/vines/stanza/iq/session.rb +17 -0
  46. data/lib/vines/stanza/iq/vcard.rb +56 -0
  47. data/lib/vines/stanza/iq/version.rb +25 -0
  48. data/lib/vines/stanza/iq.rb +48 -0
  49. data/lib/vines/stanza/message.rb +40 -0
  50. data/lib/vines/stanza/presence/error.rb +23 -0
  51. data/lib/vines/stanza/presence/probe.rb +37 -0
  52. data/lib/vines/stanza/presence/subscribe.rb +42 -0
  53. data/lib/vines/stanza/presence/subscribed.rb +51 -0
  54. data/lib/vines/stanza/presence/unavailable.rb +15 -0
  55. data/lib/vines/stanza/presence/unsubscribe.rb +38 -0
  56. data/lib/vines/stanza/presence/unsubscribed.rb +38 -0
  57. data/lib/vines/stanza/presence.rb +141 -0
  58. data/lib/vines/stanza/pubsub/create.rb +39 -0
  59. data/lib/vines/stanza/pubsub/delete.rb +41 -0
  60. data/lib/vines/stanza/pubsub/publish.rb +66 -0
  61. data/lib/vines/stanza/pubsub/subscribe.rb +44 -0
  62. data/lib/vines/stanza/pubsub/unsubscribe.rb +30 -0
  63. data/lib/vines/stanza/pubsub.rb +22 -0
  64. data/lib/vines/stanza.rb +175 -0
  65. data/lib/vines/storage/ldap.rb +71 -0
  66. data/lib/vines/storage/local.rb +139 -0
  67. data/lib/vines/storage/null.rb +39 -0
  68. data/lib/vines/storage/sql.rb +138 -0
  69. data/lib/vines/storage.rb +239 -0
  70. data/lib/vines/store.rb +110 -0
  71. data/lib/vines/stream/client/auth.rb +74 -0
  72. data/lib/vines/stream/client/auth_restart.rb +29 -0
  73. data/lib/vines/stream/client/bind.rb +72 -0
  74. data/lib/vines/stream/client/bind_restart.rb +24 -0
  75. data/lib/vines/stream/client/closed.rb +13 -0
  76. data/lib/vines/stream/client/ready.rb +17 -0
  77. data/lib/vines/stream/client/session.rb +210 -0
  78. data/lib/vines/stream/client/start.rb +27 -0
  79. data/lib/vines/stream/client/tls.rb +38 -0
  80. data/lib/vines/stream/client.rb +84 -0
  81. data/lib/vines/stream/component/handshake.rb +26 -0
  82. data/lib/vines/stream/component/ready.rb +23 -0
  83. data/lib/vines/stream/component/start.rb +19 -0
  84. data/lib/vines/stream/component.rb +58 -0
  85. data/lib/vines/stream/http/auth.rb +22 -0
  86. data/lib/vines/stream/http/bind.rb +32 -0
  87. data/lib/vines/stream/http/bind_restart.rb +37 -0
  88. data/lib/vines/stream/http/ready.rb +29 -0
  89. data/lib/vines/stream/http/request.rb +172 -0
  90. data/lib/vines/stream/http/session.rb +120 -0
  91. data/lib/vines/stream/http/sessions.rb +65 -0
  92. data/lib/vines/stream/http/start.rb +23 -0
  93. data/lib/vines/stream/http.rb +157 -0
  94. data/lib/vines/stream/parser.rb +79 -0
  95. data/lib/vines/stream/sasl.rb +128 -0
  96. data/lib/vines/stream/server/auth.rb +13 -0
  97. data/lib/vines/stream/server/auth_restart.rb +13 -0
  98. data/lib/vines/stream/server/final_restart.rb +21 -0
  99. data/lib/vines/stream/server/outbound/auth.rb +31 -0
  100. data/lib/vines/stream/server/outbound/auth_restart.rb +20 -0
  101. data/lib/vines/stream/server/outbound/auth_result.rb +32 -0
  102. data/lib/vines/stream/server/outbound/final_features.rb +28 -0
  103. data/lib/vines/stream/server/outbound/final_restart.rb +20 -0
  104. data/lib/vines/stream/server/outbound/start.rb +20 -0
  105. data/lib/vines/stream/server/outbound/tls.rb +30 -0
  106. data/lib/vines/stream/server/outbound/tls_result.rb +34 -0
  107. data/lib/vines/stream/server/ready.rb +24 -0
  108. data/lib/vines/stream/server/start.rb +13 -0
  109. data/lib/vines/stream/server/tls.rb +13 -0
  110. data/lib/vines/stream/server.rb +150 -0
  111. data/lib/vines/stream/state.rb +60 -0
  112. data/lib/vines/stream.rb +247 -0
  113. data/lib/vines/token_bucket.rb +55 -0
  114. data/lib/vines/user.rb +123 -0
  115. data/lib/vines/version.rb +6 -0
  116. data/lib/vines/xmpp_server.rb +25 -0
  117. data/lib/vines.rb +203 -0
  118. data/test/cluster/publisher_test.rb +57 -0
  119. data/test/cluster/sessions_test.rb +47 -0
  120. data/test/cluster/subscriber_test.rb +109 -0
  121. data/test/config/host_test.rb +369 -0
  122. data/test/config/pubsub_test.rb +187 -0
  123. data/test/config_test.rb +732 -0
  124. data/test/error_test.rb +58 -0
  125. data/test/ext/nokogiri.rb +14 -0
  126. data/test/follower_test.rb +102 -0
  127. data/test/jid_test.rb +147 -0
  128. data/test/kit_test.rb +31 -0
  129. data/test/router_test.rb +243 -0
  130. data/test/stanza/iq/disco_info_test.rb +78 -0
  131. data/test/stanza/iq/disco_items_test.rb +49 -0
  132. data/test/stanza/iq/private_storage_test.rb +184 -0
  133. data/test/stanza/iq/roster_test.rb +229 -0
  134. data/test/stanza/iq/session_test.rb +25 -0
  135. data/test/stanza/iq/vcard_test.rb +146 -0
  136. data/test/stanza/iq/version_test.rb +64 -0
  137. data/test/stanza/iq_test.rb +70 -0
  138. data/test/stanza/message_test.rb +126 -0
  139. data/test/stanza/presence/probe_test.rb +50 -0
  140. data/test/stanza/presence/subscribe_test.rb +83 -0
  141. data/test/stanza/pubsub/create_test.rb +116 -0
  142. data/test/stanza/pubsub/delete_test.rb +169 -0
  143. data/test/stanza/pubsub/publish_test.rb +309 -0
  144. data/test/stanza/pubsub/subscribe_test.rb +205 -0
  145. data/test/stanza/pubsub/unsubscribe_test.rb +148 -0
  146. data/test/stanza_test.rb +85 -0
  147. data/test/storage/ldap_test.rb +201 -0
  148. data/test/storage/local_test.rb +59 -0
  149. data/test/storage/mock_redis.rb +97 -0
  150. data/test/storage/null_test.rb +29 -0
  151. data/test/storage/storage_tests.rb +182 -0
  152. data/test/storage_test.rb +85 -0
  153. data/test/store_test.rb +130 -0
  154. data/test/stream/client/auth_test.rb +137 -0
  155. data/test/stream/client/ready_test.rb +47 -0
  156. data/test/stream/client/session_test.rb +27 -0
  157. data/test/stream/component/handshake_test.rb +52 -0
  158. data/test/stream/component/ready_test.rb +103 -0
  159. data/test/stream/component/start_test.rb +39 -0
  160. data/test/stream/http/auth_test.rb +70 -0
  161. data/test/stream/http/ready_test.rb +86 -0
  162. data/test/stream/http/request_test.rb +209 -0
  163. data/test/stream/http/sessions_test.rb +49 -0
  164. data/test/stream/http/start_test.rb +50 -0
  165. data/test/stream/parser_test.rb +122 -0
  166. data/test/stream/sasl_test.rb +195 -0
  167. data/test/stream/server/auth_test.rb +61 -0
  168. data/test/stream/server/outbound/auth_test.rb +75 -0
  169. data/test/stream/server/ready_test.rb +98 -0
  170. data/test/test_helper.rb +42 -0
  171. data/test/token_bucket_test.rb +44 -0
  172. data/test/user_test.rb +96 -0
  173. data/vines.gemspec +30 -0
  174. metadata +387 -0
data/lib/vines.rb ADDED
@@ -0,0 +1,203 @@
1
+ # encoding: UTF-8
2
+
3
+ module Vines
4
+ NAMESPACES = {
5
+ :stream => 'http://etherx.jabber.org/streams'.freeze,
6
+ :client => 'jabber:client'.freeze,
7
+ :server => 'jabber:server'.freeze,
8
+ :component => 'jabber:component:accept'.freeze,
9
+ :roster => 'jabber:iq:roster'.freeze,
10
+ :non_sasl => 'jabber:iq:auth'.freeze,
11
+ :storage => 'jabber:iq:private'.freeze,
12
+ :version => 'jabber:iq:version'.freeze,
13
+ :sasl => 'urn:ietf:params:xml:ns:xmpp-sasl'.freeze,
14
+ :tls => 'urn:ietf:params:xml:ns:xmpp-tls'.freeze,
15
+ :bind => 'urn:ietf:params:xml:ns:xmpp-bind'.freeze,
16
+ :session => 'urn:ietf:params:xml:ns:xmpp-session'.freeze,
17
+ :ping => 'urn:xmpp:ping'.freeze,
18
+ :pubsub => 'http://jabber.org/protocol/pubsub'.freeze,
19
+ :pubsub_event => 'http://jabber.org/protocol/pubsub#event'.freeze,
20
+ :pubsub_create => 'http://jabber.org/protocol/pubsub#create-nodes'.freeze,
21
+ :pubsub_delete => 'http://jabber.org/protocol/pubsub#delete-nodes'.freeze,
22
+ :pubsub_instant => 'http://jabber.org/protocol/pubsub#instant-nodes'.freeze,
23
+ :pubsub_item_ids => 'http://jabber.org/protocol/pubsub#item-ids'.freeze,
24
+ :pubsub_publish => 'http://jabber.org/protocol/pubsub#publish'.freeze,
25
+ :pubsub_subscribe => 'http://jabber.org/protocol/pubsub#subscribe'.freeze,
26
+ :disco_items => 'http://jabber.org/protocol/disco#items'.freeze,
27
+ :disco_info => 'http://jabber.org/protocol/disco#info'.freeze,
28
+ :http_bind => 'http://jabber.org/protocol/httpbind'.freeze,
29
+ :bosh => 'urn:xmpp:xbosh'.freeze,
30
+ :vcard => 'vcard-temp'.freeze,
31
+ :si => 'http://jabber.org/protocol/si'.freeze,
32
+ :byte_streams => 'http://jabber.org/protocol/bytestreams'.freeze
33
+ }.freeze
34
+
35
+ module Log
36
+ @@logger = nil
37
+ def log
38
+ unless @@logger
39
+ @@logger = Logger.new(STDOUT)
40
+ @@logger.level = Logger::INFO
41
+ @@logger.progname = 'vines'
42
+ @@logger.formatter = Class.new(Logger::Formatter) do
43
+ def initialize
44
+ @time = "%Y-%m-%dT%H:%M:%SZ".freeze
45
+ @fmt = "[%s] %5s -- %s: %s\n".freeze
46
+ end
47
+ def call(severity, time, program, msg)
48
+ @fmt % [time.utc.strftime(@time), severity, program, msg2str(msg)]
49
+ end
50
+ end.new
51
+ end
52
+ @@logger
53
+ end
54
+ end
55
+ end
56
+
57
+ begin
58
+ # try to initialize lygneo AppConfig
59
+ require "#{Dir.pwd}/config/load_config.rb"
60
+ rescue LoadError
61
+ puts "Cannot find Lygneo environment! Fallback to vines configuration."
62
+ end
63
+
64
+ %w[
65
+ base64
66
+ bcrypt
67
+ digest/sha1
68
+ em-hiredis
69
+ eventmachine
70
+ fiber
71
+ fileutils
72
+ http/parser
73
+ json
74
+ logger
75
+ net/ldap
76
+ nokogiri
77
+ openssl
78
+ optparse
79
+ resolv
80
+ set
81
+ socket
82
+ yaml
83
+
84
+ vines/cli
85
+ vines/log
86
+ vines/jid
87
+
88
+ vines/stanza
89
+ vines/stanza/iq
90
+ vines/stanza/iq/query
91
+ vines/stanza/iq/auth
92
+ vines/stanza/iq/disco_info
93
+ vines/stanza/iq/disco_items
94
+ vines/stanza/iq/error
95
+ vines/stanza/iq/ping
96
+ vines/stanza/iq/private_storage
97
+ vines/stanza/iq/result
98
+ vines/stanza/iq/roster
99
+ vines/stanza/iq/session
100
+ vines/stanza/iq/vcard
101
+ vines/stanza/iq/version
102
+ vines/stanza/message
103
+ vines/stanza/presence
104
+ vines/stanza/presence/error
105
+ vines/stanza/presence/probe
106
+ vines/stanza/presence/subscribe
107
+ vines/stanza/presence/subscribed
108
+ vines/stanza/presence/unavailable
109
+ vines/stanza/presence/unsubscribe
110
+ vines/stanza/presence/unsubscribed
111
+ vines/stanza/pubsub
112
+ vines/stanza/pubsub/create
113
+ vines/stanza/pubsub/delete
114
+ vines/stanza/pubsub/publish
115
+ vines/stanza/pubsub/subscribe
116
+ vines/stanza/pubsub/unsubscribe
117
+
118
+ vines/storage
119
+ vines/storage/ldap
120
+ vines/storage/local
121
+ vines/storage/sql
122
+ vines/storage/null
123
+
124
+ vines/config
125
+ vines/config/host
126
+ vines/config/port
127
+ vines/config/pubsub
128
+
129
+ vines/store
130
+ vines/follower
131
+ vines/daemon
132
+ vines/error
133
+ vines/kit
134
+ vines/router
135
+ vines/token_bucket
136
+ vines/user
137
+ vines/version
138
+ vines/xmpp_server
139
+
140
+ vines/cluster
141
+ vines/cluster/connection
142
+ vines/cluster/publisher
143
+ vines/cluster/pubsub
144
+ vines/cluster/sessions
145
+ vines/cluster/subscriber
146
+
147
+ vines/stream
148
+ vines/stream/sasl
149
+ vines/stream/state
150
+ vines/stream/parser
151
+
152
+ vines/stream/client
153
+ vines/stream/client/session
154
+ vines/stream/client/start
155
+ vines/stream/client/tls
156
+ vines/stream/client/auth_restart
157
+ vines/stream/client/auth
158
+ vines/stream/client/bind_restart
159
+ vines/stream/client/bind
160
+ vines/stream/client/ready
161
+ vines/stream/client/closed
162
+
163
+ vines/stream/component
164
+ vines/stream/component/start
165
+ vines/stream/component/handshake
166
+ vines/stream/component/ready
167
+
168
+ vines/stream/http
169
+ vines/stream/http/session
170
+ vines/stream/http/sessions
171
+ vines/stream/http/request
172
+ vines/stream/http/start
173
+ vines/stream/http/auth
174
+ vines/stream/http/bind_restart
175
+ vines/stream/http/bind
176
+ vines/stream/http/ready
177
+
178
+ vines/stream/server
179
+ vines/stream/server/start
180
+ vines/stream/server/tls
181
+ vines/stream/server/auth_restart
182
+ vines/stream/server/auth
183
+ vines/stream/server/final_restart
184
+ vines/stream/server/ready
185
+
186
+ vines/stream/server/outbound/start
187
+ vines/stream/server/outbound/tls
188
+ vines/stream/server/outbound/tls_result
189
+ vines/stream/server/outbound/auth_restart
190
+ vines/stream/server/outbound/auth
191
+ vines/stream/server/outbound/auth_result
192
+ vines/stream/server/outbound/final_restart
193
+ vines/stream/server/outbound/final_features
194
+
195
+ vines/command/bcrypt
196
+ vines/command/cert
197
+ vines/command/init
198
+ vines/command/ldap
199
+ vines/command/restart
200
+ vines/command/schema
201
+ vines/command/start
202
+ vines/command/stop
203
+ ].each {|f| require f }
@@ -0,0 +1,57 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'test_helper'
4
+
5
+ describe Vines::Cluster::Publisher do
6
+ subject { Vines::Cluster::Publisher.new(cluster) }
7
+ let(:connection) { MiniTest::Mock.new }
8
+ let(:cluster) { MiniTest::Mock.new }
9
+
10
+ before do
11
+ cluster.expect :id, 'abc'
12
+ cluster.expect :connection, connection
13
+ end
14
+
15
+ describe '#broadcast' do
16
+ before do
17
+ msg = {from: 'abc', type: 'online', time: Time.now.to_i}.to_json
18
+ connection.expect :publish, nil, ["cluster:nodes:all", msg]
19
+ end
20
+
21
+ it 'publishes the message to every cluster node' do
22
+ subject.broadcast(:online)
23
+ connection.verify
24
+ cluster.verify
25
+ end
26
+ end
27
+
28
+ describe '#route' do
29
+ let(:stanza) { "<message>hello</message>" }
30
+
31
+ before do
32
+ msg = {from: 'abc', type: 'stanza', stanza: stanza}.to_json
33
+ connection.expect :publish, nil, ["cluster:nodes:node-42", msg]
34
+ end
35
+
36
+ it 'publishes the message to just one cluster node' do
37
+ subject.route(stanza, "node-42")
38
+ connection.verify
39
+ cluster.verify
40
+ end
41
+ end
42
+
43
+ describe '#update_user' do
44
+ let(:jid) { Vines::JID.new('alice@wonderland.lit') }
45
+
46
+ before do
47
+ msg = {from: 'abc', type: 'user', jid: jid.to_s}.to_json
48
+ connection.expect :publish, nil, ["cluster:nodes:node-42", msg]
49
+ end
50
+
51
+ it 'publishes the new user to just one cluster node' do
52
+ subject.update_user(jid, "node-42")
53
+ connection.verify
54
+ cluster.verify
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,47 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'test_helper'
4
+ require 'storage/storage_tests'
5
+ require 'storage/mock_redis'
6
+
7
+ describe Vines::Cluster::Sessions do
8
+ subject { Vines::Cluster::Sessions.new(cluster) }
9
+ let(:connection) { MockRedis.new }
10
+ let(:cluster) { OpenStruct.new(id: 'abc', connection: connection) }
11
+ let(:jid1) { 'alice@wonderland.lit/tea' }
12
+ let(:jid2) { 'alice@wonderland.lit/cake' }
13
+
14
+ describe 'when saving to the cluster' do
15
+ it 'writes to a redis hash' do
16
+ StorageTests::EMLoop.new do
17
+ subject.save(jid1, {available: true, interested: true})
18
+ subject.save(jid2, {available: false, interested: false})
19
+ EM.next_tick do
20
+ session1 = {node: 'abc', available: true, interested: true}
21
+ session2 = {node: 'abc', available: false, interested: false}
22
+ connection.db["sessions:alice@wonderland.lit"].size.must_equal 2
23
+ connection.db["sessions:alice@wonderland.lit"]['tea'].must_equal session1.to_json
24
+ connection.db["sessions:alice@wonderland.lit"]['cake'].must_equal session2.to_json
25
+ connection.db["cluster:nodes:abc"].to_a.must_equal [jid1, jid2]
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ describe 'when deleting from the cluster' do
32
+ it 'removes from a redis hash' do
33
+ StorageTests::EMLoop.new do
34
+ connection.db["sessions:alice@wonderland.lit"] = {}
35
+ connection.db["sessions:alice@wonderland.lit"]['tea'] = {node: 'abc', available: true}.to_json
36
+ connection.db["sessions:alice@wonderland.lit"]['cake'] = {node: 'abc', available: true}.to_json
37
+ connection.db["cluster:nodes:abc"] = Set.new([jid1, jid2])
38
+
39
+ subject.delete(jid1)
40
+ EM.next_tick do
41
+ connection.db["sessions:alice@wonderland.lit"].size.must_equal 1
42
+ connection.db["cluster:nodes:abc"].to_a.must_equal [jid2]
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,109 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'test_helper'
4
+
5
+ describe Vines::Cluster::Subscriber do
6
+ subject { Vines::Cluster::Subscriber.new(cluster) }
7
+ let(:connection) { MiniTest::Mock.new }
8
+ let(:cluster) { MiniTest::Mock.new }
9
+ let(:now) { Time.now.to_i }
10
+
11
+ before do
12
+ cluster.expect :id, 'abc'
13
+ end
14
+
15
+ describe '#subscribe' do
16
+ before do
17
+ cluster.expect :connect, connection
18
+ connection.expect :subscribe, nil, ['cluster:nodes:all']
19
+ connection.expect :subscribe, nil, ['cluster:nodes:abc']
20
+ connection.expect :on, nil, [:message]
21
+ end
22
+
23
+ it 'subscribes to its own channel and the broadcast channel' do
24
+ subject.subscribe
25
+ connection.verify
26
+ cluster.verify
27
+ end
28
+ end
29
+
30
+ describe 'when receiving a heartbeat broadcast message' do
31
+ before do
32
+ cluster.expect :poke, nil, ['node-42', now]
33
+ end
34
+
35
+ it 'pokes the session manager for the broadcasting node' do
36
+ msg = {from: 'node-42', type: 'heartbeat', time: now}.to_json
37
+ subject.send(:on_message, 'cluster:nodes:all', msg)
38
+ connection.verify
39
+ cluster.verify
40
+ end
41
+ end
42
+
43
+ describe 'when receiving an initial online broadcast message' do
44
+ before do
45
+ cluster.expect :poke, nil, ['node-42', now]
46
+ end
47
+
48
+ it 'pokes the session manager for the broadcasting node' do
49
+ msg = {from: 'node-42', type: 'online', time: now}.to_json
50
+ subject.send(:on_message, 'cluster:nodes:all', msg)
51
+ connection.verify
52
+ cluster.verify
53
+ end
54
+ end
55
+
56
+ describe 'when receiving an offline broadcast message' do
57
+ before do
58
+ cluster.expect :delete_sessions, nil, ['node-42']
59
+ end
60
+
61
+ it 'deletes the sessions for the broadcasting node' do
62
+ msg = {from: 'node-42', type: 'offline', time: now}.to_json
63
+ subject.send(:on_message, 'cluster:nodes:all', msg)
64
+ connection.verify
65
+ cluster.verify
66
+ end
67
+ end
68
+
69
+ describe 'when receiving a stanza routed to my node' do
70
+ let(:stream) { MiniTest::Mock.new }
71
+ let(:stanza) { "<message to='alice@wonderland.lit/tea'>hello</message>" }
72
+ let(:xml) { Nokogiri::XML(stanza).root }
73
+
74
+ before do
75
+ stream.expect :write, nil, [xml]
76
+ cluster.expect :connected_resources, [stream], ['alice@wonderland.lit/tea']
77
+ end
78
+
79
+ it 'writes the stanza to the connected user streams' do
80
+ msg = {from: 'node-42', type: 'stanza', stanza: stanza}.to_json
81
+ subject.send(:on_message, 'cluster:nodes:abc', msg)
82
+ stream.verify
83
+ connection.verify
84
+ cluster.verify
85
+ end
86
+ end
87
+
88
+ describe 'when receiving a user update message to my node' do
89
+ let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
90
+ let(:storage) { MiniTest::Mock.new }
91
+ let(:stream) { MiniTest::Mock.new }
92
+
93
+ before do
94
+ storage.expect :find_user, alice, [alice.jid.bare]
95
+ stream.expect :user, alice
96
+ cluster.expect :storage, storage, ['wonderland.lit']
97
+ cluster.expect :connected_resources, [stream], [alice.jid.bare]
98
+ end
99
+
100
+ it 'reloads the user from storage and updates their connected streams' do
101
+ msg = {from: 'node-42', type: 'user', jid: alice.jid.to_s}.to_json
102
+ subject.send(:on_message, 'cluster:nodes:abc', msg)
103
+ storage.verify
104
+ stream.verify
105
+ connection.verify
106
+ cluster.verify
107
+ end
108
+ end
109
+ end