sdp 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sdp/parser.rb ADDED
@@ -0,0 +1,116 @@
1
+ require 'sdp'
2
+ require 'parslet'
3
+
4
+ # Class for parsing SDP description text, ideally when receiving as some sort
5
+ # of client that uses SDP for describing the session for that protocol.
6
+ #
7
+ # This parser _could_ raise an error when not finding a required SDP field, but
8
+ # was instead designed to not do so. For example, if the parser parses the
9
+ # text from an SDP description, and that text is missing the Timing field (t=),
10
+ # the RFC 4566 implies that this description isn't valid (because that field is
11
+ # required). Instead ofraising an exception, the parser lets the
12
+ # SDP::Description class deal with this.
13
+ class SDP::Parser < Parslet::Parser
14
+ # All of the fields
15
+ rule(:version) { str('v=') >> field_value.as(:protocol_version) >> eol }
16
+
17
+ rule(:origin) do
18
+ str('o=') >> field_value.as(:username) >> space >>
19
+ field_value.as(:id) >> space >>
20
+ field_value.as(:version) >> space >>
21
+ field_value.as(:network_type) >> space >>
22
+ field_value.as(:address_type) >> space >>
23
+ field_value.as(:unicast_address) >> eol
24
+ end
25
+
26
+ rule(:session_name) { str('s=') >> field_value_string.as(:name) >> eol }
27
+
28
+ rule(:session_information) do
29
+ str('i=') >> field_value_string.as(:information) >> eol
30
+ end
31
+
32
+ rule(:uri) { str('u=') >> field_value.as(:uri) >> eol }
33
+
34
+ rule(:email_address) do
35
+ str('e=') >> field_value_string.as(:email_address) >> eol
36
+ end
37
+
38
+ rule(:phone_number) do
39
+ str('p=') >> field_value_string.as(:phone_number) >> eol
40
+ end
41
+
42
+ rule(:connection_data) do
43
+ str('c=') >> field_value >> space >> field_value >> space >>
44
+ field_value.as(:connection_address) >> eol
45
+ end
46
+
47
+ rule(:bandwidth) do
48
+ str('b=') >> match('[\w]').repeat(2).as(:bandwidth_type) >> str(':') >>
49
+ field_value.as(:bandwidth) >> eol
50
+ end
51
+
52
+ rule(:timing) do
53
+ str('t=') >> field_value.as(:start_time) >> space >>
54
+ field_value.as(:stop_time) >> eol
55
+ end
56
+
57
+ rule(:repeat_times) do
58
+ str('r=') >> field_value.as(:repeat_interval) >> space >>
59
+ field_value.as(:active_duration) >>
60
+ space >> field_value_string.as(:offsets_from_start_time) >> eol
61
+ end
62
+
63
+ rule(:time_zone_group) do
64
+ field_value.as(:adjustment_time) >> space >> field_value.as(:offset)
65
+ end
66
+
67
+ rule(:time_zones) do
68
+ str('z=') >> (time_zone_group >>
69
+ (space >> time_zone_group).repeat).as(:time_zones) >> eol
70
+ end
71
+
72
+ rule(:encryption_keys) do
73
+ str('k=') >> match('[\w]').repeat.as(:encryption_method) >>
74
+ (str(':') >> field_value.as(:encryption_key)).maybe >> eol
75
+ end
76
+
77
+ rule(:attribute) do
78
+ str('a=') >> match('[\w]').repeat(1).as(:attribute) >>
79
+ (str(':') >> field_value_string.as(:value)).maybe >> eol
80
+ end
81
+
82
+ rule(:attributes) { attribute.repeat(1).as(:attributes) }
83
+
84
+ rule(:media_description) do
85
+ str('m=') >> field_value.as(:media) >> space >>
86
+ field_value.as(:port) >> space >>
87
+ field_value.as(:protocol) >> space >>
88
+ field_value.as(:format) >> eol
89
+ end
90
+
91
+ # Generics
92
+ rule(:space) { match('[ ]').repeat(1) }
93
+ rule(:eol) { match('[\r]').maybe >> match('[\n]') }
94
+ rule(:field_value) { match('\S').repeat }
95
+ rule(:field_value_string) { match('[^\r\n]').repeat }
96
+
97
+ # The SDP description
98
+ rule(:session_section) do
99
+ version.maybe >> origin.maybe >> session_name.maybe >>
100
+ session_information.maybe >> uri.maybe >> email_address.maybe >>
101
+ phone_number.maybe >> connection_data.maybe >> bandwidth.maybe >>
102
+ timing.maybe >> repeat_times.maybe >> time_zones.maybe >>
103
+ encryption_keys.maybe >> attributes.maybe
104
+ end
105
+
106
+ rule(:media_section) do
107
+ media_description >> attributes.maybe
108
+ end
109
+
110
+ rule(:description) do
111
+ session_section.as(:session_section) >>
112
+ media_section.repeat.as(:media_sections)
113
+ end
114
+
115
+ root :description
116
+ end
@@ -0,0 +1,41 @@
1
+ <%# -*- coding: UTF-8 -*- %>
2
+ v=<%= protocol_version %>
3
+ o=<%= username %> <%= id %> <%= version %> <%= network_type %> <%= address_type %> <%= unicast_address %>
4
+ s=<%= name %>
5
+ <% if information %>
6
+ i=<%= information %>
7
+ <% end %>
8
+ <% if uri %>
9
+ u=<%= uri %>
10
+ <% end %>
11
+ <% if email_address %>
12
+ e=<%= email_address %>
13
+ <% end %>
14
+ <% if phone_number %>
15
+ p=<%= phone_number %>
16
+ <% end %>
17
+ c=<%= network_type %> <%= address_type %> <%= connection_address %>
18
+ <% if bandwidth %>
19
+ b=<%= bandwidth_type %>:<%= bandwidth %>
20
+ <% end %>
21
+ t=<%= start_time %> <%= stop_time %>
22
+ <% if repeat_interval %>
23
+ r=<%= repeat_interval %> <%= active_duration %> <%= offsets_from_start_time %>
24
+ <% end %>
25
+ <% unless time_zones.empty? %>
26
+ <% if time_zones.class == Array %>
27
+ z=<% time_zones.each do |time_zone| %><%= time_zone[:adjustment_time] %> <%= time_zone[:offset] %><% end %>
28
+ <% else %>
29
+ z=<%= time_zones[:adjustment_time] %> <%= time_zones[:offset] %><% end %>
30
+ <% end %>
31
+ <% if encryption_method %>
32
+ k=<%= encryption_method %><% if encryption_key %>:<%= encryption_key %><% end %>
33
+ <% end %>
34
+ <% unless attributes.empty? %>
35
+ a=<% attributes.each do |a| %><%= a[:attribute] %><% if a[:value] %>:<%= a[:value] %><% end %><% end %>
36
+ <% end %>
37
+ <% media_sections.each do |media_section| %>
38
+ m=<%= media_section[:media] %> <%= media_section[:port]%> <%= media_section[:protocol]%> <%= media_section[:format]%>
39
+ <% if media_section[:attributes] %>
40
+ <% media_section[:attributes].each do |attribute| %>
41
+ a=<%= attribute[:attribute] %><% if attribute[:value] %>:<%= attribute[:value] %><% end %><% end %><% end %><% end %>
@@ -0,0 +1,4 @@
1
+ class SDP
2
+ # sdp version
3
+ VERSION = "0.1.0"
4
+ end
data/lib/sdp.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'sdp/version'
2
+ require 'sdp/description'
3
+ require 'sdp/parser'
4
+
5
+ # The only use for this class is the #parse method, which is in this
6
+ # base class solely for convenience. Other than this method, this
7
+ # base class doesn't really do anything.
8
+ class SDP
9
+
10
+ # Creates a parser and parses the given text in to an SDP::Description
11
+ # object.
12
+ #
13
+ # @param [String] sdp_text The text from an SDP description.
14
+ # @return [SDP::Description] The object that represents the description
15
+ # that was parsed.
16
+ def self.parse sdp_text
17
+ sdp_hash = SDP::Parser.new.parse sdp_text
18
+ SDP::Description.new(sdp_hash)
19
+ end
20
+ end
21
+
22
+ # Reclass so we can raise our own Exceptions.
23
+ class SDP::RuntimeError < StandardError; end;
data/sdp.gemspec ADDED
@@ -0,0 +1,114 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{sdp}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["sloveless"]
12
+ s.date = %q{2011-01-22}
13
+ s.description = %q{This gem allows for parsing SDP (Session Description Protocol) information in to a Ruby object, making it easy to read and work with that data. It also allows for easily creating SDP objects that can be converted to text using #to_s.}
14
+ s.email = %q{steve.loveless@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "ChangeLog.rdoc",
17
+ "LICENSE.txt",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ ".infinity_test",
23
+ ".rspec",
24
+ ".yardopts",
25
+ "ChangeLog.rdoc",
26
+ "Gemfile",
27
+ "Gemfile.lock",
28
+ "LICENSE.txt",
29
+ "README.rdoc",
30
+ "Rakefile",
31
+ "features/sdp_create.feature",
32
+ "features/sdp_get.feature",
33
+ "features/step_definitions/sdp_create_steps.rb",
34
+ "features/step_definitions/sdp_get_steps.rb",
35
+ "features/support/env.rb",
36
+ "features/support/sdp_file.txt",
37
+ "gemspec.yml",
38
+ "lib/sdp.rb",
39
+ "lib/sdp/description.rb",
40
+ "lib/sdp/parser.rb",
41
+ "lib/sdp/session_template.erb",
42
+ "lib/sdp/version.rb",
43
+ "sdp.gemspec",
44
+ "spec/sdp/description_spec.rb",
45
+ "spec/sdp/parser_spec.rb",
46
+ "spec/sdp_spec.rb",
47
+ "spec/spec_helper.rb",
48
+ "tasks/metrics.rake",
49
+ "tasks/roodi_config.yml",
50
+ "tasks/stats.rake"
51
+ ]
52
+ s.has_rdoc = %q{yard}
53
+ s.homepage = %q{http://rubygems.org/gems/sdp}
54
+ s.licenses = ["MIT"]
55
+ s.require_paths = ["lib"]
56
+ s.rubyforge_project = %q{sdp}
57
+ s.rubygems_version = %q{1.3.7}
58
+ s.summary = %q{Parse and create SDP (Session Description Protocol) text based on RFC4566.}
59
+ s.test_files = [
60
+ "spec/sdp/description_spec.rb",
61
+ "spec/sdp/parser_spec.rb",
62
+ "spec/sdp_spec.rb"
63
+ ]
64
+
65
+ if s.respond_to? :specification_version then
66
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
67
+ s.specification_version = 3
68
+
69
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
70
+ s.add_runtime_dependency(%q<parslet>, ["~> 1.0.0"])
71
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
72
+ s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
73
+ s.add_runtime_dependency(%q<parslet>, ["~> 1.0.0"])
74
+ s.add_development_dependency(%q<rake>, ["~> 0.8.7"])
75
+ s.add_development_dependency(%q<ore-core>, ["~> 0.1.0"])
76
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.0"])
77
+ s.add_development_dependency(%q<ore-tasks>, ["~> 0.3.0"])
78
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
79
+ s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
80
+ s.add_development_dependency(%q<infinity_test>, [">= 0"])
81
+ s.add_development_dependency(%q<metric_fu>, [">= 0"])
82
+ s.add_development_dependency(%q<code_statistics>, ["~> 0.2.13"])
83
+ else
84
+ s.add_dependency(%q<parslet>, ["~> 1.0.0"])
85
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
86
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
87
+ s.add_dependency(%q<parslet>, ["~> 1.0.0"])
88
+ s.add_dependency(%q<rake>, ["~> 0.8.7"])
89
+ s.add_dependency(%q<ore-core>, ["~> 0.1.0"])
90
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0"])
91
+ s.add_dependency(%q<ore-tasks>, ["~> 0.3.0"])
92
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
93
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
94
+ s.add_dependency(%q<infinity_test>, [">= 0"])
95
+ s.add_dependency(%q<metric_fu>, [">= 0"])
96
+ s.add_dependency(%q<code_statistics>, ["~> 0.2.13"])
97
+ end
98
+ else
99
+ s.add_dependency(%q<parslet>, ["~> 1.0.0"])
100
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
101
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
102
+ s.add_dependency(%q<parslet>, ["~> 1.0.0"])
103
+ s.add_dependency(%q<rake>, ["~> 0.8.7"])
104
+ s.add_dependency(%q<ore-core>, ["~> 0.1.0"])
105
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0"])
106
+ s.add_dependency(%q<ore-tasks>, ["~> 0.3.0"])
107
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
108
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
109
+ s.add_dependency(%q<infinity_test>, [">= 0"])
110
+ s.add_dependency(%q<metric_fu>, [">= 0"])
111
+ s.add_dependency(%q<code_statistics>, ["~> 0.2.13"])
112
+ end
113
+ end
114
+
@@ -0,0 +1,370 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require 'sdp/description'
3
+ require 'base64'
4
+
5
+ describe SDP::Description do
6
+ before :each do
7
+ @sdp = SDP::Description.new
8
+ end
9
+
10
+ it "initializes with the protocol_version value set" do
11
+ @sdp.protocol_version.should == SDP::PROTOCOL_VERSION
12
+ end
13
+
14
+ context "can add and retrieve fields" do
15
+ it "protocol_version" do
16
+ @sdp.protocol_version = 1
17
+ @sdp.protocol_version.should == 1
18
+ end
19
+
20
+ it "username" do
21
+ @sdp.username = "jdoe"
22
+ @sdp.username.should == "jdoe"
23
+ end
24
+
25
+ it "id" do
26
+ @sdp.id = 2890844526
27
+ @sdp.id.should == 2890844526
28
+ end
29
+
30
+ it "version" do
31
+ @sdp.version = 2890842807
32
+ @sdp.version.should == 2890842807
33
+ end
34
+
35
+ it "network_type" do
36
+ @sdp.network_type = :IN
37
+ @sdp.network_type.should == :IN
38
+ end
39
+
40
+ it "address_type" do
41
+ @sdp.address_type = :IP4
42
+ @sdp.address_type.should == :IP4
43
+ end
44
+
45
+ it "unicast_address" do
46
+ @sdp.unicast_address = "10.47.16.5"
47
+ @sdp.unicast_address.should == "10.47.16.5"
48
+ end
49
+
50
+ it "name" do
51
+ @sdp.name = "This is a session"
52
+ @sdp.name.should == "This is a session"
53
+ end
54
+
55
+ it "name can be a ' '" do
56
+ @sdp.name = " "
57
+ @sdp.name.should == " "
58
+ end
59
+
60
+ it "information" do
61
+ @sdp.information = "This is a session"
62
+ @sdp.information.should == "This is a session"
63
+ end
64
+
65
+ it "uri" do
66
+ @sdp.uri = "http://localhost"
67
+ @sdp.uri.should == "http://localhost"
68
+ end
69
+
70
+ it "email_address" do
71
+ @sdp.email_address = 'me@me.com'
72
+ @sdp.email_address.should == 'me@me.com'
73
+ end
74
+
75
+ it "email_address in alternate form" do
76
+ @sdp.email_address = "Jane Doe <j.doe@example.com>"
77
+ @sdp.email_address.should == "Jane Doe <j.doe@example.com>"
78
+ end
79
+
80
+ it "phone_number" do
81
+ @sdp.phone_number = "+1 555 123 4567"
82
+ @sdp.phone_number.should == "+1 555 123 4567"
83
+ end
84
+
85
+ it "connection_address" do
86
+ @sdp.connection_address = 'localhost'
87
+ @sdp.connection_address.should == 'localhost'
88
+ end
89
+
90
+ it "connection_address using TTL" do
91
+ @sdp.connection_address = "224.2.36.42/127"
92
+ @sdp.connection_address.should == "224.2.36.42/127"
93
+ end
94
+
95
+ it "connection_address using IPv6 address and count" do
96
+ @sdp.connection_address = "FF15::101/3"
97
+ @sdp.connection_address.should == "FF15::101/3"
98
+ end
99
+
100
+ it "bandwidth_type" do
101
+ @sdp.bandwidth = :CT
102
+ @sdp.bandwidth.should == :CT
103
+ end
104
+
105
+ it "bandwidth" do
106
+ @sdp.bandwidth = 100
107
+ @sdp.bandwidth.should == 100
108
+ end
109
+
110
+ it "start_time" do
111
+ @sdp.start_time = 99112299
112
+ @sdp.start_time.should == 99112299
113
+ end
114
+
115
+ it "stop_time" do
116
+ @sdp.stop_time = 99999999
117
+ @sdp.stop_time.should == 99999999
118
+ end
119
+
120
+ it "repeat_interval" do
121
+ @sdp.repeat_interval = 12345
122
+ @sdp.repeat_interval.should == 12345
123
+ end
124
+
125
+ it "active_duration" do
126
+ @sdp.active_duration = 12345
127
+ @sdp.active_duration.should == 12345
128
+ end
129
+
130
+ it "offsets_from_start_time" do
131
+ @sdp.offsets_from_start_time = 99
132
+ @sdp.offsets_from_start_time.should == 99
133
+ end
134
+
135
+ context "time_zones" do
136
+ it "one time zone" do
137
+ new_values = { :adjustment_time => 111111,
138
+ :offset => 99 }
139
+ @sdp.time_zones << new_values
140
+ @sdp.time_zones.should == [new_values]
141
+ end
142
+
143
+ it "two time_zones" do
144
+ new_values1 = { :adjustment_time => 111111,
145
+ :offset => 99 }
146
+ new_values2 = { :adjustment_time => 222222,
147
+ :offset => 88 }
148
+ @sdp.time_zones << new_values1
149
+ @sdp.time_zones << new_values2
150
+ @sdp.time_zones.should == [new_values1, new_values2]
151
+ end
152
+ end
153
+
154
+ context "encryption keys" do
155
+ it "clear" do
156
+ @sdp.encryption_method = 'clear'
157
+ @sdp.encryption_method.should == 'clear'
158
+ @sdp.encryption_key = 'password'
159
+ @sdp.encryption_key.should == 'password'
160
+ end
161
+
162
+ it "base64" do
163
+ @sdp.encryption_method = 'base64'
164
+ @sdp.encryption_method.should == 'base64'
165
+ enc = Base64.encode64('password')
166
+ @sdp.encryption_key = enc
167
+ @sdp.encryption_key.should == enc
168
+ end
169
+
170
+ it "uri" do
171
+ @sdp.encryption_method = 'uri'
172
+ @sdp.encryption_method.should == 'uri'
173
+ uri = "http://aserver.com/thing.pdf"
174
+ @sdp.encryption_key = uri
175
+ @sdp.encryption_key.should == uri
176
+ end
177
+
178
+ it "prompt" do
179
+ @sdp.encryption_method = 'prompt'
180
+ @sdp.encryption_method.should == 'prompt'
181
+ @sdp.encryption_key.should be_nil
182
+ end
183
+ end
184
+
185
+ context "attributes" do
186
+ it "one attribute with value" do
187
+ new_values = { :attribute => 'rtpmap',
188
+ :value => "99 h263-1998/90000" }
189
+ @sdp.attributes << new_values
190
+ @sdp.attributes.first.should == new_values
191
+ end
192
+
193
+ it "one attribute with empty value" do
194
+ new_values = { :attribute => 'rtpmap',
195
+ :value => "" }
196
+ @sdp.attributes << new_values
197
+ @sdp.attributes.first.should == new_values
198
+ end
199
+
200
+ it "one attribute with nil value" do
201
+ new_values = { :attribute => 'rtpmap' }
202
+ @sdp.attributes << new_values
203
+ @sdp.attributes.first.should == new_values
204
+ end
205
+
206
+ it "two attributes" do
207
+ new_values1 = { :attribute => 'test' }
208
+ new_values2 = { :attribute => 'rtpmap',
209
+ :value => "99 h263-1998/90000" }
210
+ @sdp.attributes << new_values1
211
+ @sdp.attributes << new_values2
212
+ @sdp.attributes.should == [new_values1, new_values2]
213
+ end
214
+ end
215
+
216
+ context "media_sections" do
217
+ it "can add a basic media section" do
218
+ new_values = { :media => 'audio',
219
+ :port => 12345,
220
+ :protocol => 'RTP/AVP',
221
+ :format => 99 }
222
+ @sdp.media_sections << new_values
223
+ @sdp.media_sections.first.should == new_values
224
+ end
225
+
226
+ it "can add a basic media section with attributes" do
227
+ new_values = { :media => 'audio',
228
+ :port => 12345,
229
+ :protocol => 'RTP/AVP',
230
+ :format => 99,
231
+ :attributes => [
232
+ {
233
+ :attribute => "rtpmap",
234
+ :value => "99 h263-1998/90000"
235
+ }
236
+ ]
237
+ }
238
+ @sdp.media_sections << new_values
239
+ @sdp.media_sections.first.should == new_values
240
+ end
241
+
242
+ it "can add 2 basic media sections" do
243
+ new_values = []
244
+ new_values << { :media => 'audio',
245
+ :port => 12345,
246
+ :protocol => 'RTP/AVP',
247
+ :format => 99 }
248
+ @sdp.media_sections << new_values[0]
249
+
250
+ new_values << { :media => 'video',
251
+ :port => 5678,
252
+ :protocol => 'RTP/AVP',
253
+ :format => 33 }
254
+ @sdp.media_sections << new_values[1]
255
+
256
+ @sdp.media_sections.class.should == Array
257
+ @sdp.media_sections[0].should == new_values[0]
258
+ @sdp.media_sections[1].should == new_values[1]
259
+ end
260
+ end
261
+ end
262
+
263
+ context "#to_s" do
264
+ it "contains required session section values" do
265
+ @sdp.to_s.should match /v=0/
266
+ @sdp.to_s.should match /o=/
267
+ @sdp.to_s.should match /s=/
268
+ @sdp.to_s.should match /t=/
269
+ end
270
+ end
271
+
272
+ context "#valid?" do
273
+ before :each do
274
+ @sdp = SDP::Description.new
275
+
276
+ @sdp.protocol_version = 0
277
+ @sdp.username = "jdoe"
278
+ @sdp.id = 12345
279
+ @sdp.version = 12345
280
+ @sdp.network_type = :IN
281
+ @sdp.address_type = :IP4
282
+ @sdp.unicast_address = "127.0.0.1"
283
+ @sdp.name = "This is a test"
284
+ @sdp.start_time = 12345678
285
+ @sdp.stop_time = 12345680
286
+ @sdp.media_sections << { :media => "audio", :port => 123,
287
+ :protocol => "RTP/AVP", :format => 99 }
288
+ end
289
+
290
+ it "is valid when all required fields have values" do
291
+ @sdp.valid?.should be_true
292
+ end
293
+
294
+ it "is NOT valid when protocol_version isn't set" do
295
+ @sdp.protocol_version = nil
296
+ @sdp.valid?.should be_false
297
+ end
298
+
299
+ it "is NOT valid when username isn't set" do
300
+ @sdp.username = nil
301
+ @sdp.valid?.should be_false
302
+ end
303
+
304
+ it "is NOT valid when id isn't set" do
305
+ @sdp.id = nil
306
+ @sdp.valid?.should be_false
307
+ end
308
+
309
+ it "is NOT valid when version isn't set" do
310
+ @sdp.version = nil
311
+ @sdp.valid?.should be_false
312
+ end
313
+
314
+ it "is NOT valid when network_type isn't set" do
315
+ @sdp.network_type = nil
316
+ @sdp.valid?.should be_false
317
+ end
318
+
319
+ it "is NOT valid when address_type isn't set" do
320
+ @sdp.address_type = nil
321
+ @sdp.valid?.should be_false
322
+ end
323
+
324
+ it "is NOT valid when unicast_address isn't set" do
325
+ @sdp.unicast_address = nil
326
+ @sdp.valid?.should be_false
327
+ end
328
+
329
+ it "is NOT valid when name isn't set" do
330
+ @sdp.name = nil
331
+ @sdp.valid?.should be_false
332
+ end
333
+
334
+ it "is valid when name is ' '" do
335
+ @sdp.name = ' '
336
+ @sdp.valid?.should be_true
337
+ end
338
+
339
+ it "is NOT valid when start_time isn't set" do
340
+ @sdp.start_time = nil
341
+ @sdp.valid?.should be_false
342
+ end
343
+
344
+ it "is NOT valid when stop_time isn't set" do
345
+ @sdp.stop_time = nil
346
+ @sdp.valid?.should be_false
347
+ end
348
+
349
+ it "is NOT valid when media_sections is empty" do
350
+ @sdp[:media_sections] = []
351
+ @sdp.valid?.should be_false
352
+ end
353
+ end
354
+
355
+ context "bad initialize values" do
356
+ it "ensures a Hash is passed in" do
357
+ lambda do
358
+ SDP::Description.new 1
359
+ end.should raise_error SDP::RuntimeError
360
+ end
361
+
362
+ it "handles a Hash with irrelvant keys" do
363
+ session_values = { :bobo => "thing" }
364
+
365
+ lambda do
366
+ SDP::Description.new session_values
367
+ end.should raise_error SDP::RuntimeError
368
+ end
369
+ end
370
+ end