xmpp4r 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/ChangeLog +12 -0
  2. data/Rakefile +2 -4
  3. data/data/doc/xmpp4r/examples/advanced/adventure/adventuremuc.rb +6 -6
  4. data/data/doc/xmpp4r/examples/advanced/adventure/world.rb +3 -3
  5. data/data/doc/xmpp4r/examples/advanced/minimuc.rb +5 -5
  6. data/data/doc/xmpp4r/examples/advanced/xmpping.rb +17 -4
  7. data/data/doc/xmpp4r/examples/advanced/xmppingrc.sample +5 -0
  8. data/data/doc/xmpp4r/examples/basic/echo_threaded.rb +6 -2
  9. data/data/doc/xmpp4r/examples/basic/muc_owner_config.rb +13 -0
  10. data/lib/xmpp4r.rb +0 -6
  11. data/lib/xmpp4r/bytestreams/helper/filetransfer.rb +6 -7
  12. data/lib/xmpp4r/bytestreams/helper/ibb/base.rb +5 -6
  13. data/lib/xmpp4r/bytestreams/helper/ibb/target.rb +3 -5
  14. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb +1 -1
  15. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb +10 -8
  16. data/lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb +3 -5
  17. data/lib/xmpp4r/bytestreams/iq/bytestreams.rb +11 -17
  18. data/lib/xmpp4r/bytestreams/iq/si.rb +13 -32
  19. data/lib/xmpp4r/callbacks.rb +124 -0
  20. data/lib/xmpp4r/client.rb +2 -5
  21. data/lib/xmpp4r/command/helper/responder.rb +53 -0
  22. data/lib/xmpp4r/command/iq/command.rb +154 -0
  23. data/lib/xmpp4r/connection.rb +49 -12
  24. data/lib/xmpp4r/dataforms/x/data.rb +66 -29
  25. data/lib/xmpp4r/delay/x/delay.rb +2 -3
  26. data/lib/xmpp4r/discovery/iq/discoinfo.rb +20 -33
  27. data/lib/xmpp4r/discovery/iq/discoitems.rb +5 -28
  28. data/lib/xmpp4r/error.rb +5 -10
  29. data/lib/xmpp4r/feature_negotiation/iq/feature.rb +2 -20
  30. data/lib/xmpp4r/httpbinding.rb +5 -0
  31. data/lib/xmpp4r/httpbinding/client.rb +285 -0
  32. data/lib/xmpp4r/iq.rb +22 -41
  33. data/lib/xmpp4r/message.rb +8 -38
  34. data/lib/xmpp4r/muc.rb +2 -0
  35. data/lib/xmpp4r/muc/helper/mucclient.rb +50 -1
  36. data/lib/xmpp4r/muc/helper/simplemucclient.rb +2 -2
  37. data/lib/xmpp4r/muc/iq/mucowner.rb +11 -0
  38. data/lib/xmpp4r/muc/x/muc.rb +2 -30
  39. data/lib/xmpp4r/muc/x/mucuserinvite.rb +4 -2
  40. data/lib/xmpp4r/muc/x/mucuseritem.rb +4 -2
  41. data/lib/xmpp4r/presence.rb +7 -35
  42. data/lib/xmpp4r/pubsub.rb +1 -0
  43. data/lib/xmpp4r/pubsub/helper/nodebrowser.rb +174 -0
  44. data/lib/xmpp4r/pubsub/helper/nodehelper.rb +153 -0
  45. data/lib/xmpp4r/pubsub/helper/servicehelper.rb +326 -0
  46. data/lib/xmpp4r/pubsub/iq/pubsub.rb +19 -0
  47. data/lib/xmpp4r/pubsub/stanzas/event.rb +49 -0
  48. data/lib/xmpp4r/pubsub/stanzas/item.rb +27 -0
  49. data/lib/xmpp4r/pubsub/stanzas/items.rb +35 -0
  50. data/lib/xmpp4r/pubsub/stanzas/subscription.rb +58 -0
  51. data/lib/xmpp4r/query.rb +4 -32
  52. data/lib/xmpp4r/rexmladdons.rb +7 -772
  53. data/lib/xmpp4r/roster/helper/roster.rb +29 -50
  54. data/lib/xmpp4r/roster/iq/roster.rb +6 -35
  55. data/lib/xmpp4r/roster/x/roster.rb +13 -30
  56. data/lib/xmpp4r/rpc.rb +2 -0
  57. data/lib/xmpp4r/rpc/helper/client.rb +114 -0
  58. data/lib/xmpp4r/rpc/helper/server.rb +75 -0
  59. data/lib/xmpp4r/rpc/helper/xmlrpcaddons.rb +57 -0
  60. data/lib/xmpp4r/rpc/iq/rpc.rb +24 -0
  61. data/lib/xmpp4r/sasl.rb +1 -1
  62. data/lib/xmpp4r/semaphore.rb +38 -0
  63. data/lib/xmpp4r/stream.rb +104 -165
  64. data/lib/xmpp4r/streamparser.rb +2 -2
  65. data/lib/xmpp4r/vcard/iq/vcard.rb +5 -12
  66. data/lib/xmpp4r/version/helper/responder.rb +2 -1
  67. data/lib/xmpp4r/version/iq/version.rb +6 -18
  68. data/lib/xmpp4r/x.rb +20 -26
  69. data/lib/xmpp4r/xmpp4r.rb +1 -1
  70. data/lib/xmpp4r/xmppelement.rb +152 -0
  71. data/lib/xmpp4r/{xmlstanza.rb → xmppstanza.rb} +17 -29
  72. data/setup.rb +1 -0
  73. data/test/bytestreams/tc_ibb.rb +8 -8
  74. data/test/dataforms/tc_data.rb +81 -0
  75. data/test/lib/clienttester.rb +20 -17
  76. data/test/muc/tc_muc_mucclient.rb +48 -23
  77. data/test/muc/tc_muc_simplemucclient.rb +7 -4
  78. data/test/muc/tc_mucowner.rb +50 -0
  79. data/test/pubsub/tc_helper.rb +227 -0
  80. data/test/roster/tc_helper.rb +181 -55
  81. data/test/roster/tc_iqqueryroster.rb +33 -0
  82. data/test/roster/tc_xroster.rb +6 -3
  83. data/test/rpc/tc_helper.rb +84 -0
  84. data/test/tc_callbacks.rb +2 -1
  85. data/test/tc_class_names.rb +9 -1
  86. data/test/tc_error.rb +1 -0
  87. data/test/tc_iq.rb +13 -12
  88. data/test/tc_message.rb +1 -0
  89. data/test/tc_presence.rb +1 -0
  90. data/test/tc_rexml.rb +1 -1
  91. data/test/tc_stream.rb +147 -102
  92. data/test/tc_streamComponent.rb +94 -0
  93. data/test/tc_streamError.rb +67 -29
  94. data/test/tc_streamSend.rb +1 -1
  95. data/test/tc_xmppstanza.rb +125 -0
  96. data/test/ts_xmpp4r.rb +37 -28
  97. data/test/version/tc_helper.rb +14 -0
  98. data/test/version/tc_iqqueryversion.rb +4 -3
  99. metadata +163 -123
  100. data/data/doc/xmpp4r/examples/basic/echo_nonthreaded.rb +0 -32
  101. data/lib/callbacks.rb +0 -122
  102. data/test/tc_streamThreaded.rb +0 -168
  103. data/test/tc_xmlstanza.rb +0 -76
