sprsquish-blather 0.3.4 → 0.4.0

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 (110) hide show
  1. data/LICENSE +1 -1
  2. data/README.rdoc +41 -12
  3. data/examples/echo.rb +1 -1
  4. data/examples/execute.rb +0 -5
  5. data/examples/pubsub/cli.rb +64 -0
  6. data/examples/pubsub/ping_pong.rb +18 -0
  7. data/examples/rosterprint.rb +14 -0
  8. data/examples/xmpp4r/echo.rb +35 -0
  9. data/lib/blather/client/client.rb +19 -13
  10. data/lib/blather/client/dsl/pubsub.rb +133 -0
  11. data/lib/blather/client/dsl.rb +16 -0
  12. data/lib/blather/client.rb +1 -1
  13. data/lib/blather/core_ext/active_support/inheritable_attributes.rb +117 -0
  14. data/lib/blather/core_ext/active_support.rb +1 -117
  15. data/lib/blather/core_ext/nokogiri.rb +35 -0
  16. data/lib/blather/errors/sasl_error.rb +3 -1
  17. data/lib/blather/errors/stanza_error.rb +10 -17
  18. data/lib/blather/errors/stream_error.rb +11 -14
  19. data/lib/blather/errors.rb +3 -20
  20. data/lib/blather/jid.rb +1 -0
  21. data/lib/blather/roster.rb +9 -0
  22. data/lib/blather/roster_item.rb +6 -1
  23. data/lib/blather/stanza/disco/disco_info.rb +45 -33
  24. data/lib/blather/stanza/disco/disco_items.rb +32 -21
  25. data/lib/blather/stanza/disco.rb +7 -1
  26. data/lib/blather/stanza/iq/query.rb +16 -8
  27. data/lib/blather/stanza/iq/roster.rb +33 -22
  28. data/lib/blather/stanza/iq.rb +13 -8
  29. data/lib/blather/stanza/message.rb +20 -31
  30. data/lib/blather/stanza/presence/status.rb +13 -21
  31. data/lib/blather/stanza/presence/subscription.rb +11 -16
  32. data/lib/blather/stanza/presence.rb +3 -5
  33. data/lib/blather/stanza/pubsub/affiliations.rb +50 -0
  34. data/lib/blather/stanza/pubsub/create.rb +43 -0
  35. data/lib/blather/stanza/pubsub/errors.rb +9 -0
  36. data/lib/blather/stanza/pubsub/event.rb +77 -0
  37. data/lib/blather/stanza/pubsub/items.rb +63 -0
  38. data/lib/blather/stanza/pubsub/publish.rb +58 -0
  39. data/lib/blather/stanza/pubsub/retract.rb +53 -0
  40. data/lib/blather/stanza/pubsub/subscribe.rb +42 -0
  41. data/lib/blather/stanza/pubsub/subscription.rb +66 -0
  42. data/lib/blather/stanza/pubsub/subscriptions.rb +55 -0
  43. data/lib/blather/stanza/pubsub/unsubscribe.rb +42 -0
  44. data/lib/blather/stanza/pubsub.rb +63 -0
  45. data/lib/blather/stanza/pubsub_owner/delete.rb +34 -0
  46. data/lib/blather/stanza/pubsub_owner/purge.rb +34 -0
  47. data/lib/blather/stanza/pubsub_owner.rb +41 -0
  48. data/lib/blather/stanza.rb +35 -18
  49. data/lib/blather/stream/client.rb +1 -2
  50. data/lib/blather/stream/component.rb +9 -5
  51. data/lib/blather/stream/features/resource.rb +63 -0
  52. data/lib/blather/stream/{sasl.rb → features/sasl.rb} +53 -52
  53. data/lib/blather/stream/features/session.rb +44 -0
  54. data/lib/blather/stream/features/tls.rb +28 -0
  55. data/lib/blather/stream/features.rb +53 -0
  56. data/lib/blather/stream/parser.rb +70 -46
  57. data/lib/blather/stream.rb +76 -168
  58. data/lib/blather/xmpp_node.rb +113 -52
  59. data/lib/blather.rb +35 -12
  60. data/spec/blather/client/client_spec.rb +44 -58
  61. data/spec/blather/client/dsl/pubsub_spec.rb +465 -0
  62. data/spec/blather/client/dsl_spec.rb +19 -6
  63. data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
  64. data/spec/blather/errors/sasl_error_spec.rb +8 -8
  65. data/spec/blather/errors/stanza_error_spec.rb +25 -33
  66. data/spec/blather/errors/stream_error_spec.rb +21 -16
  67. data/spec/blather/errors_spec.rb +4 -11
  68. data/spec/blather/jid_spec.rb +31 -30
  69. data/spec/blather/roster_item_spec.rb +34 -23
  70. data/spec/blather/roster_spec.rb +27 -12
  71. data/spec/blather/stanza/discos/disco_info_spec.rb +61 -42
  72. data/spec/blather/stanza/discos/disco_items_spec.rb +47 -35
  73. data/spec/blather/stanza/iq/query_spec.rb +34 -11
  74. data/spec/blather/stanza/iq/roster_spec.rb +47 -30
  75. data/spec/blather/stanza/iq_spec.rb +19 -14
  76. data/spec/blather/stanza/message_spec.rb +30 -17
  77. data/spec/blather/stanza/presence/status_spec.rb +43 -20
  78. data/spec/blather/stanza/presence/subscription_spec.rb +41 -21
  79. data/spec/blather/stanza/presence_spec.rb +34 -21
  80. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  81. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  82. data/spec/blather/stanza/pubsub/event_spec.rb +84 -0
  83. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  84. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  85. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  86. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  87. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  88. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  89. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +61 -0
  90. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  91. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  92. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  93. data/spec/blather/stanza/pubsub_spec.rb +62 -0
  94. data/spec/blather/stanza_spec.rb +53 -38
  95. data/spec/blather/stream/client_spec.rb +231 -88
  96. data/spec/blather/stream/component_spec.rb +14 -5
  97. data/spec/blather/stream/parser_spec.rb +145 -0
  98. data/spec/blather/xmpp_node_spec.rb +192 -96
  99. data/spec/fixtures/pubsub.rb +311 -0
  100. data/spec/spec_helper.rb +5 -4
  101. metadata +53 -17
  102. data/Rakefile +0 -139
  103. data/ext/extconf.rb +0 -65
  104. data/ext/push_parser.c +0 -209
  105. data/lib/blather/core_ext/libxml.rb +0 -28
  106. data/lib/blather/stream/resource.rb +0 -48
  107. data/lib/blather/stream/session.rb +0 -36
  108. data/lib/blather/stream/stream_handler.rb +0 -39
  109. data/lib/blather/stream/tls.rb +0 -33
  110. data/spec/blather/core_ext/libxml_spec.rb +0 -58
