sipatra 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+