@@ -6,6 +6,7 @@ $:.unshift File::dirname(__FILE__) + '/../../lib'
6
6
  require 'test/unit'
7
7
  require File::dirname(__FILE__) + '/../lib/clienttester'
8
8
  require 'xmpp4r/muc'
9
+ require 'xmpp4r/semaphore'
9
10
  include Jabber
10
11
 
11
12
  class SimpleMUCClientTest < Test::Unit::TestCase
@@ -23,8 +24,8 @@ class SimpleMUCClientTest < Test::Unit::TestCase
23
24
  m = MUC::SimpleMUCClient.new(@client)
24
25
 
25
26
  block_args = []
26
- wait = Mutex.new
27
- block = lambda { |*a| block_args = a; wait.unlock }
27
+ wait = Semaphore.new
28
+ block = lambda { |*a| block_args = a; wait.run }
28
29
  m.on_room_message(&block)
29
30
  m.on_message(&block)
30
31
  m.on_private_message(&block)
@@ -49,6 +50,7 @@ class SimpleMUCClientTest < Test::Unit::TestCase
49
50
  }
50
51
  m.my_jid = 'hag66@shakespeare.lit/pda'
51
52
  assert_equal(m, m.join('darkcave@macbeth.shakespeare.lit/thirdwitch'))
53
+ wait_state
52
54
  assert(m.active?)
53
55
  assert_equal(3, m.roster.size)
54
56
 
@@ -62,9 +64,10 @@ class SimpleMUCClientTest < Test::Unit::TestCase
62
64
  send(msg.set_from('darkcave@macbeth.shakespeare.lit/thirdwitch').set_to('hag66@shakespeare.lit/pda'))
63
65
  }
64
66
  assert_nil(m.subject)
65
- wait.lock
67
+ wait.wait
66
68
  m.subject = 'TestCasing room'
67
- wait.lock
69
+ wait_state
70
+ wait.wait
68
71
  assert_equal([nil, 'thirdwitch', 'TestCasing room'], block_args)
69
72
  assert_equal('TestCasing room', m.subject)