@@ -1,6 +1,7 @@
1
+ require 'resolv'
1
2
  require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
2
3
 
3
- describe 'Blather::Stream::Client' do
4
+ describe Blather::Stream::Client do
4
5
  class MockServer; end
5
6
  module ServerMock
6
7
  def receive_data(data)
@@ -12,44 +13,102 @@ describe 'Blather::Stream::Client' do
12
13
  def mocked_server(times = nil, &block)
13
14
  @client ||= mock()
14
15
  @client.stubs(:unbind) unless @client.respond_to?(:unbind)
16
+ @client.stubs(:post_init) unless @client.respond_to?(:post_init)
15
17
  @client.stubs(:jid=) unless @client.respond_to?(:jid=)
16
18
 
17
19
  MockServer.any_instance.expects(:receive_data).send(*(times ? [:times, times] : [:at_least, 1])).with &block
18
20
  EventMachine::run {
21
+ EM.add_timer(0.5) { EM.stop if EM.reactor_running? }
22
+
19
23
  # Mocked server
20
24
  EventMachine::start_server '127.0.0.1', 12345, ServerMock
21
25
 
22
- # Stream connection
23
- EM.connect('127.0.0.1', 12345, Stream::Client, @client, @jid || JID.new('n@d/r'), 'pass') { |c| @stream = c }
26
+ # Blather::Stream connection
27
+ EM.connect('127.0.0.1', 12345, Blather::Stream::Client, @client, @jid || Blather::JID.new('n@d/r'), 'pass') { |c| @stream = c }
24
28
  }
