vines 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +19 -0
- data/README +34 -0
- data/Rakefile +55 -0
- data/bin/vines +95 -0
- data/conf/certs/README +32 -0
- data/conf/certs/ca-bundle.crt +3987 -0
- data/conf/config.rb +114 -0
- data/lib/vines.rb +155 -0
- data/lib/vines/command/bcrypt.rb +12 -0
- data/lib/vines/command/cert.rb +49 -0
- data/lib/vines/command/init.rb +58 -0
- data/lib/vines/command/ldap.rb +35 -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.rb +191 -0
- data/lib/vines/contact.rb +99 -0
- data/lib/vines/daemon.rb +78 -0
- data/lib/vines/error.rb +150 -0
- data/lib/vines/jid.rb +56 -0
- data/lib/vines/kit.rb +23 -0
- data/lib/vines/router.rb +125 -0
- data/lib/vines/stanza.rb +55 -0
- data/lib/vines/stanza/iq.rb +50 -0
- data/lib/vines/stanza/iq/auth.rb +18 -0
- data/lib/vines/stanza/iq/disco_info.rb +25 -0
- data/lib/vines/stanza/iq/disco_items.rb +23 -0
- data/lib/vines/stanza/iq/error.rb +16 -0
- data/lib/vines/stanza/iq/ping.rb +16 -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 +153 -0
- data/lib/vines/stanza/iq/session.rb +22 -0
- data/lib/vines/stanza/iq/vcard.rb +58 -0
- data/lib/vines/stanza/message.rb +41 -0
- data/lib/vines/stanza/presence.rb +119 -0
- data/lib/vines/stanza/presence/error.rb +23 -0
- data/lib/vines/stanza/presence/probe.rb +38 -0
- data/lib/vines/stanza/presence/subscribe.rb +66 -0
- data/lib/vines/stanza/presence/subscribed.rb +64 -0
- data/lib/vines/stanza/presence/unavailable.rb +15 -0
- data/lib/vines/stanza/presence/unsubscribe.rb +57 -0
- data/lib/vines/stanza/presence/unsubscribed.rb +50 -0
- data/lib/vines/storage.rb +216 -0
- data/lib/vines/storage/couchdb.rb +119 -0
- data/lib/vines/storage/ldap.rb +59 -0
- data/lib/vines/storage/local.rb +66 -0
- data/lib/vines/storage/redis.rb +108 -0
- data/lib/vines/storage/sql.rb +174 -0
- data/lib/vines/store.rb +51 -0
- data/lib/vines/stream.rb +198 -0
- data/lib/vines/stream/client.rb +131 -0
- data/lib/vines/stream/client/auth.rb +94 -0
- data/lib/vines/stream/client/auth_restart.rb +33 -0
- data/lib/vines/stream/client/bind.rb +58 -0
- data/lib/vines/stream/client/bind_restart.rb +25 -0
- data/lib/vines/stream/client/closed.rb +13 -0
- data/lib/vines/stream/client/ready.rb +15 -0
- data/lib/vines/stream/client/start.rb +27 -0
- data/lib/vines/stream/client/tls.rb +37 -0
- data/lib/vines/stream/component.rb +53 -0
- data/lib/vines/stream/component/handshake.rb +25 -0
- data/lib/vines/stream/component/ready.rb +24 -0
- data/lib/vines/stream/component/start.rb +19 -0
- data/lib/vines/stream/http.rb +111 -0
- data/lib/vines/stream/http/http_request.rb +22 -0
- data/lib/vines/stream/http/http_state.rb +139 -0
- data/lib/vines/stream/http/http_states.rb +53 -0
- data/lib/vines/stream/parser.rb +78 -0
- data/lib/vines/stream/server.rb +126 -0
- data/lib/vines/stream/server/auth.rb +13 -0
- data/lib/vines/stream/server/auth_restart.rb +19 -0
- data/lib/vines/stream/server/final_restart.rb +20 -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 +28 -0
- data/lib/vines/stream/server/outbound/final_features.rb +27 -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 +31 -0
- data/lib/vines/stream/server/ready.rb +20 -0
- data/lib/vines/stream/server/start.rb +13 -0
- data/lib/vines/stream/server/tls.rb +13 -0
- data/lib/vines/stream/state.rb +55 -0
- data/lib/vines/token_bucket.rb +46 -0
- data/lib/vines/user.rb +124 -0
- data/lib/vines/version.rb +5 -0
- data/lib/vines/xmpp_server.rb +25 -0
- data/test/config_test.rb +396 -0
- data/test/error_test.rb +59 -0
- data/test/ext/nokogiri.rb +14 -0
- data/test/jid_test.rb +71 -0
- data/test/kit_test.rb +21 -0
- data/test/router_test.rb +60 -0
- data/test/stanza/iq/roster_test.rb +198 -0
- data/test/stanza/iq/session_test.rb +30 -0
- data/test/stanza/iq/vcard_test.rb +159 -0
- data/test/stanza/message_test.rb +124 -0
- data/test/stanza/presence/subscribe_test.rb +75 -0
- data/test/storage/couchdb_test.rb +102 -0
- data/test/storage/ldap_test.rb +207 -0
- data/test/storage/local_test.rb +54 -0
- data/test/storage/redis_test.rb +75 -0
- data/test/storage/sql_test.rb +55 -0
- data/test/storage/storage_tests.rb +134 -0
- data/test/storage_test.rb +90 -0
- data/test/stream/client/auth_test.rb +127 -0
- data/test/stream/client/ready_test.rb +47 -0
- data/test/stream/component/handshake_test.rb +46 -0
- data/test/stream/component/ready_test.rb +105 -0
- data/test/stream/component/start_test.rb +41 -0
- data/test/stream/parser_test.rb +121 -0
- data/test/stream/server/outbound/auth_test.rb +77 -0
- data/test/stream/server/ready_test.rb +100 -0
- data/test/token_bucket_test.rb +24 -0
- data/test/user_test.rb +64 -0
- metadata +318 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Nokogiri
|
4
|
+
module XML
|
5
|
+
class Node
|
6
|
+
# Override equality testing so we can use MiniTest::Mock#expect with
|
7
|
+
# Nokogiri::XML::Node arguments. Node's default behavior considers
|
8
|
+
# all nodes unequal.
|
9
|
+
def ==(node)
|
10
|
+
self.to_s == node.to_s
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/test/jid_test.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'vines'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
class JidTest < Test::Unit::TestCase
|
7
|
+
def test_nil_and_empty_jids
|
8
|
+
[nil, ''].each do |text|
|
9
|
+
assert_nothing_raised { Vines::JID.new(text) }
|
10
|
+
jid = Vines::JID.new(text)
|
11
|
+
assert_nil jid.node
|
12
|
+
assert_nil jid.resource
|
13
|
+
assert_equal '', jid.domain
|
14
|
+
assert_equal '', jid.to_s
|
15
|
+
assert_equal '', jid.bare.to_s
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_jid_too_long_error
|
20
|
+
assert_nothing_raised { Vines::JID.new('n' * 1023) }
|
21
|
+
assert_raises(ArgumentError) { Vines::JID.new('n' * 1024) }
|
22
|
+
assert_raises(ArgumentError) { Vines::JID.new('n', 'd' * 1024) }
|
23
|
+
assert_raises(ArgumentError) { Vines::JID.new('n', 'd', 'r' * 1024) }
|
24
|
+
assert_nothing_raised { Vines::JID.new('n' * 1023, 'd' * 1023, 'r' * 1023) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_domain_only
|
28
|
+
jid = Vines::JID.new('wonderland.lit')
|
29
|
+
assert_equal 'wonderland.lit', jid.to_s
|
30
|
+
assert_equal 'wonderland.lit', jid.domain
|
31
|
+
assert_nil jid.node
|
32
|
+
assert_nil jid.resource
|
33
|
+
assert_equal jid, jid.bare
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_bare_jid
|
37
|
+
jid = Vines::JID.new('alice', 'wonderland.lit')
|
38
|
+
assert_equal 'alice@wonderland.lit', jid.to_s
|
39
|
+
assert_equal 'wonderland.lit', jid.domain
|
40
|
+
assert_equal 'alice', jid.node
|
41
|
+
assert_nil jid.resource
|
42
|
+
assert_equal jid, jid.bare
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_parsed_bare_jid
|
46
|
+
jid = Vines::JID.new('alice@wonderland.lit')
|
47
|
+
assert_equal 'alice@wonderland.lit', jid.to_s
|
48
|
+
assert_equal 'wonderland.lit', jid.domain
|
49
|
+
assert_equal 'alice', jid.node
|
50
|
+
assert_nil jid.resource
|
51
|
+
assert_equal jid, jid.bare
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_full_jid
|
55
|
+
jid = Vines::JID.new('alice', 'wonderland.lit', 'tea')
|
56
|
+
assert_equal 'alice@wonderland.lit/tea', jid.to_s
|
57
|
+
assert_equal 'wonderland.lit', jid.domain
|
58
|
+
assert_equal 'alice', jid.node
|
59
|
+
assert_equal 'tea', jid.resource
|
60
|
+
assert_not_equal jid, jid.bare
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_parsed_full_jid
|
64
|
+
jid = Vines::JID.new('alice@wonderland.lit/tea')
|
65
|
+
assert_equal 'alice@wonderland.lit/tea', jid.to_s
|
66
|
+
assert_equal 'wonderland.lit', jid.domain
|
67
|
+
assert_equal 'alice', jid.node
|
68
|
+
assert_equal 'tea', jid.resource
|
69
|
+
assert_not_equal jid, jid.bare
|
70
|
+
end
|
71
|
+
end
|
data/test/kit_test.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'vines'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
class KitTest < Test::Unit::TestCase
|
7
|
+
def test_hmac
|
8
|
+
assert_equal(128, Vines::Kit.hmac('secret', 'username').length)
|
9
|
+
assert_equal(Vines::Kit.hmac('s1', 'u1'), Vines::Kit.hmac('s1', 'u1'))
|
10
|
+
assert_not_equal(Vines::Kit.hmac('s1', 'u1'), Vines::Kit.hmac('s2', 'u1'))
|
11
|
+
assert_not_equal(Vines::Kit.hmac('s1', 'u1'), Vines::Kit.hmac('s1', 'u2'))
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_uuid
|
15
|
+
ids = Array.new(1000) { Vines::Kit.uuid }
|
16
|
+
assert(ids.all? {|id| !id.nil? })
|
17
|
+
assert(ids.all? {|id| id.length == 36 })
|
18
|
+
assert(ids.all? {|id| id.match(/\w{8}-\w{4}-[4]\w{3}-[89ab]\w{3}-\w{12}/) })
|
19
|
+
assert_equal(ids.length, ids.uniq.length)
|
20
|
+
end
|
21
|
+
end
|
data/test/router_test.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'vines'
|
4
|
+
require 'minitest/mock'
|
5
|
+
require 'test/unit'
|
6
|
+
|
7
|
+
class RouterTest < Test::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
@router = Vines::Router.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_non_routable_stanza_is_local
|
13
|
+
stanza = MiniTest::Mock.new
|
14
|
+
stanza.expect(:name, 'auth')
|
15
|
+
assert @router.local?(stanza)
|
16
|
+
assert stanza.verify
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_stanza_missing_to_is_local
|
20
|
+
stanza = MiniTest::Mock.new
|
21
|
+
stanza.expect(:name, 'message')
|
22
|
+
stanza.expect(:[], nil, ['to'])
|
23
|
+
assert @router.local?(stanza)
|
24
|
+
assert stanza.verify
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_stanza_with_local_jid_is_local
|
28
|
+
config = MiniTest::Mock.new
|
29
|
+
config.expect(:vhost?, true, ['wonderland.lit'])
|
30
|
+
stream = MiniTest::Mock.new
|
31
|
+
stream.expect(:config, config)
|
32
|
+
@router << stream
|
33
|
+
|
34
|
+
stanza = MiniTest::Mock.new
|
35
|
+
stanza.expect(:name, 'message')
|
36
|
+
stanza.expect(:[], 'alice@wonderland.lit', ['to'])
|
37
|
+
assert @router.local?(stanza)
|
38
|
+
|
39
|
+
assert stanza.verify
|
40
|
+
assert stream.verify
|
41
|
+
assert config.verify
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_stanza_with_remote_jid_is_not_local
|
45
|
+
config = MiniTest::Mock.new
|
46
|
+
config.expect(:vhost?, false, ['wonderland.lit'])
|
47
|
+
stream = MiniTest::Mock.new
|
48
|
+
stream.expect(:config, config)
|
49
|
+
@router << stream
|
50
|
+
|
51
|
+
stanza = MiniTest::Mock.new
|
52
|
+
stanza.expect(:name, 'message')
|
53
|
+
stanza.expect(:[], 'alice@wonderland.lit', ['to'])
|
54
|
+
assert !@router.local?(stanza)
|
55
|
+
|
56
|
+
assert stanza.verify
|
57
|
+
assert stream.verify
|
58
|
+
assert config.verify
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'vines'
|
4
|
+
require 'ext/nokogiri'
|
5
|
+
require 'minitest/mock'
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
class RosterTest < Test::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
@stream = MiniTest::Mock.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_roster_get_with_empty_roster
|
14
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit')
|
15
|
+
expected = node(%q{<iq id="42" type="result"><query xmlns="jabber:iq:roster"/></iq>})
|
16
|
+
@stream.expect(:write, nil, [expected])
|
17
|
+
@stream.expect(:requested_roster!, nil)
|
18
|
+
@stream.expect(:user, alice)
|
19
|
+
|
20
|
+
node = node(%q{<iq id="42" type="get"><query xmlns='jabber:iq:roster'/></iq>})
|
21
|
+
stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
|
22
|
+
stanza.process
|
23
|
+
assert @stream.verify
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_roster_get_with_non_empty_roster
|
27
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit')
|
28
|
+
alice.roster << Vines::Contact.new(:jid => 'hatter@wonderland.lit')
|
29
|
+
alice.roster << Vines::Contact.new(:jid => 'cat@wonderland.lit', :groups => ['Friends', 'Cats'])
|
30
|
+
|
31
|
+
expected = node(%q{
|
32
|
+
<iq id="42" type="result">
|
33
|
+
<query xmlns="jabber:iq:roster">
|
34
|
+
<item jid="cat@wonderland.lit" subscription="none">
|
35
|
+
<group>Cats</group>
|
36
|
+
<group>Friends</group>
|
37
|
+
</item>
|
38
|
+
<item jid="hatter@wonderland.lit" subscription="none"/>
|
39
|
+
</query>
|
40
|
+
</iq>}.strip.gsub(/\n|\s{2,}/, ''))
|
41
|
+
|
42
|
+
@stream.expect(:write, nil, [expected])
|
43
|
+
@stream.expect(:requested_roster!, nil)
|
44
|
+
@stream.expect(:user, alice)
|
45
|
+
|
46
|
+
node = node(%q{<iq id="42" type="get"><query xmlns='jabber:iq:roster'/></iq>})
|
47
|
+
stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
|
48
|
+
stanza.process
|
49
|
+
assert @stream.verify
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_roster_set_with_invalid_to_address
|
53
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
|
54
|
+
@stream.expect(:user, alice)
|
55
|
+
|
56
|
+
node = node(%q{
|
57
|
+
<iq id="42" type="set" to="romeo@verona.lit">
|
58
|
+
<query xmlns="jabber:iq:roster"/>
|
59
|
+
</iq>}.strip.gsub(/\n|\s{2,}/, ''))
|
60
|
+
|
61
|
+
stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
|
62
|
+
assert_raise(Vines::StanzaErrors::Forbidden) { stanza.process }
|
63
|
+
assert @stream.verify
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_roster_set_with_no_items
|
67
|
+
node = node(%q{
|
68
|
+
<iq id="42" type="set">
|
69
|
+
<query xmlns="jabber:iq:roster"/>
|
70
|
+
</iq>}.strip.gsub(/\n|\s{2,}/, ''))
|
71
|
+
|
72
|
+
stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
|
73
|
+
assert_raise(Vines::StanzaErrors::BadRequest) { stanza.process }
|
74
|
+
assert @stream.verify
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_roster_set_with_two_items
|
78
|
+
node = node(%q{
|
79
|
+
<iq id="42" type="set">
|
80
|
+
<query xmlns="jabber:iq:roster">
|
81
|
+
<item jid="hatter@wonderland.lit"/>
|
82
|
+
<item jid="cat@wonderland.lit"/>
|
83
|
+
</query>
|
84
|
+
</iq>}.strip.gsub(/\n|\s{2,}/, ''))
|
85
|
+
|
86
|
+
stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
|
87
|
+
assert_raise(Vines::StanzaErrors::BadRequest) { stanza.process }
|
88
|
+
assert @stream.verify
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_roster_set_missing_jid
|
92
|
+
node = node(%q{
|
93
|
+
<iq id="42" type="set">
|
94
|
+
<query xmlns="jabber:iq:roster">
|
95
|
+
<item name="Mad Hatter"/>
|
96
|
+
</query>
|
97
|
+
</iq>}.strip.gsub(/\n|\s{2,}/, ''))
|
98
|
+
|
99
|
+
stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
|
100
|
+
assert_raise(Vines::StanzaErrors::BadRequest) { stanza.process }
|
101
|
+
assert @stream.verify
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_roster_set_with_duplicate_groups
|
105
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
|
106
|
+
@stream.expect(:user, alice)
|
107
|
+
|
108
|
+
node = node(%q{
|
109
|
+
<iq id="42" type="set">
|
110
|
+
<query xmlns="jabber:iq:roster">
|
111
|
+
<item jid="hatter@wonderland.lit" name="Mad Hatter">
|
112
|
+
<group>Friends</group>
|
113
|
+
<group>Friends</group>
|
114
|
+
</item>
|
115
|
+
</query>
|
116
|
+
</iq>}.strip.gsub(/\n|\s{2,}/, ''))
|
117
|
+
|
118
|
+
stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
|
119
|
+
assert_raise(Vines::StanzaErrors::BadRequest) { stanza.process }
|
120
|
+
assert @stream.verify
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_roster_set_with_empty_group
|
124
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
|
125
|
+
@stream.expect(:user, alice)
|
126
|
+
|
127
|
+
node = node(%q{
|
128
|
+
<iq id="42" type="set">
|
129
|
+
<query xmlns="jabber:iq:roster">
|
130
|
+
<item jid="hatter@wonderland.lit" name="Mad Hatter">
|
131
|
+
<group></group>
|
132
|
+
</item>
|
133
|
+
</query>
|
134
|
+
</iq>}.strip.gsub(/\n|\s{2,}/, ''))
|
135
|
+
|
136
|
+
stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
|
137
|
+
assert_raise(Vines::StanzaErrors::NotAcceptable) { stanza.process }
|
138
|
+
assert @stream.verify
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_roster_set_sends_results
|
142
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
|
143
|
+
storage = MiniTest::Mock.new
|
144
|
+
storage.expect(:save_user, nil, [alice])
|
145
|
+
|
146
|
+
recipient = MiniTest::Mock.new
|
147
|
+
recipient.expect(:user, alice)
|
148
|
+
def recipient.nodes; @nodes; end
|
149
|
+
def recipient.write(node)
|
150
|
+
@nodes ||= []
|
151
|
+
@nodes << node
|
152
|
+
end
|
153
|
+
|
154
|
+
router = MiniTest::Mock.new
|
155
|
+
router.expect(:interested_resources, [recipient], [alice.jid])
|
156
|
+
|
157
|
+
@stream.expect(:user, alice)
|
158
|
+
@stream.expect(:update_user_streams, nil, [alice])
|
159
|
+
@stream.expect(:router, router)
|
160
|
+
@stream.expect(:domain, 'wonderland.lit')
|
161
|
+
@stream.expect(:storage, storage, ['wonderland.lit'])
|
162
|
+
expected = node(%q{<iq id="42" type="result"/>})
|
163
|
+
@stream.expect(:write, nil, [expected])
|
164
|
+
|
165
|
+
node = node(%q{
|
166
|
+
<iq id="42" type="set">
|
167
|
+
<query xmlns="jabber:iq:roster">
|
168
|
+
<item jid="hatter@wonderland.lit" name="Mad Hatter">
|
169
|
+
<group>Friends</group>
|
170
|
+
</item>
|
171
|
+
</query>
|
172
|
+
</iq>}.strip.gsub(/\n|\s{2,}/, ''))
|
173
|
+
|
174
|
+
stanza = Vines::Stanza::Iq::Roster.new(node, @stream)
|
175
|
+
stanza.process
|
176
|
+
assert_nothing_raised { stanza.process }
|
177
|
+
assert @stream.verify
|
178
|
+
assert storage.verify
|
179
|
+
assert router.verify
|
180
|
+
|
181
|
+
expected = node(%q{
|
182
|
+
<iq type="set" to="alice@wonderland.lit/tea">
|
183
|
+
<query xmlns="jabber:iq:roster">
|
184
|
+
<item jid="hatter@wonderland.lit" name="Mad Hatter" subscription="none">
|
185
|
+
<group>Friends</group>
|
186
|
+
</item>
|
187
|
+
</query>
|
188
|
+
</iq>}.strip.gsub(/\n|\s{2,}/, ''))
|
189
|
+
recipient.nodes[0].remove_attribute('id') # id is random
|
190
|
+
assert_equal expected, recipient.nodes[0]
|
191
|
+
end
|
192
|
+
|
193
|
+
private
|
194
|
+
|
195
|
+
def node(xml)
|
196
|
+
Nokogiri::XML(xml).root
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'vines'
|
4
|
+
require 'ext/nokogiri'
|
5
|
+
require 'minitest/mock'
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
class SessionTest < Test::Unit::TestCase
|
9
|
+
def test_session
|
10
|
+
stream = MiniTest::Mock.new
|
11
|
+
stream.expect(:domain, 'wonderland.lit')
|
12
|
+
expected = node(%q{<iq from="wonderland.lit" id="42" type="result"/>})
|
13
|
+
stream.expect(:write, nil, [expected])
|
14
|
+
|
15
|
+
node = node(
|
16
|
+
%q{<iq id="42" to="wonderland.lit" type="set">
|
17
|
+
<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
|
18
|
+
</iq>})
|
19
|
+
|
20
|
+
stanza = Vines::Stanza::Iq::Session.new(node, stream)
|
21
|
+
stanza.process
|
22
|
+
assert stream.verify
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def node(xml)
|
28
|
+
Nokogiri::XML(xml).root
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'vines'
|
4
|
+
require 'ext/nokogiri'
|
5
|
+
require 'minitest/mock'
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
class VcardTest < Test::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
@stream = MiniTest::Mock.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_vcard_get_on_remote_jid_routes
|
14
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
|
15
|
+
node = node(%q{<iq id="42" to="romeo@verona.lit" type="get"><vCard xmlns="vcard-temp"/></iq>})
|
16
|
+
|
17
|
+
router = MiniTest::Mock.new
|
18
|
+
router.expect(:local?, false, [node])
|
19
|
+
router.expect(:route, nil, [node])
|
20
|
+
|
21
|
+
@stream.expect(:user, alice)
|
22
|
+
@stream.expect(:router, router)
|
23
|
+
|
24
|
+
stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
|
25
|
+
stanza.process
|
26
|
+
assert @stream.verify
|
27
|
+
assert router.verify
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_vcard_get_missing_to_address
|
31
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
|
32
|
+
node = node(%q{<iq id="42" type="get"><vCard xmlns="vcard-temp"/></iq>})
|
33
|
+
|
34
|
+
router = MiniTest::Mock.new
|
35
|
+
router.expect(:local?, true, [node])
|
36
|
+
|
37
|
+
card = node(%q{<vCard xmlns="vcard-temp"><FN>Alice in Wonderland</FN></vCard>})
|
38
|
+
|
39
|
+
storage = MiniTest::Mock.new
|
40
|
+
storage.expect(:find_vcard, card, [alice.jid.bare])
|
41
|
+
|
42
|
+
@stream.expect(:user, alice)
|
43
|
+
@stream.expect(:router, router)
|
44
|
+
@stream.expect(:domain, 'wonderland.lit')
|
45
|
+
@stream.expect(:storage, storage, ['wonderland.lit'])
|
46
|
+
expected = node(%q{
|
47
|
+
<iq id="42" to="alice@wonderland.lit/tea" type="result">
|
48
|
+
<vCard xmlns="vcard-temp">
|
49
|
+
<FN>Alice in Wonderland</FN>
|
50
|
+
</vCard>
|
51
|
+
</iq>}.strip.gsub(/\n|\s{2,}/, ''))
|
52
|
+
@stream.expect(:write, nil, [expected])
|
53
|
+
|
54
|
+
stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
|
55
|
+
stanza.process
|
56
|
+
assert @stream.verify
|
57
|
+
assert router.verify
|
58
|
+
assert storage.verify
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_vcard_get_another_user_includes_from_address
|
62
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
|
63
|
+
node = node(%q{<iq id="42" to="hatter@wonderland.lit" type="get"><vCard xmlns="vcard-temp"/></iq>})
|
64
|
+
|
65
|
+
router = MiniTest::Mock.new
|
66
|
+
router.expect(:local?, true, [node])
|
67
|
+
|
68
|
+
card = node(%q{<vCard xmlns="vcard-temp"><FN>Mad Hatter</FN></vCard>})
|
69
|
+
|
70
|
+
storage = MiniTest::Mock.new
|
71
|
+
storage.expect(:find_vcard, card, [Vines::JID.new('hatter@wonderland.lit')])
|
72
|
+
|
73
|
+
@stream.expect(:user, alice)
|
74
|
+
@stream.expect(:router, router)
|
75
|
+
@stream.expect(:domain, 'wonderland.lit')
|
76
|
+
@stream.expect(:storage, storage, ['wonderland.lit'])
|
77
|
+
expected = node(%q{
|
78
|
+
<iq from="hatter@wonderland.lit" id="42" to="alice@wonderland.lit/tea" type="result">
|
79
|
+
<vCard xmlns="vcard-temp">
|
80
|
+
<FN>Mad Hatter</FN>
|
81
|
+
</vCard>
|
82
|
+
</iq>}.strip.gsub(/\n|\s{2,}/, ''))
|
83
|
+
@stream.expect(:write, nil, [expected])
|
84
|
+
|
85
|
+
stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
|
86
|
+
stanza.process
|
87
|
+
assert @stream.verify
|
88
|
+
assert router.verify
|
89
|
+
assert storage.verify
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_missing_vcard_get_returns_item_not_found
|
93
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
|
94
|
+
node = node(%q{<iq id="42" type="get"><vCard xmlns="vcard-temp"/></iq>})
|
95
|
+
|
96
|
+
router = MiniTest::Mock.new
|
97
|
+
router.expect(:local?, true, [node])
|
98
|
+
|
99
|
+
storage = MiniTest::Mock.new
|
100
|
+
storage.expect(:find_vcard, nil, [alice.jid.bare])
|
101
|
+
|
102
|
+
@stream.expect(:user, alice)
|
103
|
+
@stream.expect(:router, router)
|
104
|
+
@stream.expect(:domain, 'wonderland.lit')
|
105
|
+
@stream.expect(:storage, storage, ['wonderland.lit'])
|
106
|
+
|
107
|
+
stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
|
108
|
+
assert_raise(Vines::StanzaErrors::ItemNotFound) { stanza.process }
|
109
|
+
assert @stream.verify
|
110
|
+
assert router.verify
|
111
|
+
assert storage.verify
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_vcard_set_on_another_user_returns_forbidden
|
115
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
|
116
|
+
node = node(%q{<iq id="42" to="hatter@wonderland.lit" type="set"><vCard xmlns="vcard-temp"><FN>Alice</FN></vCard></iq>})
|
117
|
+
|
118
|
+
router = MiniTest::Mock.new
|
119
|
+
router.expect(:local?, true, [node])
|
120
|
+
|
121
|
+
@stream.expect(:user, alice)
|
122
|
+
@stream.expect(:router, router)
|
123
|
+
|
124
|
+
stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
|
125
|
+
assert_raise(Vines::StanzaErrors::Forbidden) { stanza.process }
|
126
|
+
assert @stream.verify
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_vcard_set_returns_result
|
130
|
+
alice = Vines::User.new(:jid => 'alice@wonderland.lit/tea')
|
131
|
+
node = node(%q{<iq id="42" type="set"><vCard xmlns="vcard-temp"><FN>Alice</FN></vCard></iq>})
|
132
|
+
card = node(%q{<vCard xmlns="vcard-temp"><FN>Alice</FN></vCard>})
|
133
|
+
|
134
|
+
router = MiniTest::Mock.new
|
135
|
+
router.expect(:local?, true, [node])
|
136
|
+
|
137
|
+
storage = MiniTest::Mock.new
|
138
|
+
storage.expect(:save_vcard, nil, [alice.jid, card])
|
139
|
+
|
140
|
+
@stream.expect(:user, alice)
|
141
|
+
@stream.expect(:router, router)
|
142
|
+
@stream.expect(:domain, 'wonderland.lit')
|
143
|
+
@stream.expect(:storage, storage, ['wonderland.lit'])
|
144
|
+
expected = node(%q{<iq id="42" to="alice@wonderland.lit/tea" type="result"/>})
|
145
|
+
@stream.expect(:write, nil, [expected])
|
146
|
+
|
147
|
+
stanza = Vines::Stanza::Iq::Vcard.new(node, @stream)
|
148
|
+
stanza.process
|
149
|
+
assert @stream.verify
|
150
|
+
assert router.verify
|
151
|
+
assert storage.verify
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
def node(xml)
|
157
|
+
Nokogiri::XML(xml).root
|
158
|
+
end
|
159
|
+
end
|