diaspora-vines 0.1.2

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 (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/contact.rb +111 -0
  30. data/lib/vines/daemon.rb +78 -0
  31. data/lib/vines/error.rb +150 -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/contact_test.rb +102 -0
  125. data/test/error_test.rb +58 -0
  126. data/test/ext/nokogiri.rb +14 -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
@@ -0,0 +1,369 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'test_helper'
4
+
5
+ describe Vines::Config::Host do
6
+ def test_missing_storage
7
+ assert_raises(RuntimeError) do
8
+ Vines::Config.new do
9
+ host 'wonderland.lit' do
10
+ # missing storage
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ def test_bad_storage
17
+ assert_raises(RuntimeError) do
18
+ Vines::Config.new do
19
+ host 'wonderland.lit' do
20
+ storage 'bogus' do
21
+ # no bogus storage implementation
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def test_duplicate_storage
29
+ assert_raises(RuntimeError) do
30
+ Vines::Config.new do
31
+ host 'wonderland.lit' do
32
+ storage('fs') { dir Dir.tmpdir }
33
+ storage('fs') { dir Dir.tmpdir }
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def test_good_storage_raises_no_errors
40
+ config = Vines::Config.new do
41
+ host 'wonderland.lit' do
42
+ storage 'fs' do
43
+ dir Dir.tmpdir
44
+ end
45
+ end
46
+ end
47
+ refute_nil config.vhost('wonderland.lit').storage
48
+ end
49
+
50
+ def test_ldap_added_to_storage
51
+ config = Vines::Config.new do
52
+ host 'wonderland.lit' do
53
+ storage(:fs) { dir Dir.tmpdir }
54
+ # added after storage
55
+ ldap 'ldap.wonderland.lit', 1636 do
56
+ tls true
57
+ dn 'cn=Directory Manager'
58
+ password 'secr3t'
59
+ basedn 'dc=wonderland,dc=lit'
60
+ groupdn 'cn=chatters,dc=wonderland,dc=lit'
61
+ object_class 'person'
62
+ user_attr 'uid'
63
+ name_attr 'cn'
64
+ end
65
+ end
66
+
67
+ host 'verona.lit' do
68
+ ldap 'ldap.verona.lit', 1636 do
69
+ tls true
70
+ dn 'cn=Directory Manager'
71
+ password 'secr3t'
72
+ basedn 'dc=wonderland,dc=lit'
73
+ object_class 'person'
74
+ user_attr 'uid'
75
+ name_attr 'cn'
76
+ end
77
+ # added before storage
78
+ storage(:fs) { dir Dir.tmpdir }
79
+ end
80
+ end
81
+ %w[wonderland.lit verona.lit].each do |domain|
82
+ refute_nil config.vhost(domain).storage.ldap
83
+ assert config.vhost(domain).storage.ldap?
84
+ end
85
+ end
86
+
87
+ def test_empty_component_name_raises
88
+ assert_raises(RuntimeError) do
89
+ Vines::Config.new do
90
+ host 'wonderland.lit' do
91
+ storage(:fs) { dir Dir.tmpdir }
92
+ components '' => 'secr3t'
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ def test_nil_component_name_raises
99
+ assert_raises(RuntimeError) do
100
+ Vines::Config.new do
101
+ host 'wonderland.lit' do
102
+ storage(:fs) { dir Dir.tmpdir }
103
+ components nil => 'secr3t'
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ def test_empty_component_password_raises
110
+ assert_raises(RuntimeError) do
111
+ Vines::Config.new do
112
+ host 'wonderland.lit' do
113
+ storage(:fs) { dir Dir.tmpdir }
114
+ components 'tea' => ''
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ def test_nil_component_password_raises
121
+ assert_raises(RuntimeError) do
122
+ Vines::Config.new do
123
+ host 'wonderland.lit' do
124
+ storage(:fs) { dir Dir.tmpdir }
125
+ components 'tea' => nil
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ def test_duplicate_component_raises
132
+ assert_raises(RuntimeError) do
133
+ Vines::Config.new do
134
+ host 'wonderland.lit' do
135
+ storage(:fs) { dir Dir.tmpdir }
136
+ components 'tea' => 'one'
137
+ components 'TEA' => 'two'
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ def test_duplicate_component_in_one_call_raises
144
+ assert_raises(RuntimeError) do
145
+ Vines::Config.new do
146
+ host 'wonderland.lit' do
147
+ storage(:fs) { dir Dir.tmpdir }
148
+ components 'tea' => 'one', 'TEA' => 'two'
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ def test_duplicate_component_symbol_raises
155
+ assert_raises(RuntimeError) do
156
+ Vines::Config.new do
157
+ host 'wonderland.lit' do
158
+ storage(:fs) { dir Dir.tmpdir }
159
+ components 'tea' => 'one'
160
+ components :TEA => 'two'
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+ def test_invalid_host_domain_raises
167
+ assert_raises(ArgumentError) do
168
+ Vines::Config.new do
169
+ host 'wonderland.lit ' do
170
+ storage(:fs) { dir Dir.tmpdir }
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ def test_invalid_jid_host_domain_raises
177
+ assert_raises(RuntimeError) do
178
+ Vines::Config.new do
179
+ host 'alice@wonderland.lit' do
180
+ storage(:fs) { dir Dir.tmpdir }
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ def test_invalid_component_domain_raises
187
+ assert_raises(ArgumentError) do
188
+ Vines::Config.new do
189
+ host 'wonderland.lit' do
190
+ storage(:fs) { dir Dir.tmpdir }
191
+ components 'exam ple' => 'one'
192
+ end
193
+ end
194
+ end
195
+ end
196
+
197
+ def test_invalid_jid_component_domain_raises
198
+ assert_raises(RuntimeError) do
199
+ Vines::Config.new do
200
+ host 'wonderland.lit' do
201
+ storage(:fs) { dir Dir.tmpdir }
202
+ components 'alice@example' => 'one'
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ def test_multi_subdomain_component_raises
209
+ assert_raises(RuntimeError) do
210
+ Vines::Config.new do
211
+ host 'wonderland.lit' do
212
+ storage(:fs) { dir Dir.tmpdir }
213
+ components 'exam.ple' => 'one'
214
+ end
215
+ end
216
+ end
217
+ end
218
+
219
+ def test_case_insensitive_component_name
220
+ config = Vines::Config.new do
221
+ host 'WONDERLAND.LIT' do
222
+ storage(:fs) { dir Dir.tmpdir }
223
+ components 'TEA' => 'secr3t', CAKE: 'Passw0rd'
224
+ end
225
+ end
226
+ host = config.vhost('wonderland.lit')
227
+ refute_nil host
228
+ assert_equal 2, host.components.size
229
+ assert_equal host.components['tea.wonderland.lit'], 'secr3t'
230
+ assert_equal host.components['cake.wonderland.lit'], 'Passw0rd'
231
+ end
232
+
233
+ def test_component?
234
+ config = Vines::Config.new do
235
+ host 'wonderland.lit' do
236
+ storage(:fs) { dir Dir.tmpdir }
237
+ components 'tea' => 'secr3t', cake: 'passw0rd'
238
+ end
239
+ end
240
+ host = config.vhost('wonderland.lit')
241
+ refute_nil host
242
+ refute host.component?(nil)
243
+ refute host.component?('tea')
244
+ refute host.component?(:cake)
245
+ assert host.component?('tea.wonderland.lit')
246
+ assert host.component?(Vines::JID.new('tea.wonderland.lit'))
247
+ assert host.component?('cake.wonderland.lit')
248
+ assert_nil host.password(nil)
249
+ assert_nil host.password('bogus')
250
+ assert_equal 'secr3t', host.password('tea.wonderland.lit')
251
+ assert_equal 'passw0rd', host.password('cake.wonderland.lit')
252
+ expected = {'tea.wonderland.lit' => 'secr3t', 'cake.wonderland.lit' => 'passw0rd'}
253
+ assert_equal expected, host.components
254
+
255
+ refute config.component?(nil)
256
+ refute config.component?('tea')
257
+ refute config.component?('bogus')
258
+ assert config.component?('tea.wonderland.lit')
259
+ assert config.component?(Vines::JID.new('tea.wonderland.lit'))
260
+ assert config.component?('cake.wonderland.lit')
261
+ assert config.component?('tea.wonderland.lit', 'cake.wonderland.lit')
262
+ refute config.component?('tea.wonderland.lit', 'bogus.wonderland.lit')
263
+
264
+ assert_nil config.component_password(nil)
265
+ assert_nil config.component_password('bogus')
266
+ assert_equal 'secr3t', config.component_password('tea.wonderland.lit')
267
+ assert_equal 'passw0rd', config.component_password('cake.wonderland.lit')
268
+ end
269
+
270
+ def test_invalid_pubsub_domain_raises
271
+ assert_raises(ArgumentError) do
272
+ Vines::Config.new do
273
+ host 'wonderland.lit' do
274
+ storage(:fs) { dir Dir.tmpdir }
275
+ pubsub 'exam ple'
276
+ end
277
+ end
278
+ end
279
+ end
280
+
281
+ def test_invalid_jid_pubsub_domain_raises
282
+ assert_raises(RuntimeError) do
283
+ Vines::Config.new do
284
+ host 'wonderland.lit' do
285
+ storage(:fs) { dir Dir.tmpdir }
286
+ pubsub 'alice@example'
287
+ end
288
+ end
289
+ end
290
+ end
291
+
292
+ def test_multi_subdomain_pubsub_raises
293
+ assert_raises(RuntimeError) do
294
+ Vines::Config.new do
295
+ host 'wonderland.lit' do
296
+ storage(:fs) { dir Dir.tmpdir }
297
+ pubsub 'exam.ple'
298
+ end
299
+ end
300
+ end
301
+ end
302
+
303
+ def test_case_insensitive_pubsub_name
304
+ config = Vines::Config.new do
305
+ host 'WONDERLAND.LIT' do
306
+ storage(:fs) { dir Dir.tmpdir }
307
+ pubsub 'TEA', :CAKE
308
+ end
309
+ end
310
+ host = config.vhost('wonderland.lit')
311
+ refute_nil host
312
+ assert_equal 2, host.pubsubs.size
313
+ refute_nil host.pubsubs['tea.wonderland.lit']
314
+ refute_nil host.pubsubs['cake.wonderland.lit']
315
+ end
316
+
317
+ def test_pubsub?
318
+ config = Vines::Config.new do
319
+ host 'wonderland.lit' do
320
+ storage(:fs) { dir Dir.tmpdir }
321
+ pubsub 'tea', :cake
322
+ end
323
+ end
324
+ host = config.vhost('wonderland.lit')
325
+ refute_nil host
326
+ refute host.pubsub?(nil)
327
+ refute host.pubsub?('tea')
328
+ refute host.pubsub?(:cake)
329
+ assert host.pubsub?('tea.wonderland.lit')
330
+ assert host.pubsub?(Vines::JID.new('tea.wonderland.lit'))
331
+ assert host.pubsub?('cake.wonderland.lit')
332
+ assert_equal ['tea.wonderland.lit', 'cake.wonderland.lit'], host.pubsubs.keys
333
+
334
+ refute config.pubsub?(nil)
335
+ refute config.pubsub?('tea')
336
+ refute config.pubsub?('bogus')
337
+ assert config.pubsub?('tea.wonderland.lit')
338
+ assert config.pubsub?(Vines::JID.new('tea.wonderland.lit'))
339
+ assert config.pubsub?('cake.wonderland.lit')
340
+ refute config.pubsub?('alice@cake.wonderland.lit')
341
+ end
342
+
343
+ def test_default_private_storage_is_off
344
+ config = Vines::Config.new do
345
+ host 'wonderland.lit' do
346
+ storage(:fs) { dir Dir.tmpdir }
347
+ end
348
+ end
349
+ host = config.vhost('wonderland.lit')
350
+ refute_nil host
351
+ refute host.private_storage?
352
+ end
353
+
354
+ def test_enable_private_storage
355
+ config = Vines::Config.new do
356
+ host 'wonderland.lit' do
357
+ private_storage true
358
+ storage(:fs) { dir Dir.tmpdir }
359
+ end
360
+ end
361
+ host = config.vhost('wonderland.lit')
362
+ refute_nil host
363
+ assert host.private_storage?
364
+ assert config.private_storage?('wonderland.lit')
365
+ assert config.private_storage?(Vines::JID.new('wonderland.lit'))
366
+ refute config.private_storage?(Vines::JID.new('alice@wonderland.lit'))
367
+ refute config.private_storage?(nil)
368
+ end
369
+ end
@@ -0,0 +1,187 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'test_helper'
4
+
5
+ describe Vines::Config::PubSub do
6
+ subject { config.pubsub('topics.wonderland.lit') }
7
+ let(:alice) { Vines::JID.new('alice@wonderland.lit') }
8
+ let(:romeo) { Vines::JID.new('romeo@verona.lit') }
9
+ let(:config) do
10
+ @config = Vines::Config.new do
11
+ host 'wonderland.lit' do
12
+ storage(:fs) { dir Dir.tmpdir }
13
+ pubsub 'topics'
14
+ end
15
+ end
16
+ end
17
+
18
+ it 'adds and deletes a topic node' do
19
+ topic = 'rhode_island_is_neither_a_road_nor_an_island'
20
+ refute subject.node?(topic)
21
+ subject.add_node(topic)
22
+ assert subject.node?(topic)
23
+ subject.delete_node(topic)
24
+ refute subject.node?(topic)
25
+ end
26
+
27
+ it 'ignores deleting a missing topic node' do
28
+ topic = 'kittens_vs_puppies'
29
+ refute subject.node?(topic)
30
+ subject.delete_node(topic)
31
+ refute subject.node?(topic)
32
+ end
33
+
34
+ it 'subscribes a jid to a node' do
35
+ topic = 'with_jid'
36
+ jid = Vines::JID.new('alice@wonderland.lit')
37
+ subject.add_node(topic)
38
+ subject.subscribe(topic, jid)
39
+ assert subject.subscribed?(topic, jid.to_s)
40
+ assert subject.subscribed?(topic, jid)
41
+ end
42
+
43
+ it 'does not allow remote jids to subscribe to a node by default' do
44
+ topic = 'remote_jids_failed'
45
+ jid = 'romeo@verona.lit'
46
+ subject.add_node(topic)
47
+ subject.subscribe(topic, jid)
48
+ refute subject.subscribed?(topic, jid)
49
+ end
50
+
51
+ it 'allows remote jid subscriptions when cross domain messages are enabled' do
52
+ topic = 'remote_jids_allowed'
53
+ jid = 'romeo@verona.lit'
54
+ config.vhost('wonderland.lit').cross_domain_messages true
55
+ subject.add_node(topic)
56
+ subject.subscribe(topic, jid)
57
+ assert subject.subscribed?(topic, jid)
58
+ end
59
+
60
+ it 'ignores subscribing to a missing node' do
61
+ topic = 'bogus'
62
+ jid = 'alice@wonderland.lit'
63
+ refute subject.node?(topic)
64
+ subject.subscribe(topic, jid)
65
+ refute subject.node?(topic)
66
+ refute subject.subscribed?(topic, jid)
67
+ end
68
+
69
+ it 'deletes the node after unsubscribing' do
70
+ topic = 'delete_me'
71
+ jid = 'alice@wonderland.lit/tea'
72
+ subject.add_node(topic)
73
+ subject.subscribe(topic, jid)
74
+ assert subject.subscribed?(topic, jid)
75
+ subject.unsubscribe(topic, jid)
76
+ refute subject.subscribed?(topic, jid)
77
+ refute subject.node?(topic)
78
+ end
79
+
80
+ it 'unsubscribes a jid from all topics' do
81
+ topic = 'pirates_vs_ninjas'
82
+ topic2 = 'pirates_vs_ninjas_2'
83
+ jid = 'alice@wonderland.lit'
84
+ jid2 = 'hatter@wonderland.lit'
85
+ subject.add_node(topic)
86
+ subject.add_node(topic2)
87
+
88
+ subject.subscribe(topic, jid)
89
+ subject.subscribe(topic, jid2)
90
+ subject.subscribe(topic2, jid)
91
+ assert subject.subscribed?(topic, jid)
92
+ assert subject.subscribed?(topic, jid2)
93
+ assert subject.subscribed?(topic2, jid)
94
+
95
+ subject.unsubscribe_all(jid)
96
+ refute subject.node?(topic2)
97
+ refute subject.subscribed?(topic, jid)
98
+ refute subject.subscribed?(topic2, jid)
99
+ assert subject.subscribed?(topic, jid2)
100
+ end
101
+
102
+ describe 'when publishing a message to a topic node' do
103
+ let(:xml) do
104
+ node(%q{
105
+ <iq type='set' to='topics.wonderland.lit'>
106
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
107
+ <publish node='pirates_vs_ninjas'>
108
+ <item id='item_42'>
109
+ <entry xmlns='http://www.w3.org/2005/Atom'>
110
+ <title>Test</title>
111
+ <summary>This is a summary.</summary>
112
+ </entry>
113
+ </item>
114
+ </publish>
115
+ </pubsub>
116
+ </iq>})
117
+ end
118
+
119
+ let(:recipient) do
120
+ recipient = MiniTest::Mock.new
121
+ recipient.expect :user, Vines::User.new(jid: alice)
122
+ class << recipient
123
+ attr_accessor :nodes
124
+ def write(node)
125
+ @nodes ||= []
126
+ @nodes << node
127
+ end
128
+ end
129
+ recipient
130
+ end
131
+
132
+ before do
133
+ router = MiniTest::Mock.new
134
+ router.expect :connected_resources, [recipient], [alice, 'topics.wonderland.lit']
135
+ class << router
136
+ attr_accessor :nodes
137
+ def route(node)
138
+ @nodes ||= []
139
+ @nodes << node
140
+ end
141
+ end
142
+
143
+ class << config
144
+ attr_accessor :router
145
+ end
146
+ config.router = router
147
+ config.vhost('wonderland.lit').cross_domain_messages true
148
+
149
+ subject.add_node(topic)
150
+ subject.subscribe(topic, alice)
151
+ subject.subscribe(topic, romeo)
152
+ end
153
+
154
+ let(:topic) { 'pirates_vs_ninjas' }
155
+
156
+ it 'writes the message to local connected resource streams' do
157
+ expected = xml.clone
158
+ expected['to'] = 'alice@wonderland.lit'
159
+ expected['from'] = 'topics.wonderland.lit'
160
+
161
+ subject.publish(topic, xml)
162
+ config.router.verify
163
+ recipient.verify
164
+
165
+ # id is random
166
+ received = recipient.nodes.first
167
+ received['id'].wont_be_nil
168
+ received.remove_attribute('id')
169
+ received.must_equal expected
170
+ end
171
+
172
+ it 'routes the message to remote jids' do
173
+ expected = xml.clone
174
+ expected['to'] = 'romeo@verona.lit'
175
+ expected['from'] = 'topics.wonderland.lit'
176
+
177
+ subject.publish(topic, xml)
178
+ config.router.verify
179
+
180
+ # id is random
181
+ routed = config.router.nodes.first
182
+ routed['id'].wont_be_nil
183
+ routed.remove_attribute('id')
184
+ routed.must_equal expected
185
+ end
186
+ end
187
+ end