25
29
  end
26
30
 
31
+
27
32
  it 'can be started' do
28
33
  client = mock()
29
34
  params = [client, 'n@d/r', 'pass', 'host', 1234]
30
35
  EM.expects(:connect).with do |*parms|
31
- parms[0] == 'host' &&
32
- parms[1] == 1234 &&
33
- parms[3] == client &&
34
- parms[5] == 'pass' &&
35
- parms[4] == JID.new('n@d/r')
36
+ parms[0].must_equal 'host'
37
+ parms[1].must_equal 1234
38
+ parms[3].must_equal client
39
+ parms[5].must_equal 'pass'
40
+ parms[4].must_equal Blather::JID.new('n@d/r')
41
+ end
42
+
43
+ Blather::Stream::Client.start *params
44
+ end
45
+
46
+ it 'attempts to find the SRV record if a host is not provided' do
47
+ dns = mock(:sort! => nil, :empty? => false)
48
+ dns.expects(:each).yields(mock({
49
+ :target => 'd',
50
+ :port => 5222
51
+ }))
52
+ Resolv::DNS.expects(:open).yields(mock(:getresources => dns))
53
+
54
+ client = Class.new
55
+ EM.expects(:connect).with do |*parms|
56
+ parms[0].must_equal 'd'
57
+ parms[1].must_equal 5222
58
+ parms[3].must_equal client
59
+ parms[5].must_equal 'pass'
60
+ parms[4].must_equal Blather::JID.new('n@d/r')
36
61
  end
37
62
 
38
- Stream::Client.start *(params)
63
+ Blather::Stream::Client.start client, 'n@d/r', 'pass'
64
+ end
65
+
66
+ it 'will attempt as many connections as it takes' do
67
+ dns = [mock(:target => 'd', :port => 5222), mock(:target => 'g', :port => 1234)]
68
+ dns.stubs(:sort!) #ignore sorting
69
+ Resolv::DNS.expects(:open).yields(mock(:getresources => dns))
70
+
71
+ client = Class.new
72
+ EM.expects(:connect).with do |*parms|
73
+ raise Blather::Stream::NoConnection if parms[0] == 'd'
74
+ parms[0].must_equal 'g'
75
+ parms[1].must_equal 1234
76
+ parms[3].must_equal client
77
+ parms[5].must_equal 'pass'
78
+ parms[4].must_equal Blather::JID.new('n@d/r')
79
+ end
80
+ Blather::Stream::Client.start client, 'n@d/r', 'pass'
81
+ end
82
+
83
+ it 'will not attempt to connect more often than necessary' do
84
+ dns = [mock(:target => 'd', :port => 5222), mock()]
85
+ dns.stubs(:sort!) #ignore sorting
86
+ Resolv::DNS.expects(:open).yields(mock(:getresources => dns))
87
+
88
+ client = Class.new
89
+ EM.expects(:connect).with do |*parms|
90
+ parms[0].must_equal 'd'
91
+ parms[1].must_equal 5222
92
+ parms[3].must_equal client
93
+ parms[5].must_equal 'pass'
94
+ parms[4].must_equal Blather::JID.new('n@d/r')
95
+ end
96
+ Blather::Stream::Client.start client, 'n@d/r', 'pass'
39
97
  end
40
98
 
41
99
  it 'can figure out the host to use based on the jid' do
42
- client = mock()
43
- params = [client, 'n@d/r', 'pass', 'd', 5222]
100
+ Resolv::DNS.expects(:open).yields(mock(:getresources => mock(:empty? => true)))
101
+ client = Class.new
102
+ params = [client, 'n@d/r', 'pass', nil, 5222]
44
103
  EM.expects(:connect).with do |*parms|
45
- parms[0] == 'd' &&
46
- parms[1] == 5222 &&
47
- parms[3] == client &&
48
- parms[5] == 'pass' &&
49
- parms[4] == JID.new('n@d/r')
104
+ parms[0].must_equal 'd'
105
+ parms[1].must_equal 5222
106
+ parms[3].must_equal client
107
+ parms[5].must_equal 'pass'
108
+ parms[4].must_equal Blather::JID.new('n@d/r')
50
109
  end
