sipatra 0.0.3 → 0.1.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.
@@ -0,0 +1,352 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class FakeApp
4
+ include Sipatra::HelperMethods
5
+
6
+ public :message # or we would NOT have access to the WRONG private method of Object
7
+ end
8
+
9
+ describe 'When', Sipatra::HelperMethods, 'is included; ', FakeApp do
10
+ def mock_address
11
+ @mock_address ||= mock('Address')
12
+ end
13
+
14
+ def mock_uri
15
+ @mock_uri ||= mock('URI')
16
+ end
17
+
18
+ def mock_proxy
19
+ @mock_proxy ||= mock('Proxy')
20
+ end
21
+
22
+ def mock_sip_factory
23
+ @sip_factory ||= mock('SipFactory')
24
+ end
25
+
26
+ def mock_response
27
+ @mock_response ||= mock('SipServletResponse')
28
+ end
29
+
30
+ subject do
31
+ FakeApp::new
32
+ end
33
+
34
+ before do
35
+ subject.stub!(:message).and_return(Object::new)
36
+ end
37
+
38
+ describe "#convert_status_code" do
39
+ it "should convert Integer to an Integer" do
40
+ subject.send(:convert_status_code, 400).should be_kind_of(Integer)
41
+ end
42
+
43
+ it "should convert a Symbol to it's numeric equivalent" do
44
+ subject.send(:convert_status_code, :not_found).should == 404
45
+ end
46
+ end
47
+
48
+ describe "#remove_header" do
49
+ it "should remove the header with the given name" do
50
+ subject.message.should_receive(:removeHeader).twice.with('toto')
51
+
52
+ subject.remove_header(:toto)
53
+ subject.remove_header('toto')
54
+ end
55
+ end
56
+
57
+ describe "#modify_header" do
58
+ # TODO: what if we have multiple headers ?
59
+ it 'should replace a header value with substitution' do
60
+ mock_headers = mock('HeadersWrapper')
61
+ subject.should_receive(:headers).twice.and_return(mock_headers)
62
+ mock_headers.should_receive(:"[]").with('X-Header').and_return(['old_value'])
63
+ mock_headers.should_receive(:"[]=").with('X-Header', ['new_value'])
64
+
65
+ subject.modify_header 'X-Header', /^old_(value)$/, 'new_\1'
66
+ end
67
+
68
+ it 'should replace multiple headers with substitution' do
69
+ mock_headers = mock('HeadersWrapper')
70
+ subject.should_receive(:headers).twice.and_return(mock_headers)
71
+ mock_headers.should_receive(:"[]").with('X-Header').and_return(['old_value', 'old_foo'])
72
+ mock_headers.should_receive(:"[]=").with('X-Header', ['new_value', 'new_foo'])
73
+
74
+ subject.modify_header 'X-Header', /^old_(.*)$/, 'new_\1'
75
+ end
76
+
77
+ it 'should replace a header value with a block result' do
78
+ mock_headers = mock('HeadersWrapper')
79
+ subject.should_receive(:headers).twice.and_return(mock_headers)
80
+ mock_headers.should_receive(:"[]").with('X-Header').and_return(['old_value', 'old_value'])
81
+ mock_headers.should_receive(:"[]=").with('X-Header', ['new_value', 'new_value'])
82
+
83
+ i = 0
84
+ subject.modify_header 'X-Header' do |value|
85
+ value.should == "old_value"
86
+ i += 1
87
+ 'new_value'
88
+ end
89
+ i.should == 2
90
+ end
91
+ end
92
+
93
+ describe "#create_address" do
94
+ before do
95
+ subject.stub!(:sip_factory => mock_sip_factory)
96
+ end
97
+
98
+ it "should create a wildcard address" do
99
+ mock_sip_factory.should_receive(:createAddress).twice.with('*').and_return(mock_address)
100
+
101
+ subject.create_address('*').should == mock_address
102
+ subject.create_address(:*).should == mock_address
103
+ end
104
+
105
+ it "should set expires on the address" do
106
+ mock_sip_factory.should_receive(:createAddress).with('test').and_return(mock_address)
107
+ mock_address.should_receive(:setExpires).with(1234)
108
+
109
+ subject.create_address('test', :expires => 1234).should == mock_address
110
+ end
111
+
112
+ it "should set displayName on the address" do
113
+ mock_sip_factory.should_receive(:createAddress).with('test').and_return(mock_address)
114
+ mock_address.should_receive(:setDisplayName).with("display name")
115
+
116
+ subject.create_address('test', :display_name => "display name").should == mock_address
117
+ end
118
+ end
119
+
120
+ describe "#create_uri" do
121
+ before do
122
+ subject.stub!(:sip_factory => mock_sip_factory)
123
+ mock_sip_factory.should_receive(:createURI).with('some_uri').and_return(mock_uri)
124
+ end
125
+
126
+ it "should createURI and set LR to true" do
127
+ mock_uri.should_receive(:setLrParam).with(true)
128
+ mock_uri.should_not_receive(:setParameter)
129
+
130
+ subject.create_uri('some_uri').should == mock_uri
131
+ end
132
+
133
+ it "should createURI and set LR to false" do
134
+ mock_uri.should_receive(:setLrParam).with(false)
135
+ mock_uri.should_not_receive(:setParameter)
136
+
137
+ subject.create_uri('some_uri', :lr => false).should == mock_uri
138
+ end
139
+
140
+ it "should createURI, set LR to false and other parameters" do
141
+ mock_uri.should_receive(:setLrParam).with(false)
142
+ mock_uri.should_receive(:setParameter).with("a_name", "a value")
143
+ mock_uri.should_receive(:setParameter).with("another_name", "another value")
144
+
145
+ subject.create_uri('some_uri',
146
+ :lr => false,
147
+ :a_name => "a value",
148
+ "another_name" => :"another value").should == mock_uri
149
+ end
150
+ end
151
+
152
+ describe "#send_response" do
153
+ it 'should raise an ArgumentError when call with an incorrect symbol' do
154
+ lambda { subject.send_response(:toto) }.should raise_exception(ArgumentError)
155
+ end
156
+
157
+ it 'should create a 404 status code when called with :not_found' do
158
+ subject.message.should_receive(:createResponse).with(404).and_return(mock_response)
159
+ mock_response.should_receive(:send)
160
+
161
+ subject.send_response(:not_found)
162
+ end
163
+
164
+ it 'should respond to send_response with Integer' do
165
+ subject.message.should_receive(:createResponse).with(500).and_return(mock_response)
166
+ mock_response.should_receive(:send)
167
+
168
+ subject.send_response(500)
169
+ end
170
+
171
+ it 'should respond to send_response with a block' do
172
+ subject.message.should_receive(:createResponse).with(500).and_return(mock_response)
173
+ mock_response.should_receive(:addHeader).with('Test1', 'Value1')
174
+ mock_response.should_receive(:send)
175
+
176
+ subject.send_response(500) do
177
+ response.addHeader('Test1', 'Value1')
178
+ end
179
+ end
180
+
181
+ it 'should respond to send_response with a Hash' do
182
+ subject.message.should_receive(:createResponse).with(500).and_return(mock_response)
183
+ mock_response.should_receive(:addHeader).with('Test1', '1234')
184
+ mock_response.should_receive(:send)
185
+
186
+ subject.send_response 500, :Test1 => 1234
187
+ end
188
+
189
+ it 'should respond to send_response with a Hash and block' do
190
+ subject.message.should_receive(:createResponse).with(500).and_return(mock_response)
191
+ mock_response.should_receive(:addHeader).with('Test1', 'Value1')
192
+ mock_response.should_receive(:addHeader).with('Test2', 'Value2')
193
+ mock_response.should_receive(:send)
194
+
195
+ subject.send_response 500, :Test1 => 'Value1' do
196
+ response.addHeader('Test2', 'Value2')
197
+ end
198
+ end
199
+
200
+ it 'should respond to send_response with a message and block' do
201
+ subject.message.should_receive(:createResponse).with(500, 'Error').and_return(mock_response)
202
+ mock_response.should_receive(:addHeader).with('Test2', 'Value2')
203
+ mock_response.should_receive(:send)
204
+
205
+ subject.send_response(500, 'Error') do
206
+ response.addHeader('Test2', 'Value2')
207
+ end
208
+ end
209
+ end
210
+
211
+ it 'should respond to header[]' do
212
+ subject.message.should_receive(:getHeader).twice.with('toto').and_return('test1')
213
+
214
+ subject.header[:toto].should == 'test1'
215
+ subject.header['toto'].should == 'test1'
216
+ end
217
+
218
+ it 'should respond to header[]=' do
219
+ subject.message.should_receive(:setHeader).twice.with('toto', 'test2')
220
+
221
+ subject.header[:toto] = 'test2'
222
+ subject.header['toto'] = 'test2'
223
+ end
224
+
225
+ it 'should respond to headers[]' do
226
+ subject.message.should_receive(:getHeaders).twice.with('toto').and_return(['test1', 'test2'])
227
+
228
+ subject.headers[:toto].should == ['test1', 'test2']
229
+ subject.headers['toto'].should == ['test1', 'test2']
230
+ end
231
+
232
+ it 'should respond to headers[]=' do
233
+ values = ['foo', :bar]
234
+
235
+ subject.message.should_receive(:removeHeader).with('toto')
236
+ values.each do |value|
237
+ subject.message.should_receive(:addHeader).with('toto', value.to_s)
238
+ end
239
+ subject.message.should_receive(:removeHeader).with('toto')
240
+ values.each do |value|
241
+ subject.message.should_receive(:addHeader).with('toto', value.to_s)
242
+ end
243
+
244
+ subject.headers[:toto] = values
245
+ subject.headers['toto'] = values
246
+ end
247
+
248
+ it 'should respond to address_header[]' do
249
+ subject.message.should_receive(:getAddressHeader).twice.with('toto').and_return(['test1', 'test2'])
250
+
251
+ subject.address_header[:toto].should == ['test1', 'test2']
252
+ subject.address_header['toto'].should == ['test1', 'test2']
253
+ end
254
+
255
+ it 'should respond to address_header[]=' do
256
+ subject.message.should_receive(:setAddressHeader).twice.with('toto', 'test2')
257
+
258
+ subject.address_header[:toto] = 'test2'
259
+ subject.address_header['toto'] = 'test2'
260
+ end
261
+
262
+ it 'should respond to address_headers[]' do
263
+ subject.message.should_receive(:getAddressHeaders).twice.with('toto').and_return(['test1', 'test2'])
264
+
265
+ subject.address_headers[:toto].should == ['test1', 'test2']
266
+ subject.address_headers['toto'].should == ['test1', 'test2']
267
+ end
268
+
269
+ it 'should not respond to address_headers[]=' do
270
+ values = ['foo', :bar]
271
+ subject.message.should_receive(:removeHeader).with('toto')
272
+ values.each do |value|
273
+ subject.message.should_receive(:addAddressHeader).with('toto', value, true)
274
+ end
275
+ subject.message.should_receive(:removeHeader).with('toto')
276
+ values.each do |value|
277
+ subject.message.should_receive(:addAddressHeader).with('toto', value, true)
278
+ end
279
+
280
+ subject.address_headers[:toto] = values
281
+ subject.address_headers['toto'] = values
282
+ end
283
+
284
+ it 'should respond to header?' do
285
+ subject.message.should_receive(:getHeader).twice.with('toto').and_return('test1')
286
+
287
+ subject.header?(:toto).should == true
288
+ subject.header?('toto').should == true
289
+ end
290
+
291
+ it 'should add a header' do
292
+ subject.message.should_receive(:addHeader).twice.with('toto', 'test2')
293
+
294
+ subject.add_header(:toto, 'test2')
295
+ subject.add_header('toto', 'test2')
296
+ end
297
+
298
+ it 'should add an address header' do
299
+ subject.message.should_receive(:addAddressHeader).with('titi', 'test1', false)
300
+ subject.message.should_receive(:addAddressHeader).twice.with('toto', 'test2', true)
301
+
302
+ subject.add_address_header(:titi, 'test1', false)
303
+ subject.add_address_header(:toto, 'test2')
304
+ subject.add_address_header('toto', 'test2')
305
+ end
306
+
307
+ it 'should push a route' do
308
+ mock_sip_factory.should_receive(:createAddress).with('sip:an_address').and_return(mock_address)
309
+ subject.should_receive(:sip_factory).and_return(mock_sip_factory)
310
+ subject.message.should_receive(:pushRoute).with(mock_address)
311
+
312
+ subject.push_route('sip:an_address')
313
+ end
314
+
315
+ describe "#proxy" do
316
+ it 'should proxy without URI' do
317
+ subject.message.should_receive(:requestURI).and_return('the_uri')
318
+ subject.message.should_receive(:proxy).and_return(mock_proxy)
319
+ mock_proxy.should_receive(:proxyTo).with('the_uri')
320
+
321
+ subject.proxy
322
+ end
323
+
324
+ it 'should proxy (RR) without URI' do
325
+ subject.message.should_receive(:requestURI).and_return('the_uri')
326
+ subject.message.should_receive(:proxy).and_return(mock_proxy)
327
+ mock_proxy.should_receive(:setRecordRoute).with(true)
328
+ mock_proxy.should_receive(:proxyTo).with('the_uri')
329
+
330
+ subject.proxy :record_route => true
331
+ end
332
+
333
+ it 'should proxy with an URI' do
334
+ subject.message.should_receive(:proxy).and_return(mock_proxy)
335
+ subject.should_receive(:sip_factory).and_return(mock_sip_factory)
336
+ mock_sip_factory.should_receive(:createURI).with('the_uri_string').and_return('the_uri')
337
+ mock_proxy.should_receive(:proxyTo).with('the_uri')
338
+
339
+ subject.proxy('the_uri_string')
340
+ end
341
+
342
+ it 'should proxy (RR) with an URI' do
343
+ subject.message.should_receive(:proxy).and_return(mock_proxy)
344
+ subject.should_receive(:sip_factory).and_return(mock_sip_factory)
345
+ mock_sip_factory.should_receive(:createURI).with('the_uri_string').and_return('the_uri')
346
+ mock_proxy.should_receive(:setRecordRoute).with(false)
347
+ mock_proxy.should_receive(:proxyTo).with('the_uri')
348
+
349
+ subject.proxy('the_uri_string', :record_route => false)
350
+ end
351
+ end
352
+ end
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ describe Sipatra do
4
+ subject do
5
+ Sipatra
6
+ end
7
+
8
+ it_should_behave_like ExtensionsMethods
9
+
10
+ describe "#register_extensions" do
11
+ module ExtensionModule
12
+ def dsl_extension
13
+ invite 'foo' do
14
+ # nothing
15
+ end
16
+ end
17
+ end
18
+
19
+ it "should add the module as a DSL extensions" do
20
+ Sipatra.register_extension ExtensionModule
21
+
22
+ Sipatra::Application.public_methods.include?('dsl_extension').should be_true
23
+ private_methods.include?('dsl_extension').should be_true
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <sip-app xmlns="http://www.jcp.org/xml/ns/sipservlet"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xsi:schemaLocation="http://www.jcp.org/xml/ns/sipservlet http://www.jcp.org/xml/ns/sipservlet/sip-app_1_1.xsd"
5
+ version="1.1">
6
+ <listener>
7
+ <listener-class>org.cipango.sipatra.DefaultContextLoader</listener-class>
8
+ </listener>
9
+ <servlet>
10
+ <servlet-name>sipatra</servlet-name>
11
+ <servlet-class>org.cipango.sipatra.SipatraServlet</servlet-class>
12
+ <load-on-startup>1</load-on-startup>
13
+ </servlet>
14
+ </sip-app>
@@ -0,0 +1,26 @@
1
+ invite /.*/ do
2
+ puts "#{message.method} #{message.requestURI}"
3
+ $stdout.flush
4
+ proxy "sip:#{message.requestURI.user}@127.0.0.1:5090"
5
+ end
6
+
7
+ register do
8
+ puts "#{message.method} #{message.requestURI}"
9
+ $stdout.flush
10
+ proxy "sip:#{message.requestURI.user}@127.0.100.1:5060"
11
+ end
12
+
13
+ request do
14
+ puts "#{message.method} #{message.requestURI} [default]"
15
+ $stdout.flush
16
+ end
17
+
18
+ #ack do
19
+ # puts "#{message.method} #{message.requestURI}"
20
+ # proxy "sip:toto@127.0.2.1:5062"
21
+ #end
22
+
23
+ response do
24
+ puts "RESPONSE: #{message.status} #{message.request.requestURI}"
25
+ $stdout.flush
26
+ end
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+ <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
3
+ <Configure class="org.cipango.sipapp.SipAppContext">
4
+ <Set name="contextPath">/sipatra</Set>
5
+ <Set name="war">/vagrant/test/integration/sipapp</Set>
6
+ <Set name="defaultsDescriptor"><SystemProperty default="." name="jetty.home"/>/etc/webdefault.xml</Set>
7
+ <Set name="defaultsSipDescriptor"><SystemProperty default="." name="jetty.home"/>/etc/sipdefault.xml</Set>
8
+ </Configure>
9
+
@@ -0,0 +1,122 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1" ?>
2
+ <!DOCTYPE scenario SYSTEM "sipp.dtd">
3
+
4
+ <!-- This program is free software; you can redistribute it and/or -->
5
+ <!-- modify it under the terms of the GNU General Public License as -->
6
+ <!-- published by the Free Software Foundation; either version 2 of the -->
7
+ <!-- License, or (at your option) any later version. -->
8
+ <!-- -->
9
+ <!-- This program is distributed in the hope that it will be useful, -->
10
+ <!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
11
+ <!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
12
+ <!-- GNU General Public License for more details. -->
13
+ <!-- -->
14
+ <!-- You should have received a copy of the GNU General Public License -->
15
+ <!-- along with this program; if not, write to the -->
16
+ <!-- Free Software Foundation, Inc., -->
17
+ <!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
18
+ <!-- -->
19
+ <!-- Sipp default 'uac' scenario. -->
20
+ <!-- -->
21
+
22
+ <scenario name="Basic Sipstone UAC">
23
+ <!-- In client mode (sipp placing calls), the Call-ID MUST be -->
24
+ <!-- generated by sipp. To do so, use [call_id] keyword. -->
25
+ <send retrans="500">
26
+ <![CDATA[
27
+
28
+ INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
29
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
30
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
31
+ To: sut <sip:[service]@[remote_ip]:[remote_port]>
32
+ Call-ID: [call_id]
33
+ CSeq: 1 INVITE
34
+ Contact: sip:sipp@[local_ip]:[local_port]
35
+ Max-Forwards: 70
36
+ Subject: Performance Test
37
+ Content-Type: application/sdp
38
+ Content-Length: [len]
39
+
40
+ v=0
41
+ o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
42
+ s=-
43
+ c=IN IP[media_ip_type] [media_ip]
44
+ t=0 0
45
+ m=audio [media_port] RTP/AVP 0
46
+ a=rtpmap:0 PCMU/8000
47
+
48
+ ]]>
49
+ </send>
50
+
51
+ <recv response="100"
52
+ optional="true">
53
+ </recv>
54
+
55
+ <recv response="180" optional="true">
56
+ </recv>
57
+
58
+ <recv response="183" optional="true">
59
+ </recv>
60
+
61
+ <!-- By adding rrs="true" (Record Route Sets), the route sets -->
62
+ <!-- are saved and used for following messages sent. Useful to test -->
63
+ <!-- against stateful SIP proxies/B2BUAs. -->
64
+ <recv response="200" rtd="true" rrs="true">
65
+ <action>
66
+ <ereg regexp=".*<([^>]*)>.*" search_in="hdr" header="Contact:" check_it="true" assign_to="1,contact" />
67
+ <log message="Junk is [$1]"/>
68
+ </action>
69
+ </recv>
70
+
71
+ <!-- Packet lost can be simulated in any send/recv message by -->
72
+ <!-- by adding the 'lost = "10"'. Value can be [1-100] percent. -->
73
+ <send>
74
+ <![CDATA[
75
+
76
+ ACK [$contact] SIP/2.0
77
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
78
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
79
+ To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
80
+ Call-ID: [call_id]
81
+ CSeq: 1 ACK
82
+ Contact: sip:sipp@[local_ip]:[local_port]
83
+ Max-Forwards: 70
84
+ Subject: Performance Test
85
+ Content-Length: 0
86
+
87
+ ]]>
88
+ </send>
89
+
90
+ <!-- This delay can be customized by the -d command-line option -->
91
+ <!-- or by adding a 'milliseconds = "value"' option here. -->
92
+ <pause milliseconds="500"/>
93
+
94
+ <!-- The 'crlf' option inserts a blank line in the statistics report. -->
95
+ <send retrans="500">
96
+ <![CDATA[
97
+
98
+ BYE [$contact] SIP/2.0
99
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
100
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
101
+ To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
102
+ Call-ID: [call_id]
103
+ CSeq: 2 BYE
104
+ Contact: sip:sipp@[local_ip]:[local_port]
105
+ Max-Forwards: 70
106
+ Subject: Performance Test
107
+ Content-Length: 0
108
+
109
+ ]]>
110
+ </send>
111
+
112
+ <recv response="200" crlf="true">
113
+ </recv>
114
+
115
+ <!-- definition of the response time repartition table (unit is ms) -->
116
+ <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
117
+
118
+ <!-- definition of the call length repartition table (unit is ms) -->
119
+ <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
120
+
121
+ </scenario>
122
+