70
73
  end
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift '../lib'
4
+
5
+ require 'test/unit'
6
+ require 'xmpp4r'
7
+ require 'xmpp4r/muc'
8
+ include Jabber
9
+
10
+ class MUCOwnerTest < Test::Unit::TestCase
11
+ def test_parse
12
+ s = <<EOF
13
+ <iq from='darkcave@macbeth.shakespeare.lit'
14
+ id='config1'
15
+ to='crone1@shakespeare.lit/desktop'
16
+ type='result'>
17
+ <query xmlns='http://jabber.org/protocol/muc#owner'>
18
+ <x xmlns='jabber:x:data' type='form'>
19
+ <title>Configuration for "darkcave" Room</title>
20
+ <instructions>
21
+ Complete this form to make changes to
22
+ the configuration of your room.
23
+ </instructions>
24
+ <field
25
+ type='hidden'
26
+ var='FORM_TYPE'>
27
+ <value>http://jabber.org/protocol/muc#roomconfig</value>
28
+ </field>
29
+ <field
30
+ label='Natural-Language Room Name'
31
+ type='text-single'
32
+ var='muc#roomconfig_roomname'>
33
+ <value>A Dark Cave</value>
34
+ </field>
35
+ </x>
36
+ </query>
37
+ </iq>
38
+ EOF
39
+ iq = Iq::import(REXML::Document.new(s).root)
40
+
41
+ assert_kind_of(Iq, iq)
42
+ assert_kind_of(MUC::IqQueryMUCOwner, iq.query)
43
+ assert_kind_of(Dataforms::XData, iq.query.x)
44
+ assert_kind_of(Dataforms::XData, iq.query.x('jabber:x:data'))
45
+ assert_kind_of(Dataforms::XData, iq.query.x(Dataforms::XData))
46
+
47
+ assert_equal(1, iq.query.x.fields.size)
48
+ assert_equal('Natural-Language Room Name', iq.query.x.fields[0].label)
49
+ end
50
+ end
@@ -0,0 +1,227 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift File::dirname(__FILE__) + '/../../lib'
4
+
5
+ require 'test/unit'
6
+ require File::dirname(__FILE__) + '/../lib/clienttester'
7
+
8
+ require 'xmpp4r'
9
+ require 'xmpp4r/pubsub/helper/servicehelper'
10
+ include Jabber
11
+
12
+
13
+ class PubSub::ServiceHelperTest < Test::Unit::TestCase
14
+ include ClientTester
15
+
16
+ def test_create
17
+ h = PubSub::ServiceHelper.new(@client,'pubsub.example.org')
18
+ assert_kind_of(PubSub::ServiceHelper, h)
19
+
20
+ state { |iq|
21
+ assert_kind_of(Jabber::Iq, iq)
22
+ assert_equal(:set, iq.type)
23
+ assert_equal(1, iq.children.size)
24
+ assert_equal('http://jabber.org/protocol/pubsub', iq.pubsub.namespace)
25
+ assert_equal(1, iq.pubsub.children.size)
26
+ assert_equal('create', iq.pubsub.children.first.name)
27
+ assert_equal('mynode', iq.pubsub.children.first.attributes['node'])
28
+ send("<iq type='result' to='#{iq.from}' from='#{iq.to}' id='#{iq.id}'>
29
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
30
+ <create node='#{iq.pubsub.children.first.attributes['node']}'/>
31
+ </pubsub>
32
+ </iq>")
33
+ }
34
+ assert_equal('mynode', h.create('mynode'))
35
+ wait_state
36
+ end
37
+
38
+ def test_delete
39
+ h = PubSub::ServiceHelper.new(@client,'pubsub.example.org')
40
+
41
+ state { |iq|
42
+ assert_kind_of(Jabber::Iq, iq)
43
+ assert_equal(:set, iq.type)
44
+ assert_equal(1, iq.children.size)
45
+ assert_equal(1, iq.pubsub.children.size)
46
+ assert_equal('delete', iq.pubsub.children.first.name)
47
+ assert_equal('mynode', iq.pubsub.children.first.attributes['node'])
48
+ send("<iq type='result' to='#{iq.from}' from='#{iq.to}' id='#{iq.id}'/>")
49
+ }
50
+ h.delete('mynode')
51
+ wait_state
52
+ end
53
+
54
+ def test_publish
55
+ item1 = Jabber::PubSub::Item.new
56
+ item1.text = 'foobar'
57
+ h = PubSub::ServiceHelper.new(@client,'pubsub.example.org')
58
+
59
+ state { |iq|
60
+ assert_kind_of(Jabber::Iq, iq)
61
+ assert_equal(:set, iq.type)
62
+ assert_equal(1, iq.children.size)
63
+ assert_equal(1, iq.pubsub.children.size)
64
+ assert_equal('publish', iq.pubsub.children[0].name)
65
+ assert_equal(1, iq.pubsub.children[0].children.size)
66
+ assert_equal('item', iq.pubsub.children[0].children[0].name)
67
+ assert_nil(iq.pubsub.children[0].children[0].attributes['id'])
68
+ assert_equal(1, iq.pubsub.children[0].children[0].children.size)
69
+ assert_equal(item1.children.to_s, iq.pubsub.children[0].children[0].children[0].to_s)
70
+ send("<iq type='result' to='#{iq.from}' from='#{iq.to}' id='#{iq.id}'/>")
71
+ }
72
+ h.publish('mynode', item1)
73
+ wait_state
74
+ end
75
+
76
+ def test_items
77
+ item1 = Jabber::PubSub::Item.new("1")
78
+ item1.text = 'foobar'
79
+ item2 = Jabber::PubSub::Item.new("2")
80
+ item2.text = 'barfoo'
81
+
82
+ h = PubSub::ServiceHelper.new(@client,'pubsub.example.org')
83
+
84
+ state { |iq|
85
+ assert_kind_of(Jabber::Iq, iq)
86
+ assert_equal(:get, iq.type)
87
+ assert_equal(1, iq.pubsub.children.size)
88
+ assert_equal('items', iq.pubsub.children.first.name)
89
+ assert_equal('mynode', iq.pubsub.children.first.attributes['node'])
90
+ send("<iq type='result' to='#{iq.from}' from='#{iq.to}' id='#{iq.id}'>
91
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
92
+ <items node='mynode'>
93
+ #{item1.to_s}
94
+ #{item2.to_s}
95
+ </items>
96
+ </pubsub>
97
+ </iq>")
98
+ }
99
+
100
+ items = h.items('mynode')
101
+ assert_equal(2, items.size)
102
+ assert_kind_of(REXML::Text, items['1'])
103
+ assert_kind_of(REXML::Text, items['2'])
104
+ assert_equal(item1.children.to_s, items['1'].to_s)
105
+ assert_equal(item2.children.to_s, items['2'].to_s)
106
+ wait_state
107
+ end
108
+
109
+ def test_affiliations
110
+ h = PubSub::ServiceHelper.new(@client,'pubsub.example.org')
111
+
112
+ state { |iq|
113
+ assert_kind_of(Jabber::Iq, iq)
114
+ assert_equal(:get, iq.type)
115
+ assert_equal(1, iq.pubsub.children.size)
116
+ assert_equal('affiliations', iq.pubsub.children.first.name)
117
+ send("<iq type='result' to='#{iq.from}' from='#{iq.to}' id='#{iq.id}'>
118
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
119
+ <affiliations>
120
+ <affiliation node='node1' affiliation='owner'/>
121
+ <affiliation node='node2' affiliation='publisher'/>
122
+ <affiliation node='node5' affiliation='outcast'/>
123
+ <affiliation node='node6' affiliation='owner'/>
124
+ </affiliations>
125
+ </pubsub>
126
+ </iq>")
127
+ }
128
+
129
+ a = h.affiliations
130
+ assert_kind_of(Hash, a)
131
+ assert_equal(4, a.size)
132
+ assert_equal(:owner, a['node1'])
133
+ assert_equal(:publisher, a['node2'])
134
+ assert_equal(:outcast, a['node5'])
135
+ assert_equal(:owner, a['node6'])
136
+ wait_state
137
+ end
138
+
139
+ def test_subscriptions
140
+ h = PubSub::ServiceHelper.new(@client,'pubsub.example.org')
141
+
142
+ state { |iq|
143
+ assert_kind_of(Jabber::Iq, iq)
144
+ assert_equal(:get, iq.type)
145
+ assert_equal(1, iq.pubsub.children.size)
146
+ assert_equal('subscriptions', iq.pubsub.children.first.name)
147
+ send("<iq type='result' to='#{iq.from}' from='#{iq.to}' id='#{iq.id}'>
148
+ <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
149
+ <subscriptions node='princely_musings'>
150
+ <subscription jid='hamlet@denmark.lit' subscription='subscribed'/>
151
+ <subscription jid='polonius@denmark.lit' subscription='unconfigured'/>
152
+ <subscription jid='bernardo@denmark.lit' subscription='subscribed' subid='123-abc'/>
153
+ <subscription jid='bernardo@denmark.lit' subscription='subscribed' subid='004-yyy'/>
154
+ </subscriptions>
155
+ </pubsub>
156
+ </iq>")
157
+ }
158
+
159
+ s = h.subscriptions('mynode')
160
+ assert_kind_of(Array,s)
161
+ assert_equal(4,s.size)
162
+ assert_kind_of(REXML::Element,s[0])
163
+ assert_kind_of(REXML::Element,s[1])
164
+ assert_kind_of(REXML::Element,s[2])
165
+ assert_kind_of(REXML::Element,s[3])
166
+ wait_state
167
+ end
168
+
169
+ def test_get_all_subscriptions
170
+ h = PubSub::ServiceHelper.new(@client,'pubsub.example.org')
171
+
172
+ state { |iq|
173
+ assert_kind_of(Jabber::Iq, iq)
174
+ assert_equal(:get, iq.type)
175
+ assert_equal(1, iq.pubsub.children.size)
176
+ assert_equal('subscriptions', iq.pubsub.children.first.name)
177
+ send("<iq type='result' to='#{iq.from}' from='#{iq.to}' id='#{iq.id}'>
178
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
179
+ <subscriptions>
180
+ <subscription node='node1' jid='francisco@denmark.lit' subscription='subscribed'/>
181
+ <subscription node='node2' jid='francisco@denmark.lit' subscription='subscribed'/>
182
+ <subscription node='node5' jid='francisco@denmark.lit' subscription='unconfigured'/>
183
+ <subscription node='node6' jid='francisco@denmark.lit' subscription='pending'/>
184
+ </subscriptions>
185
+ </pubsub>
186
+ </iq>")
187
+ }
188
+
189
+ s = h.subscriptions
190
+ assert_kind_of(Array,s)
191
+ assert_equal(4,s.size)
192
+ assert_kind_of(REXML::Element,s[0])
193
+ assert_kind_of(REXML::Element,s[1])
194
+ assert_kind_of(REXML::Element,s[2])
195
+ assert_kind_of(REXML::Element,s[3])
196
+ wait_state
197
+ end
198
+
199
+ def test_subscribers
200
+ h = PubSub::ServiceHelper.new(@client,'pubsub.example.org')
201
+
202
+ state { |iq|
203
+ assert_kind_of(Jabber::Iq, iq)
204
+ assert_equal(:get, iq.type)
205
+ assert_equal(1, iq.pubsub.children.size)
206
+ assert_equal('subscriptions', iq.pubsub.children.first.name)
207
+ send("<iq type='result' to='#{iq.from}' from='#{iq.to}' id='#{iq.id}'>
208
+ <pubsub xmlns='http://jabber.org/protocol/pubsub'>
209
+ <subscriptions node='princely_musings'>
210
+ <subscription jid='peter@denmark.lit' subscription='subscribed'/>
211
+ <subscription jid='frank@denmark.lit' subscription='subscribed'/>
212
+ <subscription jid='albrecht@denmark.lit' subscription='unconfigured'/>
213
+ <subscription jid='hugo@denmark.lit' subscription='pending'/>
214
+ </subscriptions>
215
+ </pubsub>
216
+ </iq>")
217
+ }
218
+
219
+ s = h.subscribers('princely_musings')
220
+ assert_equal(4,s.size)
221
+ assert_kind_of(String,s[0])
222
+ assert_kind_of(String,s[1])
223
+ assert_kind_of(String,s[2])
224
+ assert_kind_of(String,s[3])
225
+ wait_state
226
+ end
227
+ end
@@ -7,6 +7,7 @@ require File::dirname(__FILE__) + '/../lib/clienttester'
7
7
 
8
8
  require 'xmpp4r'
9
9
  require 'xmpp4r/roster/helper/roster'
10
+ require 'xmpp4r/semaphore'
10
11
  include Jabber
11
12
 
12
13
  class Roster::HelperTest < Test::Unit::TestCase
@@ -29,14 +30,13 @@ class Roster::HelperTest < Test::Unit::TestCase
29
30
  </iq>")
30
31
  }
31
32
 
32
- query_waiter = Mutex.new
33
- query_waiter.lock
33
+ query_waiter = Semaphore.new
34
34
  h = Roster::Helper::new(@client)
35
35
  h.add_query_callback { |iq|
36
- query_waiter.unlock
36
+ query_waiter.run
37
37
  }
38
38
  wait_state
39
- query_waiter.lock
39
+ query_waiter.wait
40
40
 
41
41
  assert_equal([nil], h.groups)
42
42
  jids = h.find_by_group(nil).collect { |item| item.jid }.sort
@@ -73,12 +73,11 @@ class Roster::HelperTest < Test::Unit::TestCase
73
73
  </iq>")
74
74
  }
75
75
 
76
- query_waiter = Mutex.new
77
- query_waiter.lock
76
+ query_waiter = Semaphore.new
78
77
  h = Roster::Helper::new(@client)
79
- h.add_query_callback { |iq| query_waiter.unlock }
78
+ h.add_query_callback { |iq| query_waiter.run }
80
79
  wait_state
81
- query_waiter.lock
80
+ query_waiter.wait
82
81
 
83
82
  assert_equal([], h.groups)
84
83
  assert_nil(h['a@b.c'])
@@ -88,7 +87,7 @@ class Roster::HelperTest < Test::Unit::TestCase
88
87
  <item jid='a@b.c'/>
89
88
  </query>
90
89
  </iq>")
91
- query_waiter.lock
90
+ query_waiter.wait
92
91
 
93
92
  assert_kind_of(Roster::Helper::RosterItem, h['a@b.c'])
94
93
  assert_equal(JID.new('a@b.c'), h['a@b.c'].jid)
@@ -101,7 +100,7 @@ class Roster::HelperTest < Test::Unit::TestCase
101
100
  <item jid='a@b.c' subscription='from' name='ABC' ask='subscribe'/>
102
101
  </query>
103
102
  </iq>")
104
- query_waiter.lock
103
+ query_waiter.wait
105
104
 
106
105
  assert_kind_of(Roster::Helper::RosterItem, h['a@b.c'])
107
106
  assert_equal(JID.new('a@b.c'), h['a@b.c'].jid)
@@ -114,7 +113,7 @@ class Roster::HelperTest < Test::Unit::TestCase
114
113
  <item jid='a@b.c'/>
115
114
  </query>
116
115
  </iq>")
117
- query_waiter.lock
116
+ query_waiter.wait
118
117
 
119
118
  assert_kind_of(Roster::Helper::RosterItem, h['a@b.c'])
120
119
  assert_equal(JID.new('a@b.c'), h['a@b.c'].jid)
@@ -127,7 +126,7 @@ class Roster::HelperTest < Test::Unit::TestCase
127
126
  <item jid='a@b.c' subscription='remove'/>
128
127
  </query>
129
128
  </iq>")
130
- query_waiter.lock
129
+ query_waiter.wait
131
130
 
132
131
  assert_nil(h['a@b.c'])
133
132
  end
@@ -141,22 +140,25 @@ class Roster::HelperTest < Test::Unit::TestCase
141
140
  </iq>")
142
141
  }
143
142
 
144
- query_waiter = Mutex.new
145
- query_waiter.lock
146
- presence_waiter = Mutex.new
147
- presence_waiter.lock
143
+ query_waiter = Semaphore.new
144
+ presence_waiter = Semaphore.new
148
145
  h = Roster::Helper::new(@client)
149
146
  h.add_query_callback { |iq|
150
- query_waiter.unlock
147
+ query_waiter.run
151
148
  }
152
149
  cb_item, cb_op, cb_p = nil, nil, nil
153
150
  h.add_presence_callback { |item,oldpres,pres|
151
+ # HACK:
152
+ # if two stanzas are expected for one sent stanza,
153
+ # race conditions may appear here
154
+ Thread.pass
155
+
154
156
  cb_item, cb_op, cb_p = item, oldpres, pres
155
- presence_waiter.unlock
157
+ presence_waiter.run
156
158
  }
157
159
 
158
160
  wait_state
159
- query_waiter.lock
161
+ query_waiter.wait
160
162
 
161
163
  assert_equal(false, h['a@b.c'].online?)
162
164
  presences = 0
@@ -164,7 +166,7 @@ class Roster::HelperTest < Test::Unit::TestCase
164
166
  assert_equal(0, presences)
165
167
 
166
168
  send("<presence from='a@b.c/r'/>")
167
- presence_waiter.lock
169
+ presence_waiter.wait
168
170
 
169
171
  assert_kind_of(Roster::Helper::RosterItem, cb_item)
170
172
  assert_nil(cb_op)
@@ -176,7 +178,7 @@ class Roster::HelperTest < Test::Unit::TestCase
176
178
  assert_equal(1, presences)
177
179
 
178
180
  send("<presence from='a@b.c/r2'/>")
179
- presence_waiter.lock
181
+ presence_waiter.wait
180
182
 
181
183
  assert_kind_of(Roster::Helper::RosterItem, cb_item)
182
184
  assert_nil(cb_op)
@@ -188,7 +190,7 @@ class Roster::HelperTest < Test::Unit::TestCase
188
190
  assert_equal(2, presences)
189
191
 
190
192
  send("<presence from='a@b.c/r'/>")
191
- presence_waiter.lock
193
+ presence_waiter.wait
192
194
 
193
195
  assert_kind_of(Roster::Helper::RosterItem, cb_item)
194
196
  assert_kind_of(Presence, cb_op)
@@ -201,7 +203,7 @@ class Roster::HelperTest < Test::Unit::TestCase
201
203
  assert_equal(2, presences)
202
204
 
203
205
  send("<presence from='a@b.c/r' type='error'/>")
204
- presence_waiter.lock
206
+ presence_waiter.wait
205
207
 
206
208
  assert_kind_of(Roster::Helper::RosterItem, cb_item)
207
209
  assert_kind_of(Presence, cb_op)
@@ -214,7 +216,7 @@ class Roster::HelperTest < Test::Unit::TestCase
214
216
  assert_equal(2, presences)
215
217
 
216
218
  send("<presence from='a@b.c/r2' type='unavailable'/>")
217
- presence_waiter.lock
219
+ presence_waiter.wait
218
220
 
219
221
  assert_kind_of(Roster::Helper::RosterItem, cb_item)
220
222
  assert_kind_of(Presence, cb_op)
@@ -227,7 +229,7 @@ class Roster::HelperTest < Test::Unit::TestCase
227
229
  assert_equal(2, presences)
228
230
 
229
231
  send("<presence from='a@b.c/r'/>")
230
- presence_waiter.lock
232
+ presence_waiter.wait
231
233
 
232
234
  assert_kind_of(Roster::Helper::RosterItem, cb_item)
233
235
  assert_kind_of(Presence, cb_op)
@@ -240,7 +242,7 @@ class Roster::HelperTest < Test::Unit::TestCase
240
242
  assert_equal(2, presences)
241
243
 
242
244
  send("<presence from='a@b.c/r2'/>")
243
- presence_waiter.lock
245
+ presence_waiter.wait
244
246
 
245
247
  assert_kind_of(Roster::Helper::RosterItem, cb_item)
246
248
  assert_kind_of(Presence, cb_op)
@@ -254,7 +256,7 @@ class Roster::HelperTest < Test::Unit::TestCase
254
256
 
255
257
  send("<presence from='a@b.c' type='error'/>")
256
258
  2.times {
257
- presence_waiter.lock
259
+ presence_waiter.wait
258
260
 
259
261
  assert_kind_of(Roster::Helper::RosterItem, cb_item)
260
262
  assert_kind_of(Presence, cb_op)
@@ -267,7 +269,7 @@ class Roster::HelperTest < Test::Unit::TestCase
267
269
  assert_equal(1, presences)
268
270
 
269
271
  send("<presence from='a@b.c/r'/>")
270
- presence_waiter.lock
272
+ presence_waiter.wait
271
273
 
272
274
  assert_kind_of(Roster::Helper::RosterItem, cb_item)
273
275
  assert_nil(cb_op)
@@ -286,12 +288,11 @@ class Roster::HelperTest < Test::Unit::TestCase
286
288
  </iq>")
287
289
  }
288
290
 
289
- query_waiter = Mutex.new
290
- query_waiter.lock
291
+ query_waiter = Semaphore.new
291
292
  h = Roster::Helper::new(@client)
292
- h.add_query_callback { |iq| query_waiter.unlock }
293
+ h.add_query_callback { |iq| query_waiter.run }
293
294
  wait_state
294
- query_waiter.lock
295
+ query_waiter.wait
295
296
 
296
297
  state { |iq|
297
298
  assert_kind_of(Iq, iq)
@@ -309,10 +310,11 @@ class Roster::HelperTest < Test::Unit::TestCase
309
310
  assert_kind_of(Presence, pres)
310
311
  assert_equal(:subscribe, pres.type)
311
312
  assert_equal(JID.new('contact@example.org'), pres.to)
313
+ Thread.pass
312
314
  }
313
315
  h.add('contact@example.org', 'MyContact', true)
314
316
  wait_state
315
- query_waiter.lock
317
+ query_waiter.wait
316
318
  wait_state
317
319
  end
318
320
 
@@ -323,25 +325,33 @@ class Roster::HelperTest < Test::Unit::TestCase
323
325
  </iq>")
324
326
  }
325
327
 
326
- query_waiter = Mutex.new
327
- query_waiter.lock
328
+ query_waiter = Semaphore.new
328
329
  h = Roster::Helper::new(@client)
329
- h.add_query_callback { |iq| query_waiter.unlock }
330
+ h.add_query_callback { |iq| query_waiter.run }
330
331
  wait_state
331
- query_waiter.lock
332
+ query_waiter.wait
333
+
334
+ state { |pres|
335
+ assert_kind_of(Presence, pres)
336
+ assert_equal(:subscribed, pres.type)
337
+ }
338
+ state { |iq|
339
+ assert_kind_of(Iq, iq)
340
+ assert_equal(:set, iq.type)
341
+ send("<iq type='result' id='#{iq.id}'/>")
342
+ }
332
343
 
333
- cb_lock = Mutex.new
334
- cb_lock.lock
344
+ cb_lock = Semaphore.new
335
345
  h.add_subscription_request_callback { |item,pres|
336
346
  assert_nil(item)
337
347
  assert_kind_of(Presence, pres)
338
348
  h.accept_subscription(pres.from)
339
-
340
- cb_lock.unlock
349
+ cb_lock.run
341
350
  }
342
-
343
351
  send("<presence type='subscribe' from='contact@example.org' to='user@example.com'/>")
344
- cb_lock.lock
352
+ skip_state
353
+ wait_state
354
+ cb_lock.wait
345
355
 
346
356
  state { |pres|
347
357
  assert_kind_of(Presence, pres)
@@ -358,32 +368,148 @@ class Roster::HelperTest < Test::Unit::TestCase
358
368
  </iq>")
359
369
  }
360
370
 
361
- query_waiter = Mutex.new
362
- query_waiter.lock
371
+ query_waiter = Semaphore.new
363
372
  h = Roster::Helper::new(@client)
364
- h.add_query_callback { |iq| query_waiter.unlock }
373
+ h.add_query_callback { |iq| query_waiter.run }
365
374
  wait_state
366
- query_waiter.lock
375
+ query_waiter.wait
367
376
 
368
- cb_lock = Mutex.new
369
- cb_lock.lock
377
+ state { |pres|
378
+ assert_kind_of(Presence, pres)
379
+ assert_equal(:unsubscribed, pres.type)
380
+ assert_equal(JID.new('contact@example.org'), pres.to)
381
+ }
382
+ cb_lock = Semaphore.new
370
383
  h.add_subscription_request_callback { |item,pres|
371
384
  assert_nil(item)
372
385
  assert_kind_of(Presence, pres)
373
386
  h.decline_subscription(pres.from)
374
387
 
375
- cb_lock.unlock
388
+ cb_lock.run
376
389
  }
377
390
 
378
391
  send("<presence type='subscribe' from='contact@example.org' to='user@example.com'/>")
379
- cb_lock.lock
392
+ wait_state
393
+ cb_lock.wait
394
+ end
380
395
 
381
- state { |pres|
382
- assert_kind_of(Presence, pres)
383
- assert_equal(:unsubscribed, pres.type)
384
- assert_equal(JID.new('contact@example.org'), pres.to)
396
+ def test_groupset
397
+ state { |iq|
398
+ send("<iq type='result'>
399
+ <query xmlns='jabber:iq:roster'>
400
+ <item jid='test@test' subscription='both'>
401
+ <group>One</group>
402
+ <group>Two</group>
403
+ </item>
404
+ </query>
405
+ </iq>")
406
+ }
407
+
408
+ query_waiter = Semaphore.new
409
+ h = Roster::Helper.new(@client)
410
+ h.add_query_callback { query_waiter.run }
411
+ wait_state
412
+ query_waiter.wait
413
+
414
+ assert_equal(1, h.items.size)
415
+ assert_equal(%w(One Two).sort, h['test@test'].groups.sort)
416
+
417
+ state { |iq|
418
+ send("<iq type='result' id='#{iq.id}'>#{iq.query}</iq>")
419
+ }
420
+ h['test@test'].groups = %w(One Two Three)
421
+ h['test@test'].send
422
+ wait_state
423
+ query_waiter.wait
424
+ assert_equal(%w(One Two Three).sort, h['test@test'].groups.sort)
425
+ end
426
+
427
+ def test_nameset
428
+ state { |iq|
429
+ send("<iq type='result'>
430
+ <query xmlns='jabber:iq:roster'>
431
+ <item jid='test@test' subscription='both'/>
432
+ </query>
433
+ </iq>")
434
+ }
435
+
436
+ query_waiter = Semaphore.new
437
+ h = Roster::Helper.new(@client)
438
+ h.add_query_callback { query_waiter.run }
439
+ wait_state
440
+ query_waiter.wait
441
+
442
+ assert_equal(1, h.items.size)
443
+ assert_nil(h['test@test'].iname)
444
+
445
+ state { |iq|
446
+ send("<iq type='result' id='#{iq.id}'>#{iq.query}</iq>")
385
447
  }
448
+ h['test@test'].iname = 'Unknown'
449
+ h['test@test'].send
386
450
  wait_state
451
+ query_waiter.wait
452
+ assert_equal('Unknown', h['test@test'].iname)
453
+
454
+ state { |iq|
455
+ send("<iq type='result' id='#{iq.id}'>#{iq.query}</iq>")
456
+ }
457
+ h['test@test'].iname = 'Known'
458
+ h['test@test'].send
459
+ wait_state
460
+ query_waiter.wait
461
+ assert_equal('Known', h['test@test'].iname)
462
+
463
+ state { |iq|
464
+ send("<iq type='result' id='#{iq.id}'>#{iq.query}</iq>")
465
+ }
466
+ h['test@test'].iname = nil
467
+ h['test@test'].send
468
+ wait_state
469
+ query_waiter.wait
470
+ assert_nil(h['test@test'].iname)
471
+ end
472
+
473
+ def test_update_callback
474
+ update_args = nil
475
+ update_waiter = Semaphore.new
476
+
477
+ h = Roster::Helper.new(@client)
478
+ h.add_update_callback { |*a|
479
+ update_args = a
480
+ update_waiter.run
481
+ }
482
+
483
+ send("<iq type='set'>
484
+ <query xmlns='jabber:iq:roster'>
485
+ <item jid='foo@bar' name='Foo'/>
486
+ </query>
487
+ </iq>")
488
+ update_waiter.wait
489
+ assert_nil(update_args[0])
490
+ assert_equal(JID.new('foo@bar'), update_args[1].jid)
491
+ assert_equal('Foo', update_args[1].iname)
492
+
493
+ send("<iq type='set'>
494
+ <query xmlns='jabber:iq:roster'>
495
+ <item jid='foo@bar'/>
496
+ </query>
497
+ </iq>")
498
+ update_waiter.wait
499
+ assert_equal(JID.new('foo@bar'), update_args[0].jid)
500
+ assert_equal('Foo', update_args[0].iname)
501
+ assert_equal(JID.new('foo@bar'), update_args[1].jid)
502
+ assert_nil(update_args[1].iname)
503
+
504
+ send("<iq type='set'>
505
+ <query xmlns='jabber:iq:roster'>
506
+ <item jid='foo@bar' subscription='remove'/>
507
+ </query>
508
+ </iq>")
509
+ update_waiter.wait
510
+ assert_equal(JID.new('foo@bar'), update_args[0].jid)
511
+ assert_nil(update_args[0].iname)
512
+ assert_nil(update_args[1])
387
513
  end
388
514
  end
389
515