51
110
 
52
- Stream::Client.start client, 'n@d/r', 'pass'
111
+ Blather::Stream::Client.start client, 'n@d/r', 'pass'
53
112
  end
54
113
 
55
114
  it 'starts the stream once the connection is complete' do
@@ -60,7 +119,7 @@ describe 'Blather::Stream::Client' do
60
119
  @client = mock()
61
120
  @client.expects(:receive_data).with do |n|
62
121
  EM.stop
63
- n.kind_of?(Stanza::Message) && @stream.ready?.must_equal(true)
122
+ n.must_be_kind_of Blather::Stanza::Message
64
123
  end
65
124
 
66
125
  mocked_server(1) do |val, server|
@@ -70,7 +129,7 @@ describe 'Blather::Stream::Client' do
70
129
  end
71
130
  end
72
131
 
73
- it 'puts itself in the stopped state and calls @client.stopped when stopped' do
132
+ it 'puts itself in the stopped state and calls @client.unbind when unbound' do
74
133
  @client = mock()
75
134
  @client.expects(:unbind).at_least_once
76
135
 
@@ -95,7 +154,6 @@ describe 'Blather::Stream::Client' do
95
154
  it 'will be in the negotiating state during feature negotiations' do
96
155
  state = nil
97
156
  @client = mock()
98
- @client.stubs(:post_init)
99
157
  @client.expects(:receive_data).with do |n|
100
158
  EM.stop
101
159
  state.must_equal(:negotiated) && @stream.negotiating?.must_equal(false)
@@ -111,7 +169,7 @@ describe 'Blather::Stream::Client' do
111
169
 
112
170
  when :started
113
171
  state = :negotiated
114
- @stream.negotiating?.must_equal(true)
172
+ @stream.negotiating?.must_equal true
115
173
  server.send_data "<iq from='d' type='result' id='#{val[/id="([^"]+)"/,1]}' />"
116
174
  server.send_data "<message to='a@b/c' from='d@e/f' type='chat' xml:lang='en'><body>Message!</body></message>"
117
175
  true
@@ -186,13 +244,36 @@ describe 'Blather::Stream::Client' do
186
244
  end
187
245
  end
188
246
 
247
+ it 'skips features it is unable to handle' do
248
+ state = nil
249
+ mocked_server() do |val, server|
250
+ case state
251
+ when nil
252
+ state = :started
253
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
254
+ server.send_data "<stream:features><auth xmlns='http://jabber.org/features/iq-auth'/><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' /></stream:features>"
255
+ val.must_match(/stream:stream/)
256
+
257
+ when :started
258
+ EM.stop
259
+ val.must_match(/starttls/)
260
+
261
+ else
262
+ EM.stop
263
+ false
264
+
265
+ end
266
+ end
267
+ end
268
+
189
269
  it 'starts TLS when asked' do
190
270
  state = nil
191
271
  mocked_server(3) do |val, server|
192
272
  case state
193
273
  when nil
194
274
  state = :started
195
- server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' /></stream:features>"
275
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
276
+ server.send_data "<stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' /></stream:features>"
196
277
  val.must_match(/stream:stream/)
197
278
 
198
279
  when :started
@@ -216,7 +297,7 @@ describe 'Blather::Stream::Client' do
216
297
  it 'will fail if TLS negotiation fails' do
217
298
  state = nil
218
299
  @client = mock()
219
- @client.expects(:receive_data).with { |v| v.must_be_kind_of TLSFailure }
300
+ @client.expects(:receive_data).with { |v| v.must_be_kind_of Blather::Stream::TLS::TLSFailure }
220
301
  mocked_server(3) do |val, server|
221
302
  case state
222
303
  when nil
@@ -246,14 +327,14 @@ describe 'Blather::Stream::Client' do
246
327
  state = nil
247
328
  @client = mock()
248
329
  @client.expects(:receive_data).with do |v|
249
- v.must_be_kind_of UnknownResponse
250
- v.node.element_name.must_equal 'foo-bar'
330
+ v.must_be_kind_of Blather::Stream::TLS::TLSFailure
251
331
  end
252
332
  mocked_server(3) do |val, server|
253
333
  case state
254
334
  when nil
255
335
  state = :started
