File: clienttester.rb

package info (click to toggle)
ruby-xmpp4r 0.5.6-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 1,384 kB
  • sloc: ruby: 17,382; xml: 74; sh: 12; makefile: 4
file content (149 lines) | stat: -rwxr-xr-x 3,721 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# =XMPP4R - XMPP Library for Ruby
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
# Website::http://xmpp4r.github.io

$:.unshift '../lib'
require 'xmpp4r'
require 'test/unit'
require 'socket'
require 'xmpp4r/semaphore'

# Jabber::debug = true
$ctdebug = false
# $ctdebug = true

# This is sane for tests:
Thread::abort_on_exception = true

# Turn $VERBOSE off to suppress warnings about redefinition
oldverbose = $VERBOSE
$VERBOSE = false

module Jabber
  ##
  # The ClientTester is a mix-in which provides a setup and teardown
  # method to prepare a Stream object (@client) and the method
  # interfacing as the "server side":
  # * send(xml):: Send a stanza to @client
  #
  # The server side is a stream, too: add your callbacks to @server
  #
  # ClientTester is written to test complex helper classes.
  module ClientTester
    @@SOCKET_PORT = 65223

    def setup
      servlisten = TCPServer.new(@@SOCKET_PORT)
      serverwait = Semaphore.new
      stream = '<stream:stream xmlns:stream="http://etherx.jabber.org/streams">'

      @state = 0
      @states = []

      Thread.new do
        Thread.current.abort_on_exception = true
        serversock = servlisten.accept
        servlisten.close
        serversock.sync = true
        @server = Stream.new
        @server.add_xml_callback do |xml|
          if xml.prefix == 'stream' and xml.name == 'stream'
            send(stream)
            true
          else
            false
          end
        end
        @server.start(serversock)

        serverwait.run
      end

      clientsock = TCPSocket.new('localhost', @@SOCKET_PORT)
      clientsock.sync = true
      @client = Stream.new
#=begin
      class << @client
        def jid
          begin
            #raise
          rescue
            puts $!.backtrace.join("\n")
          end
          JID.new('test@test.com/test')
        end
      end
#=end
      @client.start(clientsock)

      @processdone_wait = Semaphore.new
      @nextstate_wait = Semaphore.new
      serverwait.wait
      @server.add_stanza_callback { |stanza|
        # Client prepares everything, then calls wait_state. Problem: because
        # of a race condition, it is possible that we receive the stanza before
        # what to do with it is defined. We busy-wait on @states here.
        n = 0
        while @state >= @states.size and n < 1000
          Thread.pass
          n += 1
        end
        if n == 1000
          puts "Unmanaged stanza in state. Maybe processed by helper?" if $ctdebug
        else
          begin
            puts "Calling #{@states[@state]} for #{stanza.to_s}" if $ctdebug
            @states[@state].call(stanza)
          rescue Exception => e
            puts "Exception in state: #{e.class}: #{e}\n#{e.backtrace.join("\n")}"
          end
          @state += 1
          @nextstate_wait.wait
          @processdone_wait.run
        end

        false
      }
      @client.send(stream) { |reply| true }

    end

    def teardown
      # In some cases, we might lost count of some stanzas
      # (for example, if the handler raises an exception)
      # so we can't block forever.
      n = 0
      while @client.processing > 0 and n < 1000
        Thread::pass
        n += 1
      end
      n = 0
      while @server.processing > 0 and n < 1000
        Thread::pass
        n += 1
      end
      @client.close
      @server.close
    end

    def send(xml)
      @server.send(xml)
    end

    def state(&block)
      @states << block
    end

    def wait_state
      @nextstate_wait.run
      @processdone_wait.wait
    end

    def skip_state
      @nextstate_wait.run
    end
  end
end

# Restore the old $VERBOSE setting
$VERBOSE = oldverbose