sdp 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.
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