256
- server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' /></stream:features>"
336
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
337
+ server.send_data "<stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls' /></stream:features>"
257
338
  val.must_match(/stream:stream/)
258
339
 
259
340
  when :started
@@ -368,9 +449,9 @@ describe 'Blather::Stream::Client' do
368
449
  end
369
450
  end
370
451
 
371
- it 'connects via ANONYMOUS if the JID has a blank node' do
452
+ it 'connects via ANONYMOUS if the Blather::JID has a blank node' do
372
453
  state = nil
373
- @jid = JID.new '@d'
454
+ @jid = Blather::JID.new '@d'
374
455
 
375
456
  mocked_server(3) do |val, server|
376
457
  case state
@@ -397,11 +478,37 @@ describe 'Blather::Stream::Client' do
397
478
  end
398
479
  end
399
480
 
481
+ it 'fails if asked to connect via ANONYMOUS but the server does not support it' do
482
+ state = nil
483
+ @jid = Blather::JID.new '@d'
484
+ @client = mock()
485
+ @client.expects(:receive_data).with { |s| s.must_be_instance_of Blather::BlatherError }
486
+
487
+ mocked_server(2) do |val, server|
488
+ case state
489
+ when nil
490
+ state = :started
491
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
492
+ server.send_data "<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism></mechanisms></stream:features>"
493
+ val.must_match(/stream:stream/)
494
+
495
+ when :started
496
+ EM.stop
497
+ val.must_match(/stream:stream/)
498
+
499
+ else
500
+ EM.stop
501
+ false
502
+
503
+ end
504
+ end
505
+ end
506
+
400
507
  it 'tries each possible mechanism until it fails completely' do
401
508
  state = nil
402
509
  @client = mock()
403
510
  @client.expects(:receive_data).with do |n|
404
- n.must_be_kind_of(SASLError)
511
+ n.must_be_kind_of(Blather::SASLError)
405
512
  n.name.must_equal :not_authorized
406
513
  end
407
514
 
@@ -409,7 +516,8 @@ describe 'Blather::Stream::Client' do
409
516
  case state
410
517
  when nil
411
518
  state = :started
412
- server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism></mechanisms></stream:features>"
519
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
520
+ server.send_data "<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism></mechanisms></stream:features>"
413
521
  val.must_match(/stream:stream/)
414
522
 
415
523
  when :started
@@ -471,9 +579,37 @@ describe 'Blather::Stream::Client' do
471
579
  end
472
580
  end
473
581
 
582
+ it 'will ignore methods it does not understand' do
583
+ state = nil
584
+ mocked_server(3) do |val, server|
585
+ case state
586
+ when nil
587
+ state = :started
588
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
589
+ server.send_data "<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>CRAM-MD5</mechanism><mechanism>PLAIN</mechanism></mechanisms></stream:features>"
590
+ val.must_match(/stream:stream/)
591
+
592
+ when :started
593
+ state = :auth_sent
594
+ server.send_data "<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl' />"
595
+ val.must_equal('<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">bkBkAG4AcGFzcw==</auth>')
596
+
597
+ when :auth_sent
598
+ EM.stop
599
+ state = :complete
600
+ val.must_match(/stream:stream/)
601
+
602
+ else
603
+ EM.stop
604
+ false
605
+
606
+ end
607
+ end
608
+ end
609
+ =begin
474
610
  it 'sends client an error when an unknown mechanism is sent' do
475
611
  @client = mock()
476
- @client.expects(:receive_data).with { |v| v.must_be_kind_of(Stream::SASL::UnknownMechanism) }
612
+ @client.expects(:receive_data).with { |v| v.must_be_kind_of(Blather::Stream::SASL::UnknownMechanism) }
477
613
  started = false
478
614
  mocked_server(2) do |val, server|
479
615
  if !started
@@ -489,7 +625,7 @@ describe 'Blather::Stream::Client' do
489
625
  end
490
626
  end
491
627
  end
