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.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/LICENSE +19 -0
- data/README.md +7 -0
- data/Rakefile +23 -0
- data/bin/vines +4 -0
- data/conf/certs/README +39 -0
- data/conf/certs/ca-bundle.crt +3895 -0
- data/conf/config.rb +42 -0
- data/lib/vines/cli.rb +132 -0
- data/lib/vines/cluster/connection.rb +26 -0
- data/lib/vines/cluster/publisher.rb +55 -0
- data/lib/vines/cluster/pubsub.rb +92 -0
- data/lib/vines/cluster/sessions.rb +125 -0
- data/lib/vines/cluster/subscriber.rb +108 -0
- data/lib/vines/cluster.rb +246 -0
- data/lib/vines/command/bcrypt.rb +12 -0
- data/lib/vines/command/cert.rb +50 -0
- data/lib/vines/command/init.rb +68 -0
- data/lib/vines/command/ldap.rb +38 -0
- data/lib/vines/command/restart.rb +12 -0
- data/lib/vines/command/schema.rb +24 -0
- data/lib/vines/command/start.rb +28 -0
- data/lib/vines/command/stop.rb +18 -0
- data/lib/vines/config/host.rb +125 -0
- data/lib/vines/config/port.rb +132 -0
- data/lib/vines/config/pubsub.rb +108 -0
- data/lib/vines/config.rb +223 -0
- data/lib/vines/contact.rb +111 -0
- data/lib/vines/daemon.rb +78 -0
- data/lib/vines/error.rb +150 -0
- data/lib/vines/jid.rb +95 -0
- data/lib/vines/kit.rb +23 -0
- data/lib/vines/log.rb +24 -0
- data/lib/vines/router.rb +179 -0
- data/lib/vines/stanza/iq/auth.rb +18 -0
- data/lib/vines/stanza/iq/disco_info.rb +45 -0
- data/lib/vines/stanza/iq/disco_items.rb +29 -0
- data/lib/vines/stanza/iq/error.rb +16 -0
- data/lib/vines/stanza/iq/ping.rb +16 -0
- data/lib/vines/stanza/iq/private_storage.rb +83 -0
- data/lib/vines/stanza/iq/query.rb +10 -0
- data/lib/vines/stanza/iq/result.rb +16 -0
- data/lib/vines/stanza/iq/roster.rb +140 -0
- data/lib/vines/stanza/iq/session.rb +17 -0
- data/lib/vines/stanza/iq/vcard.rb +56 -0
- data/lib/vines/stanza/iq/version.rb +25 -0
- data/lib/vines/stanza/iq.rb +48 -0
- data/lib/vines/stanza/message.rb +40 -0
- data/lib/vines/stanza/presence/error.rb +23 -0
- data/lib/vines/stanza/presence/probe.rb +37 -0
- data/lib/vines/stanza/presence/subscribe.rb +42 -0
- data/lib/vines/stanza/presence/subscribed.rb +51 -0
- data/lib/vines/stanza/presence/unavailable.rb +15 -0
- data/lib/vines/stanza/presence/unsubscribe.rb +38 -0
- data/lib/vines/stanza/presence/unsubscribed.rb +38 -0
- data/lib/vines/stanza/presence.rb +141 -0
- data/lib/vines/stanza/pubsub/create.rb +39 -0
- data/lib/vines/stanza/pubsub/delete.rb +41 -0
- data/lib/vines/stanza/pubsub/publish.rb +66 -0
- data/lib/vines/stanza/pubsub/subscribe.rb +44 -0
- data/lib/vines/stanza/pubsub/unsubscribe.rb +30 -0
- data/lib/vines/stanza/pubsub.rb +22 -0
- data/lib/vines/stanza.rb +175 -0
- data/lib/vines/storage/ldap.rb +71 -0
- data/lib/vines/storage/local.rb +139 -0
- data/lib/vines/storage/null.rb +39 -0
- data/lib/vines/storage/sql.rb +138 -0
- data/lib/vines/storage.rb +239 -0
- data/lib/vines/store.rb +110 -0
- data/lib/vines/stream/client/auth.rb +74 -0
- data/lib/vines/stream/client/auth_restart.rb +29 -0
- data/lib/vines/stream/client/bind.rb +72 -0
- data/lib/vines/stream/client/bind_restart.rb +24 -0
- data/lib/vines/stream/client/closed.rb +13 -0
- data/lib/vines/stream/client/ready.rb +17 -0
- data/lib/vines/stream/client/session.rb +210 -0
- data/lib/vines/stream/client/start.rb +27 -0
- data/lib/vines/stream/client/tls.rb +38 -0
- data/lib/vines/stream/client.rb +84 -0
- data/lib/vines/stream/component/handshake.rb +26 -0
- data/lib/vines/stream/component/ready.rb +23 -0
- data/lib/vines/stream/component/start.rb +19 -0
- data/lib/vines/stream/component.rb +58 -0
- data/lib/vines/stream/http/auth.rb +22 -0
- data/lib/vines/stream/http/bind.rb +32 -0
- data/lib/vines/stream/http/bind_restart.rb +37 -0
- data/lib/vines/stream/http/ready.rb +29 -0
- data/lib/vines/stream/http/request.rb +172 -0
- data/lib/vines/stream/http/session.rb +120 -0
- data/lib/vines/stream/http/sessions.rb +65 -0
- data/lib/vines/stream/http/start.rb +23 -0
- data/lib/vines/stream/http.rb +157 -0
- data/lib/vines/stream/parser.rb +79 -0
- data/lib/vines/stream/sasl.rb +128 -0
- data/lib/vines/stream/server/auth.rb +13 -0
- data/lib/vines/stream/server/auth_restart.rb +13 -0
- data/lib/vines/stream/server/final_restart.rb +21 -0
- data/lib/vines/stream/server/outbound/auth.rb +31 -0
- data/lib/vines/stream/server/outbound/auth_restart.rb +20 -0
- data/lib/vines/stream/server/outbound/auth_result.rb +32 -0
- data/lib/vines/stream/server/outbound/final_features.rb +28 -0
- data/lib/vines/stream/server/outbound/final_restart.rb +20 -0
- data/lib/vines/stream/server/outbound/start.rb +20 -0
- data/lib/vines/stream/server/outbound/tls.rb +30 -0
- data/lib/vines/stream/server/outbound/tls_result.rb +34 -0
- data/lib/vines/stream/server/ready.rb +24 -0
- data/lib/vines/stream/server/start.rb +13 -0
- data/lib/vines/stream/server/tls.rb +13 -0
- data/lib/vines/stream/server.rb +150 -0
- data/lib/vines/stream/state.rb +60 -0
- data/lib/vines/stream.rb +247 -0
- data/lib/vines/token_bucket.rb +55 -0
- data/lib/vines/user.rb +123 -0
- data/lib/vines/version.rb +6 -0
- data/lib/vines/xmpp_server.rb +25 -0
- data/lib/vines.rb +203 -0
- data/test/cluster/publisher_test.rb +57 -0
- data/test/cluster/sessions_test.rb +47 -0
- data/test/cluster/subscriber_test.rb +109 -0
- data/test/config/host_test.rb +369 -0
- data/test/config/pubsub_test.rb +187 -0
- data/test/config_test.rb +732 -0
- data/test/contact_test.rb +102 -0
- data/test/error_test.rb +58 -0
- data/test/ext/nokogiri.rb +14 -0
- data/test/jid_test.rb +147 -0
- data/test/kit_test.rb +31 -0
- data/test/router_test.rb +243 -0
- data/test/stanza/iq/disco_info_test.rb +78 -0
- data/test/stanza/iq/disco_items_test.rb +49 -0
- data/test/stanza/iq/private_storage_test.rb +184 -0
- data/test/stanza/iq/roster_test.rb +229 -0
- data/test/stanza/iq/session_test.rb +25 -0
- data/test/stanza/iq/vcard_test.rb +146 -0
- data/test/stanza/iq/version_test.rb +64 -0
- data/test/stanza/iq_test.rb +70 -0
- data/test/stanza/message_test.rb +126 -0
- data/test/stanza/presence/probe_test.rb +50 -0
- data/test/stanza/presence/subscribe_test.rb +83 -0
- data/test/stanza/pubsub/create_test.rb +116 -0
- data/test/stanza/pubsub/delete_test.rb +169 -0
- data/test/stanza/pubsub/publish_test.rb +309 -0
- data/test/stanza/pubsub/subscribe_test.rb +205 -0
- data/test/stanza/pubsub/unsubscribe_test.rb +148 -0
- data/test/stanza_test.rb +85 -0
- data/test/storage/ldap_test.rb +201 -0
- data/test/storage/local_test.rb +59 -0
- data/test/storage/mock_redis.rb +97 -0
- data/test/storage/null_test.rb +29 -0
- data/test/storage/storage_tests.rb +182 -0
- data/test/storage_test.rb +85 -0
- data/test/store_test.rb +130 -0
- data/test/stream/client/auth_test.rb +137 -0
- data/test/stream/client/ready_test.rb +47 -0
- data/test/stream/client/session_test.rb +27 -0
- data/test/stream/component/handshake_test.rb +52 -0
- data/test/stream/component/ready_test.rb +103 -0
- data/test/stream/component/start_test.rb +39 -0
- data/test/stream/http/auth_test.rb +70 -0
- data/test/stream/http/ready_test.rb +86 -0
- data/test/stream/http/request_test.rb +209 -0
- data/test/stream/http/sessions_test.rb +49 -0
- data/test/stream/http/start_test.rb +50 -0
- data/test/stream/parser_test.rb +122 -0
- data/test/stream/sasl_test.rb +195 -0
- data/test/stream/server/auth_test.rb +61 -0
- data/test/stream/server/outbound/auth_test.rb +75 -0
- data/test/stream/server/ready_test.rb +98 -0
- data/test/test_helper.rb +42 -0
- data/test/token_bucket_test.rb +44 -0
- data/test/user_test.rb +96 -0
- data/vines.gemspec +30 -0
- metadata +387 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::Iq do
|
6
|
+
subject { Vines::Stanza::Iq.new(xml, stream) }
|
7
|
+
let(:stream) { MiniTest::Mock.new }
|
8
|
+
let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
|
9
|
+
let(:hatter) { Vines::User.new(jid: 'hatter@wonderland.lit/crumpets') }
|
10
|
+
let(:config) do
|
11
|
+
Vines::Config.new do
|
12
|
+
host 'wonderland.lit' do
|
13
|
+
storage(:fs) { dir Dir.tmpdir }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
class << stream
|
20
|
+
attr_accessor :config, :user
|
21
|
+
end
|
22
|
+
stream.user = hatter
|
23
|
+
stream.config = config
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'when addressed to a user rather than the server itself' do
|
27
|
+
let(:recipient) { MiniTest::Mock.new }
|
28
|
+
let(:xml) do
|
29
|
+
node(%q{
|
30
|
+
<iq id="42" type="set" to="alice@wonderland.lit/tea" from="hatter@wonderland.lit/crumpets">
|
31
|
+
<si xmlns="http://jabber.org/protocol/si" id="42_si" profile="http://jabber.org/protocol/si/profile/file-transfer">
|
32
|
+
<file xmlns="http://jabber.org/protocol/si/profile/file-transfer" name="file" size="1"/>
|
33
|
+
<feature xmlns="http://jabber.org/protocol/feature-neg">
|
34
|
+
<x xmlns="jabber:x:data" type="form">
|
35
|
+
<field var="stream-method" type="list-single">
|
36
|
+
<option>
|
37
|
+
<value>http://jabber.org/protocol/bytestreams</value>
|
38
|
+
</option>
|
39
|
+
<option>
|
40
|
+
<value>http://jabber.org/protocol/ibb</value>
|
41
|
+
</option>
|
42
|
+
</field>
|
43
|
+
</x>
|
44
|
+
</feature>
|
45
|
+
</si>
|
46
|
+
</iq>
|
47
|
+
})
|
48
|
+
end
|
49
|
+
|
50
|
+
before do
|
51
|
+
recipient.expect :user, alice, []
|
52
|
+
recipient.expect :write, nil, [xml]
|
53
|
+
stream.expect :connected_resources, [recipient], [alice.jid]
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'routes the stanza to the users connected resources' do
|
57
|
+
subject.process
|
58
|
+
stream.verify
|
59
|
+
recipient.verify
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'when given no type or body elements' do
|
64
|
+
let(:xml) { node('<iq type="set" id="42"/>') }
|
65
|
+
|
66
|
+
it 'raises a feature-not-implemented stanza error' do
|
67
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::Message do
|
6
|
+
subject { Vines::Stanza::Message.new(xml, stream) }
|
7
|
+
let(:stream) { MiniTest::Mock.new }
|
8
|
+
let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
|
9
|
+
let(:romeo) { Vines::User.new(jid: 'romeo@verona.lit/balcony') }
|
10
|
+
let(:config) do
|
11
|
+
Vines::Config.new do
|
12
|
+
host 'wonderland.lit' do
|
13
|
+
storage(:fs) { dir Dir.tmpdir }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
class << stream
|
20
|
+
attr_accessor :config, :user
|
21
|
+
end
|
22
|
+
stream.user = alice
|
23
|
+
stream.config = config
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'when message type attribute is invalid' do
|
27
|
+
let(:xml) { node('<message type="bogus">hello!</message>') }
|
28
|
+
|
29
|
+
it 'raises a bad-request stanza error' do
|
30
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'when the to address is missing' do
|
35
|
+
let(:xml) { node('<message>hello!</message>') }
|
36
|
+
let(:recipient) { MiniTest::Mock.new }
|
37
|
+
|
38
|
+
before do
|
39
|
+
recipient.expect :user, alice
|
40
|
+
recipient.expect :write, nil, [xml]
|
41
|
+
stream.expect :connected_resources, [recipient], [alice.jid.bare]
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'sends the message to the senders connected streams' do
|
45
|
+
subject.process
|
46
|
+
stream.verify
|
47
|
+
recipient.verify
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'when addressed to a non-user' do
|
52
|
+
let(:bogus) { Vines::JID.new('bogus@wonderland.lit/cake') }
|
53
|
+
let(:xml) { node(%Q{<message to="#{bogus}">hello!</message>}) }
|
54
|
+
let(:storage) { MiniTest::Mock.new }
|
55
|
+
|
56
|
+
before do
|
57
|
+
storage.expect :find_user, nil, [bogus]
|
58
|
+
stream.expect :storage, storage, [bogus.domain]
|
59
|
+
stream.expect :connected_resources, [], [bogus]
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'ignores the stanza' do
|
63
|
+
subject.process
|
64
|
+
stream.verify
|
65
|
+
storage.verify
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'when addressed to an offline user' do
|
70
|
+
let(:hatter) { Vines::User.new(jid: 'hatter@wonderland.lit/cake') }
|
71
|
+
let(:xml) { node(%Q{<message to="#{hatter.jid}">hello!</message>}) }
|
72
|
+
let(:storage) { MiniTest::Mock.new }
|
73
|
+
|
74
|
+
before do
|
75
|
+
storage.expect :find_user, hatter, [hatter.jid]
|
76
|
+
stream.expect :storage, storage, [hatter.jid.domain]
|
77
|
+
stream.expect :connected_resources, [], [hatter.jid]
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'raises a service-unavailable stanza error' do
|
81
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::ServiceUnavailable
|
82
|
+
stream.verify
|
83
|
+
storage.verify
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'when address to a local user in a different domain' do
|
88
|
+
let(:xml) { node(%Q{<message to="#{romeo.jid}">hello!</message>}) }
|
89
|
+
let(:expected) { node(%Q{<message to="#{romeo.jid}" from="#{alice.jid}">hello!</message>}) }
|
90
|
+
let(:recipient) { MiniTest::Mock.new }
|
91
|
+
|
92
|
+
before do
|
93
|
+
recipient.expect :user, romeo
|
94
|
+
recipient.expect :write, nil, [expected]
|
95
|
+
|
96
|
+
config.host 'verona.lit' do
|
97
|
+
storage(:fs) { dir Dir.tmpdir }
|
98
|
+
end
|
99
|
+
|
100
|
+
stream.expect :connected_resources, [recipient], [romeo.jid]
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'delivers the stanza to the user' do
|
104
|
+
subject.process
|
105
|
+
stream.verify
|
106
|
+
recipient.verify
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'when addressed to a remote user' do
|
111
|
+
let(:xml) { node(%Q{<message to="#{romeo.jid}">hello!</message>}) }
|
112
|
+
let(:expected) { node(%Q{<message to="#{romeo.jid}" from="#{alice.jid}">hello!</message>}) }
|
113
|
+
let(:router) { MiniTest::Mock.new }
|
114
|
+
|
115
|
+
before do
|
116
|
+
router.expect :route, nil, [expected]
|
117
|
+
stream.expect :router, router
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'routes rather than handle locally' do
|
121
|
+
subject.process
|
122
|
+
stream.verify
|
123
|
+
router.verify
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::Presence::Probe do
|
6
|
+
def setup
|
7
|
+
@alice = Vines::JID.new('alice@wonderland.lit/tea')
|
8
|
+
@stream = MiniTest::Mock.new
|
9
|
+
@config = Vines::Config.new do
|
10
|
+
host 'wonderland.lit' do
|
11
|
+
storage(:fs) { dir Dir.tmpdir }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_missing_to_address_raises
|
17
|
+
node = node(%q{<presence id="42" type="probe"/>})
|
18
|
+
stanza = Vines::Stanza::Presence::Probe.new(node, @stream)
|
19
|
+
def stanza.inbound?; false; end
|
20
|
+
|
21
|
+
@stream.expect(:user, Vines::User.new(jid: @alice))
|
22
|
+
|
23
|
+
assert_raises(Vines::StanzaErrors::BadRequest) { stanza.process }
|
24
|
+
assert @stream.verify
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_to_remote_address_routes
|
28
|
+
node = node(%q{<presence id="42" to="romeo@verona.lit" type="probe"/>})
|
29
|
+
stanza = Vines::Stanza::Presence::Probe.new(node, @stream)
|
30
|
+
def stanza.inbound?; false; end
|
31
|
+
|
32
|
+
expected = node(%Q{<presence id="42" to="romeo@verona.lit" type="probe" from="#{@alice}"/>})
|
33
|
+
router = MiniTest::Mock.new
|
34
|
+
router.expect(:route, nil, [expected])
|
35
|
+
|
36
|
+
@stream.expect(:router, router)
|
37
|
+
@stream.expect(:user, Vines::User.new(jid: @alice))
|
38
|
+
@stream.expect(:config, @config)
|
39
|
+
|
40
|
+
stanza.process
|
41
|
+
assert @stream.verify
|
42
|
+
assert router.verify
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def node(xml)
|
48
|
+
Nokogiri::XML(xml).root
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::Presence::Subscribe do
|
6
|
+
subject { Vines::Stanza::Presence::Subscribe.new(xml, stream) }
|
7
|
+
let(:stream) { MiniTest::Mock.new }
|
8
|
+
let(:alice) { Vines::JID.new('alice@wonderland.lit/tea') }
|
9
|
+
let(:hatter) { Vines::JID.new('hatter@wonderland.lit') }
|
10
|
+
let(:contact) { Vines::Contact.new(jid: hatter) }
|
11
|
+
|
12
|
+
before do
|
13
|
+
class << stream
|
14
|
+
attr_accessor :user, :nodes
|
15
|
+
def write(node)
|
16
|
+
@nodes ||= []
|
17
|
+
@nodes << node
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'outbound subscription to a local jid, but missing contact' do
|
23
|
+
let(:xml) { node(%q{<presence id="42" to="hatter@wonderland.lit" type="subscribe"/>}) }
|
24
|
+
let(:user) { MiniTest::Mock.new }
|
25
|
+
let(:storage) { MiniTest::Mock.new }
|
26
|
+
let(:recipient) { MiniTest::Mock.new }
|
27
|
+
|
28
|
+
before do
|
29
|
+
class << user
|
30
|
+
attr_accessor :jid
|
31
|
+
end
|
32
|
+
user.jid = alice
|
33
|
+
user.expect :request_subscription, nil, [hatter]
|
34
|
+
user.expect :contact, contact, [hatter]
|
35
|
+
|
36
|
+
storage.expect :save_user, nil, [user]
|
37
|
+
storage.expect :find_user, nil, [hatter]
|
38
|
+
|
39
|
+
recipient.expect :user, user
|
40
|
+
class << recipient
|
41
|
+
attr_accessor :nodes
|
42
|
+
def write(node)
|
43
|
+
@nodes ||= []
|
44
|
+
@nodes << node
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
stream.user = user
|
49
|
+
stream.expect :domain, 'wonderland.lit'
|
50
|
+
stream.expect :storage, storage, ['wonderland.lit']
|
51
|
+
stream.expect :storage, storage, ['wonderland.lit']
|
52
|
+
stream.expect :interested_resources, [recipient], [alice]
|
53
|
+
stream.expect :update_user_streams, nil, [user]
|
54
|
+
|
55
|
+
class << subject
|
56
|
+
def route_iq; false; end
|
57
|
+
def inbound?; false; end
|
58
|
+
def local?; true; end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'rejects the subscription with an unsubscribed response' do
|
63
|
+
subject.process
|
64
|
+
stream.verify
|
65
|
+
user.verify
|
66
|
+
storage.verify
|
67
|
+
stream.nodes.size.must_equal 1
|
68
|
+
|
69
|
+
expected = node(%q{<presence from="hatter@wonderland.lit" id="42" to="alice@wonderland.lit" type="unsubscribed"/>})
|
70
|
+
stream.nodes.first.must_equal expected
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'sends a roster set to the interested resources with subscription none' do
|
74
|
+
subject.process
|
75
|
+
recipient.nodes.size.must_equal 1
|
76
|
+
|
77
|
+
query = %q{<query xmlns="jabber:iq:roster"><item jid="hatter@wonderland.lit" subscription="none"/></query>}
|
78
|
+
expected = node(%Q{<iq to="alice@wonderland.lit/tea" type="set">#{query}</iq>})
|
79
|
+
recipient.nodes.first.remove_attribute('id') # id is random
|
80
|
+
recipient.nodes.first.must_equal expected
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::PubSub::Create do
|
6
|
+
subject { Vines::Stanza::PubSub::Create.new(xml, stream) }
|
7
|
+
let(:user) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
|
8
|
+
let(:stream) { MiniTest::Mock.new }
|
9
|
+
let(:config) do
|
10
|
+
Vines::Config.new do
|
11
|
+
host 'wonderland.lit' do
|
12
|
+
storage(:fs) { dir Dir.tmpdir }
|
13
|
+
pubsub 'games'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
class << stream
|
20
|
+
attr_accessor :config, :nodes, :user
|
21
|
+
def write(node)
|
22
|
+
@nodes ||= []
|
23
|
+
@nodes << node
|
24
|
+
end
|
25
|
+
end
|
26
|
+
stream.config = config
|
27
|
+
stream.user = user
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'when missing a to address' do
|
31
|
+
let(:xml) { create('') }
|
32
|
+
|
33
|
+
it 'raises a feature-not-implemented stanza error' do
|
34
|
+
stream.expect :domain, 'wonderland.lit'
|
35
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented
|
36
|
+
stream.verify
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'when addressed to bare server domain' do
|
41
|
+
let(:xml) { create('wonderland.lit') }
|
42
|
+
|
43
|
+
it 'raises a feature-not-implemented stanza error' do
|
44
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented
|
45
|
+
stream.verify
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'when addressed to a non-pubsub component' do
|
50
|
+
let(:router) { MiniTest::Mock.new }
|
51
|
+
let(:xml) { create('bogus.wonderland.lit') }
|
52
|
+
|
53
|
+
before do
|
54
|
+
router.expect :route, nil, [xml]
|
55
|
+
stream.expect :router, router
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'routes rather than handle locally' do
|
59
|
+
subject.process
|
60
|
+
stream.verify
|
61
|
+
router.verify
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'when attempting to create multiple nodes' do
|
66
|
+
let(:xml) { create('games.wonderland.lit', true) }
|
67
|
+
|
68
|
+
it 'raises a bad-request stanza error' do
|
69
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
|
70
|
+
stream.verify
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'when attempting to create duplicate nodes' do
|
75
|
+
let(:pubsub) { MiniTest::Mock.new }
|
76
|
+
let(:xml) { create('games.wonderland.lit') }
|
77
|
+
|
78
|
+
it 'raises a conflict stanza error' do
|
79
|
+
pubsub.expect :node?, true, ['game_13']
|
80
|
+
subject.stub :pubsub, pubsub do
|
81
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::Conflict
|
82
|
+
end
|
83
|
+
stream.verify
|
84
|
+
pubsub.verify
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'when given a valid stanza' do
|
89
|
+
let(:xml) { create('games.wonderland.lit') }
|
90
|
+
let(:expected) { result(user.jid, 'games.wonderland.lit') }
|
91
|
+
|
92
|
+
it 'sends an iq result stanza to sender' do
|
93
|
+
subject.process
|
94
|
+
stream.nodes.size.must_equal 1
|
95
|
+
stream.nodes.first.must_equal expected
|
96
|
+
stream.verify
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def create(to, multiple=false)
|
103
|
+
extra_create = "<create node='game_14'/>" if multiple
|
104
|
+
body = %Q{
|
105
|
+
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
106
|
+
<create node='game_13'/>
|
107
|
+
#{extra_create}
|
108
|
+
</pubsub>}
|
109
|
+
iq(type: 'set', to: to, id: 42, body: body)
|
110
|
+
end
|
111
|
+
|
112
|
+
def result(to, from)
|
113
|
+
body = '<pubsub xmlns="http://jabber.org/protocol/pubsub"><create node="game_13"/></pubsub>'
|
114
|
+
iq(from: from, id: 42, to: to, type: 'result', body: body)
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe Vines::Stanza::PubSub::Delete do
|
6
|
+
subject { Vines::Stanza::PubSub::Delete.new(xml, stream) }
|
7
|
+
let(:alice) { Vines::User.new(jid: 'alice@wonderland.lit/tea') }
|
8
|
+
let(:stream) { MiniTest::Mock.new }
|
9
|
+
let(:config) do
|
10
|
+
Vines::Config.new do
|
11
|
+
host 'wonderland.lit' do
|
12
|
+
storage(:fs) { dir Dir.tmpdir }
|
13
|
+
pubsub 'games'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
class << stream
|
20
|
+
attr_accessor :config, :domain, :nodes, :user
|
21
|
+
def write(node)
|
22
|
+
@nodes ||= []
|
23
|
+
@nodes << node
|
24
|
+
end
|
25
|
+
end
|
26
|
+
stream.config = config
|
27
|
+
stream.domain = 'wonderland.lit'
|
28
|
+
stream.user = alice
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'when missing a to address' do
|
32
|
+
let(:xml) do
|
33
|
+
node(%q{
|
34
|
+
<iq type='set' id='42'>
|
35
|
+
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
36
|
+
<delete node='game_13'/>
|
37
|
+
</pubsub>
|
38
|
+
</iq>
|
39
|
+
})
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'raises a feature-not-implemented stanza error' do
|
43
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented
|
44
|
+
stream.verify
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'when addressed to a bare server domain jid' do
|
49
|
+
let(:xml) do
|
50
|
+
node(%q{
|
51
|
+
<iq type='set' to='wonderland.lit' id='42'>
|
52
|
+
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
53
|
+
<delete node='game_13'/>
|
54
|
+
</pubsub>
|
55
|
+
</iq>
|
56
|
+
})
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'raises a feature-not-implemented stanza error' do
|
60
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented
|
61
|
+
stream.verify
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'when addressed to a non-pubsub address' do
|
66
|
+
let(:router) { MiniTest::Mock.new }
|
67
|
+
let(:xml) do
|
68
|
+
node(%q{
|
69
|
+
<iq type='set' to='bogus.wonderland.lit' id='42'>
|
70
|
+
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
71
|
+
<delete node='game_13'/>
|
72
|
+
</pubsub>
|
73
|
+
</iq>
|
74
|
+
})
|
75
|
+
end
|
76
|
+
|
77
|
+
before do
|
78
|
+
router.expect :route, nil, [xml]
|
79
|
+
stream.expect :router, router
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'routes rather than handle locally' do
|
83
|
+
subject.process
|
84
|
+
stream.verify
|
85
|
+
router.verify
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'when stanza contains multiple delete elements' do
|
90
|
+
let(:xml) do
|
91
|
+
node(%q{
|
92
|
+
<iq type='set' to='games.wonderland.lit' id='42'>
|
93
|
+
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
94
|
+
<delete node='game_13'/>
|
95
|
+
<delete node='game_14'/>
|
96
|
+
</pubsub>
|
97
|
+
</iq>
|
98
|
+
})
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'raises a bad-request stanza error' do
|
102
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::BadRequest
|
103
|
+
stream.verify
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'when deleting a missing node' do
|
108
|
+
let(:xml) do
|
109
|
+
node(%q{
|
110
|
+
<iq type='set' to='games.wonderland.lit' id='42'>
|
111
|
+
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
112
|
+
<delete node='game_13'/>
|
113
|
+
</pubsub>
|
114
|
+
</iq>
|
115
|
+
})
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'raises an item-not-found stanza error' do
|
119
|
+
-> { subject.process }.must_raise Vines::StanzaErrors::ItemNotFound
|
120
|
+
stream.verify
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'when valid stanza is received' do
|
125
|
+
let(:pubsub) { MiniTest::Mock.new }
|
126
|
+
let(:xml) do
|
127
|
+
node(%q{
|
128
|
+
<iq type='set' to='games.wonderland.lit' id='42'>
|
129
|
+
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
130
|
+
<delete node='game_13'/>
|
131
|
+
</pubsub>
|
132
|
+
</iq>
|
133
|
+
})
|
134
|
+
end
|
135
|
+
|
136
|
+
let(:result) { node(%Q{<iq from="games.wonderland.lit" id="42" to="#{alice.jid}" type="result"/>}) }
|
137
|
+
|
138
|
+
let(:broadcast) do
|
139
|
+
node(%q{
|
140
|
+
<message>
|
141
|
+
<event xmlns="http://jabber.org/protocol/pubsub#event">
|
142
|
+
<delete node="game_13"/>
|
143
|
+
</event>
|
144
|
+
</message>})
|
145
|
+
end
|
146
|
+
|
147
|
+
before do
|
148
|
+
pubsub.expect :node?, true, ['game_13']
|
149
|
+
pubsub.expect :publish, nil, ['game_13', broadcast]
|
150
|
+
pubsub.expect :delete_node, nil, ['game_13']
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'broadcasts the delete to subscribers' do
|
154
|
+
subject.stub :pubsub, pubsub do
|
155
|
+
subject.process
|
156
|
+
end
|
157
|
+
stream.verify
|
158
|
+
pubsub.verify
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'sends a result stanza to sender' do
|
162
|
+
subject.stub :pubsub, pubsub do
|
163
|
+
subject.process
|
164
|
+
end
|
165
|
+
stream.nodes.size.must_equal 1
|
166
|
+
stream.nodes.first.must_equal result
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|