492
-
628
+ =end
493
629
  %w[ aborted
494
630
  incorrect-encoding
495
631
  invalid-authzid
@@ -533,7 +669,7 @@ describe 'Blather::Stream::Client' do
533
669
  it 'fails when an unkown node comes through during SASL negotiation' do
534
670
  @client = mock()
535
671
  @client.expects(:receive_data).with do |n|
536
- n.must_be_instance_of UnknownResponse
672
+ n.must_be_instance_of Blather::UnknownResponse
537
673
  n.node.element_name.must_equal 'foo-bar'
538
674
  end
539
675
  state = nil
@@ -566,13 +702,14 @@ describe 'Blather::Stream::Client' do
566
702
  state = nil
567
703
  class Client; attr_accessor :jid; end
568
704
  @client = Client.new
569
- @jid = JID.new('n@d')
705
+ @jid = Blather::JID.new('n@d')
570
706
 
571
707
  mocked_server(3) do |val, server|
572
708
  case state
573
709
  when nil
574
710
  state = :started
575
- server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
711
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
712
+ server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
576
713
  val.must_match(/stream:stream/)
577
714
 
578
715
  when :started
@@ -584,7 +721,7 @@ describe 'Blather::Stream::Client' do
584
721
 
585
722
  when :complete
586
723
  EM.stop
587
- @client.jid.must_equal JID.new('n@d/server_resource')
724
+ @client.jid.must_equal Blather::JID.new('n@d/server_resource')
588
725
 
589
726
  else
590
727
  EM.stop
@@ -598,7 +735,7 @@ describe 'Blather::Stream::Client' do
598
735
  state = nil
599
736
  class Client; attr_accessor :jid; end
600
737
  @client = Client.new
601
- @jid = JID.new('n@d/r')
738
+ @jid = Blather::JID.new('n@d/r')
602
739
 
603
740
  mocked_server(3) do |val, server|
604
741
  case state
@@ -609,14 +746,47 @@ describe 'Blather::Stream::Client' do
609
746
 
610
747
  when :started
611
748
  state = :complete
612
- val =~ %r{<iq[^>]+id="([^"]+)"}
613
- server.send_data "<iq type='result' id='#{$1}'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>#{@jid}</jid></bind></iq>"
749
+ doc = parse_stanza val
750
+ doc.xpath('/iq/bind_ns:bind/bind_ns:resource[.="r"]', :bind_ns => Blather::Stream::Resource::BIND_NS).wont_be_empty
751
+
752
+ server.send_data "<iq type='result' id='#{doc.find_first('iq')['id']}'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>#{@jid}</jid></bind></iq>"
614
753
  server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
615
- val.must_match(%r{<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><resource>r</resource></bind>})
616
754
 
617
755
  when :complete
618
756
  EM.stop
619
- @client.jid.must_equal JID.new('n@d/r')
757
+ @client.jid.must_equal Blather::JID.new('n@d/r')
758
+
759
+ else
760
+ EM.stop
761
+ false
762
+
763
+ end
764
+ end
765
+ end
766
+
767
+ it 'will error out if the bind ID mismatches' do
768
+ state = nil
769
+ @jid = Blather::JID.new('n@d')
770
+ @client = mock()
771
+
772
+ mocked_server(3) do |val, server|
773
+ case state
774
+ when nil
775
+ state = :started
776
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
777
+ server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
778
+ val.must_match(/stream:stream/)
779
+
780
+ when :started
781
+ state = :complete
782
+ val =~ %r{<iq[^>]+id="([^"]+)"}
783
+ @client.expects(:receive_data).with("BIND result ID mismatch. Expected: #{$1}. Received: #{$1}-bad")
784
+ server.send_data "<iq type='result' id='#{$1}-bad'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>#{@jid}/server_resource</jid></bind></iq>"
785
+ val.must_match(%r{<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"\s?/>})
786
+
787
+ when :complete
788
+ EM.stop
789
+ true
620
790
 
621
791
  else
622
792
  EM.stop
@@ -641,9 +811,9 @@ describe 'Blather::Stream::Client' do
641
811
 
642
812
  when :started
643
813
  state = :complete
644
- val =~ %r{<iq[^>]+id="([^"]+)"}
645
- server.send_data "<iq type='error' id='#{$1}'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>r</resource></bind><error type='modify'><bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error></iq>"
646
- val.must_match(%r{<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><resource>r</resource></bind>})
814
+ doc = parse_stanza val
815
+ doc.xpath('/iq/bind_ns:bind/bind_ns:resource[.="r"]', :bind_ns => Blather::Stream::Resource::BIND_NS).wont_be_empty
816
+ server.send_data "<iq type='error' id='#{doc.find_first('iq')['id']}'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>r</resource></bind><error type='modify'><bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error></iq>"
647
817
 
648
818
  when :complete
649
819
  EM.stop
@@ -661,21 +831,22 @@ describe 'Blather::Stream::Client' do
661
831
  state = nil
662
832
  @client = mock()
663
833
  @client.expects(:receive_data).with do |n|
664
- n.must_be_instance_of UnknownResponse
834
+ n.must_be_instance_of Blather::UnknownResponse
665
835
  n.node.element_name.must_equal 'foo-bar'
666
836
  end
667
837
  mocked_server(3) do |val, server|
668
838
  case state
669
839
  when nil
670
840
  state = :started
671
- server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'><stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
841
+ server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
842
+ server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
672
843
  val.must_match(/stream:stream/)
673
844
 
674
845
  when :started
675
846
  state = :complete
676
- val =~ %r{<iq[^>]+id="([^"]+)"}
847
+ doc = parse_stanza val
848
+ doc.xpath('/iq/bind_ns:bind/bind_ns:resource[.="r"]', :bind_ns => Blather::Stream::Resource::BIND_NS).wont_be_empty
677
849
  server.send_data "<foo-bar />"
678
- val.must_match(%r{<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><resource>r</resource></bind>})
679
850
 
680
851
  when :complete
681
852
  EM.stop
@@ -704,9 +875,10 @@ describe 'Blather::Stream::Client' do
704
875
 
705
876
  when :started
706
877
  state = :completed
707
- server.send_data "<iq from='d' type='result' id='#{val[/id="([^"]+)"/,1]}' />"
878
+ doc = parse_stanza val
879
+ doc.find('/iq[@type="set" and @to="d"]/sess_ns:session', :sess_ns => Blather::Stream::Session::SESSION_NS).wont_be_empty
880
+ server.send_data "<iq from='d' type='result' id='#{doc.find_first('iq')['id']}' />"
708
881
  server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
709
- val.must_match(%r{<iq id="[^"]+" type="set" to="d"><session xmlns="urn:ietf:params:xml:ns:xmpp-session"\s?/></iq>})
710
882
 
711
883
  when :completed
712
884
  EM.stop
@@ -736,8 +908,9 @@ describe 'Blather::Stream::Client' do
736
908
 
737
909
  when :started
738
910
  state = :completed
739
- server.send_data "<iq from='d' type='error' id='#{val[/id="([^"]+)"/,1]}'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/><error type='wait'><internal-server-error xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error></iq>"
740
- val.must_match(%r{<iq id="[^"]+" type="set" to="d"><session xmlns="urn:ietf:params:xml:ns:xmpp-session"\s?/></iq>})
911
+ doc = parse_stanza val
912
+ doc.find('/iq[@type="set" and @to="d"]/sess_ns:session', :sess_ns => Blather::Stream::Session::SESSION_NS).wont_be_empty
913
+ server.send_data "<iq from='d' type='error' id='#{doc.find_first('iq')['id']}'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/><error type='wait'><internal-server-error xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error></iq>"
741
914
 
742
915
  when :completed
743
916
  EM.stop
@@ -755,7 +928,7 @@ describe 'Blather::Stream::Client' do
755
928
  state = nil
756
929
  @client = mock()
757
930
  @client.expects(:receive_data).with do |n|
758
- n.must_be_instance_of UnknownResponse
931
+ n.must_be_instance_of Blather::UnknownResponse
759
932
  n.node.element_name.must_equal 'foo-bar'
760
933
  end
761
934
  mocked_server(3) do |val, server|
@@ -768,8 +941,9 @@ describe 'Blather::Stream::Client' do
768
941
 
769
942
  when :started
770
943
  state = :completed
944
+ doc = parse_stanza val
945
+ doc.find('/iq[@type="set" and @to="d"]/sess_ns:session', :sess_ns => Blather::Stream::Session::SESSION_NS).wont_be_empty
771
946
  server.send_data '<foo-bar />'
772
- val.must_match(%r{<iq id="[^"]+" type="set" to="d"><session xmlns="urn:ietf:params:xml:ns:xmpp-session"\s?/></iq>})
773
947
 
774
948
  when :completed
775
949
  EM.stop
@@ -783,42 +957,10 @@ describe 'Blather::Stream::Client' do
783
957
  end
784
958
  end
785
959
 
786
- it 'sends the client a warning on parse warning' do
787
- @client = mock()
788
- @client.expects(:receive_data).with do |v|
789
- EM.stop
790
- v.must_be_kind_of ParseWarning
791
- v.message.must_match(/vcard\-temp/)
792
- end
793
- state = nil
794
- mocked_server(2) do |val, server|
795
- case state
796
- when nil
797
- state = :started
798
- server.send_data "<?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>"
799
- server.send_data "<stream:features><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind' /></stream:features>"
800
- val.must_match(/stream:stream/)
801
-
802
- when :started
803
- server.send_data <<-XML
804
- <iq xmlns="jabber:client" to="utterance.localhost" type="get" id="2590">
805
- <vCard xmlns="vcard-temp" />
806
- </iq>
807
- XML
808
- true
809
-
810
- else
811
- EM.stop
812
- false
813
-
814
- end
815
- end
816
- end
817
-
818
- it 'sends client an error on parse error' do
960
+ it 'sends client an error and reply to the server on parse error' do
819
961
  @client = mock()
820
962
  @client.expects(:receive_data).with do |v|
821
- v.must_be_kind_of ParseError
963
+ v.must_be_kind_of Blather::ParseError
822
964
  v.message.must_match(/generate\-parse\-error/)
823
965
  end
824
966
  state = nil
@@ -845,4 +987,5 @@ describe 'Blather::Stream::Client' do
845
987
  end
846
988
  end
847
989
  end
990
+
848
991
  end
@@ -1,6 +1,6 @@
1
1
  require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
2
2
 
3
- describe 'Blather::Stream::Component' do
3
+ describe Blather::Stream::Component do
4
4
  class MockServer; end
5
5
  module ServerMock
6
6
  def receive_data(data)
@@ -19,8 +19,8 @@ describe 'Blather::Stream::Component' do
19
19
  # Mocked server
20
20
  EventMachine::start_server '127.0.0.1', 12345, ServerMock
21
21
 
22
- # Stream connection
23
- EM.connect('127.0.0.1', 12345, Stream::Component, @client, @jid || 'comp.id', 'secret') { |c| @stream = c }
22
+ # Blather::Stream connection
23
+ EM.connect('127.0.0.1', 12345, Blather::Stream::Component, @client, @jid || 'comp.id', 'secret') { |c| @stream = c }
24
24
  }
25
25
  end
26
26
 
@@ -34,7 +34,7 @@ describe 'Blather::Stream::Component' do
34
34
  parms[4] == 'comp.id'
35
35
  end
36
36
 
37
- Stream::Component.start *params
37
+ Blather::Stream::Component.start *params
38
38
  end
39
39
 
40
40
  it 'shakes hands with the server' do
@@ -63,7 +63,7 @@ describe 'Blather::Stream::Component' do
63
63
  @client = mock(:post_init)
64
64
  @client.expects(:receive_data).with do |n|
65
65
  EM.stop
66
- n.kind_of?(Stanza::Message) && @stream.ready?.must_equal(true)
66
+ n.kind_of? Blather::XMPPNode
67
67
  end
68
68
 
69
69
  state = nil
@@ -83,4 +83,13 @@ describe 'Blather::Stream::Component' do
83
83
  end
84
84
  end
85
85
 
86
+ it 'sends stanzas to the wire with ensuring from is set' do
87
+ client = mock()
88
+ client.stubs(:jid)
89
+ client.stubs(:jid=)
90
+ msg = Blather::Stanza::Message.new 'to@jid.com', 'body'
91
+ comp = Blather::Stream::Component.new nil, client, 'jid.com', 'pass'
92
+ comp.expects(:send_data).with { |s| s.must_match(/^<message[^>]*from="jid\.com"/) }
93
+ comp.send msg
94
+ end
86
95
  end