playful 0.1.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +19 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +5 -0
  6. data/Gemfile +6 -0
  7. data/History.rdoc +3 -0
  8. data/LICENSE.rdoc +22 -0
  9. data/README.rdoc +194 -0
  10. data/Rakefile +20 -0
  11. data/features/control_point.feature +13 -0
  12. data/features/device.feature +22 -0
  13. data/features/device_discovery.feature +9 -0
  14. data/features/step_definitions/control_point_steps.rb +19 -0
  15. data/features/step_definitions/device_discovery_steps.rb +40 -0
  16. data/features/step_definitions/device_steps.rb +28 -0
  17. data/features/support/common.rb +9 -0
  18. data/features/support/env.rb +17 -0
  19. data/features/support/fake_upnp_device_collection.rb +108 -0
  20. data/features/support/world_extensions.rb +15 -0
  21. data/lib/core_ext/hash_patch.rb +5 -0
  22. data/lib/core_ext/socket_patch.rb +16 -0
  23. data/lib/core_ext/to_upnp_s.rb +65 -0
  24. data/lib/playful.rb +5 -0
  25. data/lib/playful/control_point.rb +175 -0
  26. data/lib/playful/control_point/base.rb +74 -0
  27. data/lib/playful/control_point/device.rb +511 -0
  28. data/lib/playful/control_point/error.rb +13 -0
  29. data/lib/playful/control_point/service.rb +404 -0
  30. data/lib/playful/device.rb +28 -0
  31. data/lib/playful/logger.rb +8 -0
  32. data/lib/playful/ssdp.rb +195 -0
  33. data/lib/playful/ssdp/broadcast_searcher.rb +114 -0
  34. data/lib/playful/ssdp/error.rb +6 -0
  35. data/lib/playful/ssdp/listener.rb +38 -0
  36. data/lib/playful/ssdp/multicast_connection.rb +112 -0
  37. data/lib/playful/ssdp/network_constants.rb +17 -0
  38. data/lib/playful/ssdp/notifier.rb +41 -0
  39. data/lib/playful/ssdp/searcher.rb +87 -0
  40. data/lib/playful/version.rb +3 -0
  41. data/lib/rack/upnp_control_point.rb +70 -0
  42. data/playful.gemspec +38 -0
  43. data/spec/spec_helper.rb +16 -0
  44. data/spec/support/search_responses.rb +134 -0
  45. data/spec/unit/core_ext/to_upnp_s_spec.rb +105 -0
  46. data/spec/unit/playful/control_point/device_spec.rb +7 -0
  47. data/spec/unit/playful/control_point_spec.rb +45 -0
  48. data/spec/unit/playful/ssdp/listener_spec.rb +29 -0
  49. data/spec/unit/playful/ssdp/multicast_connection_spec.rb +157 -0
  50. data/spec/unit/playful/ssdp/notifier_spec.rb +76 -0
  51. data/spec/unit/playful/ssdp/searcher_spec.rb +110 -0
  52. data/spec/unit/playful/ssdp_spec.rb +214 -0
  53. data/tasks/control_point.html +30 -0
  54. data/tasks/control_point.thor +43 -0
  55. data/tasks/search.thor +128 -0
  56. data/tasks/test_js/FABridge.js +1425 -0
  57. data/tasks/test_js/WebSocketMain.swf +807 -0
  58. data/tasks/test_js/swfobject.js +825 -0
  59. data/tasks/test_js/web_socket.js +1133 -0
  60. data/test/test_ssdp.rb +298 -0
  61. data/test/test_ssdp_notification.rb +74 -0
  62. data/test/test_ssdp_response.rb +31 -0
  63. data/test/test_ssdp_search.rb +23 -0
  64. metadata +339 -0
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+ require 'playful/control_point/device'
3
+
4
+
5
+ describe Playful::ControlPoint::Device do
6
+ pending
7
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'playful/control_point'
3
+
4
+
5
+ describe Playful::ControlPoint do
6
+ subject do
7
+ Playful::ControlPoint.new(1)
8
+ end
9
+
10
+ describe '#ssdp_search_and_listen' do
11
+ let(:notification) do
12
+ double 'notification'
13
+ end
14
+
15
+ let(:searcher) do
16
+ s = double 'Playful::SSDP::Searcher'
17
+ s.stub_chain(:discovery_responses, :subscribe).and_yield notification
18
+
19
+ s
20
+ end
21
+
22
+ before do
23
+ expect(Playful::SSDP).to receive(:search).with('ssdp:all', {}).and_return searcher
24
+ EM.stub(:add_periodic_timer)
25
+ end
26
+
27
+ after do
28
+ EM.unstub(:add_periodic_timer)
29
+ end
30
+
31
+ it 'creates a ControlPoint::Device for every discovery response' do
32
+ EM.stub(:add_timer)
33
+ subject.should_receive(:create_device).with(notification)
34
+ subject.ssdp_search_and_listen('ssdp:all')
35
+ end
36
+
37
+ it 'shuts down the searcher and starts the listener after the given response wait time' do
38
+ EM.stub(:add_timer).and_yield
39
+ subject.stub(:create_device)
40
+ searcher.should_receive(:close_connection)
41
+ subject.should_receive(:listen)
42
+ subject.ssdp_search_and_listen('ssdp:all')
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ require 'playful/ssdp/listener'
3
+
4
+
5
+ describe Playful::SSDP::Listener do
6
+ around(:each) do |example|
7
+ EM.synchrony do
8
+ example.run
9
+ EM.stop
10
+ end
11
+ end
12
+
13
+ before do
14
+ allow_any_instance_of(Playful::SSDP::Listener).to receive(:setup_multicast_socket)
15
+ end
16
+
17
+ subject { Playful::SSDP::Listener.new(1) }
18
+
19
+ describe '#receive_data' do
20
+ it 'logs the IP and port from which the request came from' do
21
+ expect(subject).to receive(:peer_info).and_return %w[ip port]
22
+ expect(subject).to receive(:log).
23
+ with("Response from ip:port:\nmessage\n")
24
+ allow(subject).to receive(:parse).and_return({})
25
+
26
+ subject.receive_data('message')
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,157 @@
1
+ require 'spec_helper'
2
+ require 'playful/ssdp/multicast_connection'
3
+
4
+
5
+ describe Playful::SSDP::MulticastConnection do
6
+ around(:each) do |example|
7
+ EM.synchrony do
8
+ example.run
9
+ EM.stop
10
+ end
11
+ end
12
+
13
+ subject { Playful::SSDP::MulticastConnection.new(1) }
14
+
15
+ before do
16
+ Playful.log = false
17
+ end
18
+
19
+ describe '#peer_info' do
20
+ before do
21
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:setup_multicast_socket)
22
+ subject.stub_chain(:get_peername, :[], :unpack).
23
+ and_return(%w[1234 1 2 3 4])
24
+ end
25
+
26
+ it 'returns an Array with IP and port' do
27
+ expect(subject.peer_info).to eq ['1.2.3.4', 1234]
28
+ end
29
+
30
+ it 'returns IP as a String' do
31
+ expect(subject.peer_info.first).to be_a String
32
+ end
33
+
34
+ it 'returns port as a Fixnum' do
35
+ expect(subject.peer_info.last).to be_a Fixnum
36
+ end
37
+ end
38
+
39
+ describe '#parse' do
40
+ before do
41
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:setup_multicast_socket)
42
+ end
43
+
44
+ it 'turns headers into Hash keys' do
45
+ result = subject.parse ROOT_DEVICE1
46
+ expect(result).to have_key :cache_control
47
+ expect(result).to have_key :date
48
+ expect(result).to have_key :location
49
+ expect(result).to have_key :server
50
+ expect(result).to have_key :st
51
+ expect(result).to have_key :ext
52
+ expect(result).to have_key :usn
53
+ expect(result).to have_key :content_length
54
+ end
55
+
56
+ it 'turns header values into Hash values' do
57
+ result = subject.parse ROOT_DEVICE1
58
+ expect(result[:cache_control]).to eq 'max-age=1200'
59
+ expect(result[:date]).to eq 'Mon, 26 Sep 2011 06:40:19 GMT'
60
+ expect(result[:location]).to eq 'http://1.2.3.4:5678/description/fetch'
61
+ expect(result[:server]).to eq 'Linux-i386-2.6.38-10-generic-pae, UPnP/1.0, PMS/1.25.1'
62
+ expect(result[:st]).to eq 'upnp:rootdevice'
63
+ expect(result[:ext]).to be_empty
64
+ expect(result[:usn]).to eq 'uuid:3c202906-992d-3f0f-b94c-90e1902a136d::upnp:rootdevice'
65
+ expect(result[:content_length]).to eq '0'
66
+ end
67
+
68
+ context 'single line String as response data' do
69
+ before { @data = ROOT_DEVICE1.gsub("\n", ' ') }
70
+
71
+ it 'returns an empty Hash' do
72
+ expect(subject.parse(@data)).to eq({ })
73
+ end
74
+
75
+ it "logs the 'bad' response" do
76
+ subject.should_receive(:log).twice
77
+ subject.parse @data
78
+ end
79
+ end
80
+ end
81
+
82
+ describe '#setup_multicast_socket' do
83
+ before do
84
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:set_membership)
85
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:switch_multicast_loop)
86
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:set_multicast_ttl)
87
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:set_ttl)
88
+ end
89
+
90
+ it 'adds 0.0.0.0 and 239.255.255.250 to the membership group' do
91
+ expect(subject).to receive(:set_membership).with(
92
+ IPAddr.new('239.255.255.250').hton + IPAddr.new('0.0.0.0').hton
93
+ )
94
+ subject.setup_multicast_socket
95
+ end
96
+
97
+ it 'sets multicast TTL to 4' do
98
+ expect(subject).to receive(:set_multicast_ttl).with(4)
99
+ subject.setup_multicast_socket
100
+ end
101
+
102
+ it 'sets TTL to 4' do
103
+ expect(subject).to receive(:set_ttl).with(4)
104
+ subject.setup_multicast_socket
105
+ end
106
+
107
+ context "ENV['RUBY_UPNP_ENV'] != testing" do
108
+ after { ENV['RUBY_UPNP_ENV'] = 'testing' }
109
+
110
+ it 'turns multicast loop off' do
111
+ ENV['RUBY_UPNP_ENV'] = 'development'
112
+ expect(subject).to receive(:switch_multicast_loop).with(:off)
113
+ subject.setup_multicast_socket
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '#switch_multicast_loop' do
119
+ before do
120
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:setup_multicast_socket)
121
+ end
122
+
123
+ it "passes '\\001' to the socket option call when param == :on" do
124
+ expect(subject).to receive(:set_sock_opt).with(
125
+ Socket::IPPROTO_IP, Socket::IP_MULTICAST_LOOP, "\001"
126
+ )
127
+ subject.switch_multicast_loop :on
128
+ end
129
+
130
+ it "passes '\\001' to the socket option call when param == '\\001'" do
131
+ expect(subject).to receive(:set_sock_opt).with(
132
+ Socket::IPPROTO_IP, Socket::IP_MULTICAST_LOOP, "\001"
133
+ )
134
+ subject.switch_multicast_loop "\001"
135
+ end
136
+
137
+ it "passes '\\000' to the socket option call when param == :off" do
138
+ expect(subject).to receive(:set_sock_opt).with(
139
+ Socket::IPPROTO_IP, Socket::IP_MULTICAST_LOOP, "\000"
140
+ )
141
+ subject.switch_multicast_loop :off
142
+ end
143
+
144
+ it "passes '\\000' to the socket option call when param == '\\000'" do
145
+ expect(subject).to receive(:set_sock_opt).with(
146
+ Socket::IPPROTO_IP, Socket::IP_MULTICAST_LOOP, "\000"
147
+ )
148
+ subject.switch_multicast_loop "\000"
149
+ end
150
+
151
+ it "raises when not :on, :off, '\\000', or '\\001'" do
152
+ expect { subject.switch_multicast_loop 12312312 }.
153
+ to raise_error(Playful::SSDP::Error)
154
+ end
155
+ end
156
+ end
157
+
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+ require 'playful/ssdp/notifier'
3
+
4
+
5
+ describe Playful::SSDP::Notifier do
6
+ around(:each) do |example|
7
+ EM.synchrony do
8
+ example.run
9
+ EM.stop
10
+ end
11
+ end
12
+
13
+ let(:nt) { 'en tee' }
14
+ let(:usn) { 'you ess en' }
15
+ let(:ddf_url) { 'ddf url' }
16
+ let(:duration) { 567 }
17
+
18
+ subject do
19
+ Playful::SSDP::Notifier.new(1, nt, usn, ddf_url, duration)
20
+ end
21
+
22
+ describe '#initialize' do
23
+ it 'creates a notification' do
24
+ expect_any_instance_of(Playful::SSDP::Notifier).to receive(:notification).
25
+ with(nt, usn, ddf_url, duration)
26
+
27
+ subject
28
+ end
29
+ end
30
+
31
+ describe '#post_init' do
32
+ context 'send_datagram returns positive value' do
33
+ before do
34
+ expect(subject).to receive(:send_datagram).and_return 1
35
+ end
36
+
37
+ it 'logs what was sent' do
38
+ expect(subject).to receive(:log).with /Sent notification/
39
+
40
+ subject.post_init
41
+ end
42
+ end
43
+
44
+ context 'send_datagram returns 0' do
45
+ before do
46
+ expect(subject).to receive(:send_datagram).and_return 0
47
+ end
48
+
49
+ it 'does not log what was sent' do
50
+ expect(subject).to_not receive(:log)
51
+
52
+ subject.post_init
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#notification' do
58
+ before do
59
+ subject.instance_variable_set(:@os, 'my OS')
60
+ end
61
+
62
+ it 'builds the notification message' do
63
+ expect(subject.notification(nt, usn, ddf_url, duration)).to eq <<-NOTE
64
+ NOTIFY * HTTP/1.1\r
65
+ HOST: 239.255.255.250:1900\r
66
+ CACHE-CONTROL: max-age=567\r
67
+ LOCATION: ddf url\r
68
+ NT: en tee\r
69
+ NTS: ssdp:alive\r
70
+ SERVER: my OS UPnP/1.0 Playful/#{Playful::VERSION}\r
71
+ USN: you ess en\r
72
+ \r
73
+ NOTE
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+ require 'playful/ssdp/searcher'
3
+
4
+
5
+ describe Playful::SSDP::Searcher do
6
+ around(:each) do |example|
7
+ EM.synchrony do
8
+ example.run
9
+ EM.stop
10
+ end
11
+ end
12
+
13
+ before do
14
+ Playful.log = false
15
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:setup_multicast_socket)
16
+ end
17
+
18
+ subject do
19
+ Playful::SSDP::Searcher.new(1, 'ssdp:all', {})
20
+ end
21
+
22
+ it 'lets you read its responses' do
23
+ responses = double 'responses'
24
+ subject.instance_variable_set(:@discovery_responses, responses)
25
+ expect(subject.discovery_responses).to eq responses
26
+ end
27
+
28
+ describe '#initialize' do
29
+ it 'does an #m_search' do
30
+ expect_any_instance_of(Playful::SSDP::Searcher).to receive(:m_search).and_return(<<-MSEARCH
31
+ M-SEARCH * HTTP/1.1\r
32
+ HOST: 239.255.255.250:1900\r
33
+ MAN: "ssdp:discover"\r
34
+ MX: 5\r
35
+ ST: ssdp:all\r
36
+ \r
37
+ MSEARCH
38
+ )
39
+ subject
40
+ end
41
+ end
42
+
43
+ describe '#receive_data' do
44
+ let(:parsed_response) do
45
+ parsed_response = double 'parsed response'
46
+ expect(parsed_response).to receive(:has_key?).with(:nts).and_return false
47
+ expect(parsed_response).to receive(:[]).and_return false
48
+
49
+ parsed_response
50
+ end
51
+
52
+ it 'takes a response and adds it to the list of responses' do
53
+ response = double 'response'
54
+ allow(subject).to receive(:peer_info).and_return(['0.0.0.0', 4567])
55
+
56
+ expect(subject).to receive(:parse).with(response).exactly(1).times.
57
+ and_return(parsed_response)
58
+ expect(subject.instance_variable_get(:@discovery_responses)).to receive(:<<).
59
+ with(parsed_response)
60
+
61
+ subject.receive_data(response)
62
+ end
63
+ end
64
+
65
+ describe '#post_init' do
66
+ before { allow_any_instance_of(Playful::SSDP::Searcher).to receive(:m_search).and_return('hi') }
67
+
68
+ it 'sends an M-SEARCH as a datagram over 239.255.255.250:1900' do
69
+ m_search_count_times = subject.instance_variable_get(:@m_search_count)
70
+ expect(subject).to receive(:send_datagram).
71
+ with('hi', '239.255.255.250', 1900).
72
+ exactly(m_search_count_times).times.
73
+ and_return 0
74
+ subject.post_init
75
+ end
76
+ end
77
+
78
+ describe '#m_search' do
79
+ it 'builds the MSEARCH string using the given parameters' do
80
+ expect(subject.m_search('ssdp:all', 10)).to eq <<-MSEARCH
81
+ M-SEARCH * HTTP/1.1\r
82
+ HOST: 239.255.255.250:1900\r
83
+ MAN: "ssdp:discover"\r
84
+ MX: 10\r
85
+ ST: ssdp:all\r
86
+ \r
87
+ MSEARCH
88
+ end
89
+
90
+ it 'uses 239.255.255.250 as the HOST IP' do
91
+ expect(subject.m_search('ssdp:all', 10)).to match(/HOST: 239.255.255.250/m)
92
+ end
93
+
94
+ it 'uses 1900 as the HOST port' do
95
+ expect(subject.m_search('ssdp:all', 10)).to match(/HOST:.*1900/m)
96
+ end
97
+
98
+ it 'lets you search for undefined search target types' do
99
+ expect(subject.m_search('spaceship', 10)).to eq <<-MSEARCH
100
+ M-SEARCH * HTTP/1.1\r
101
+ HOST: 239.255.255.250:1900\r
102
+ MAN: "ssdp:discover"\r
103
+ MX: 10\r
104
+ ST: spaceship\r
105
+ \r
106
+ MSEARCH
107
+ end
108
+ end
109
+ end
110
+
@@ -0,0 +1,214 @@
1
+ require 'spec_helper'
2
+ require 'playful/ssdp'
3
+
4
+
5
+ describe Playful::SSDP do
6
+ subject { Playful::SSDP }
7
+
8
+ describe '.listen' do
9
+ let(:listener) do
10
+ searcher = double 'Playful::SSDP::Listener'
11
+ searcher.stub_chain(:alive_notifications, :pop).and_yield(%w[one two])
12
+ searcher.stub_chain(:byebye_notifications, :pop).and_yield(%w[three four])
13
+
14
+ searcher
15
+ end
16
+
17
+ before do
18
+ allow(EM).to receive(:run).and_yield
19
+ allow(EM).to receive(:add_timer)
20
+ allow(EM).to receive(:open_datagram_socket).and_return listener
21
+ end
22
+
23
+ context 'reactor is already running' do
24
+ it 'returns a Playful::SSDP::Listener' do
25
+ allow(EM).to receive(:reactor_running?).and_return true
26
+ expect(subject.listen).to eq listener
27
+ end
28
+ end
29
+
30
+ context 'reactor is not already running' do
31
+ it 'returns a Hash of available and byebye responses' do
32
+ allow(EM).to receive(:add_shutdown_hook).and_yield
33
+ expect(subject.listen).to eq({
34
+ alive_notifications: %w[one two],
35
+ byebye_notifications: %w[three four]
36
+ })
37
+ end
38
+
39
+ it 'opens a UDP socket on 239.255.255.250, port 1900' do
40
+ allow(EM).to receive(:add_shutdown_hook)
41
+ expect(EM).to receive(:open_datagram_socket).with('239.255.255.250', 1900,
42
+ Playful::SSDP::Listener, 4)
43
+ subject.listen
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '.search' do
49
+ let(:multicast_searcher) do
50
+ searcher = double 'Playful::SSDP::Searcher'
51
+ searcher.stub_chain(:discovery_responses, :subscribe).and_yield(%w[one two])
52
+
53
+ searcher
54
+ end
55
+
56
+ let(:broadcast_searcher) do
57
+ searcher = double 'Playful::SSDP::BroadcastSearcher'
58
+ searcher.stub_chain(:discovery_responses, :subscribe).and_yield(%w[three four])
59
+
60
+ searcher
61
+ end
62
+
63
+ before do
64
+ allow(EM).to receive(:run).and_yield
65
+ allow(EM).to receive(:add_timer)
66
+ allow(EM).to receive(:open_datagram_socket).and_return multicast_searcher
67
+ end
68
+
69
+ context 'when search_target is not a String' do
70
+ it 'calls #to_upnp_s on search_target' do
71
+ search_target = double('search_target')
72
+ expect(search_target).to receive(:to_upnp_s)
73
+ subject.search(search_target)
74
+ end
75
+ end
76
+
77
+ context 'when search_target is a String' do
78
+ it 'calls #to_upnp_s on search_target but does not alter it' do
79
+ search_target = "I'm a string"
80
+ expect(search_target).to receive(:to_upnp_s).and_call_original
81
+
82
+ expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0,
83
+ Playful::SSDP::Searcher, "I'm a string", {})
84
+ subject.search(search_target)
85
+ end
86
+ end
87
+
88
+ context 'reactor is already running' do
89
+ it 'returns a Playful::SSDP::Searcher' do
90
+ allow(EM).to receive(:reactor_running?).and_return true
91
+ expect(subject.search).to eq multicast_searcher
92
+ end
93
+ end
94
+
95
+ context 'reactor is not already running' do
96
+ context 'options hash includes do_broadcast_search' do
97
+ before do
98
+ allow(EM).to receive(:open_datagram_socket).
99
+ and_return(multicast_searcher, broadcast_searcher)
100
+ end
101
+
102
+ it 'returns an Array of responses' do
103
+ allow(EM).to receive(:add_shutdown_hook).and_yield
104
+ expect(subject.search(:all, do_broadcast_search: true)).to eq %w[one two three four]
105
+ end
106
+
107
+ it 'opens 2 UDP sockets on 0.0.0.0, port 0' do
108
+ allow(EM).to receive(:add_shutdown_hook)
109
+ expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0, Playful::SSDP::Searcher,
110
+ 'ssdp:all', {})
111
+ expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0, Playful::SSDP::BroadcastSearcher,
112
+ 'ssdp:all', 5, 4)
113
+ subject.search(:all, do_broadcast_search: true)
114
+ end
115
+ end
116
+
117
+ context 'options hash does not include do_broadcast_search' do
118
+ it 'returns an Array of responses' do
119
+ allow(EM).to receive(:add_shutdown_hook).and_yield
120
+ expect(subject.search).to eq %w[one two]
121
+ end
122
+
123
+ it 'opens a UDP socket on 0.0.0.0, port 0' do
124
+ allow(EM).to receive(:add_shutdown_hook)
125
+ expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0, Playful::SSDP::Searcher,
126
+ 'ssdp:all', {})
127
+ subject.search
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ describe '.notify' do
134
+ pending 'Implementation of UPnP Devices'
135
+ end
136
+
137
+ describe '.send_notification' do
138
+ pending 'Implementation of UPnP Devices'
139
+ end
140
+
141
+ =begin
142
+ context 'by default' do
143
+ it "searches for 'ssdp:all'" do
144
+ pending
145
+ end
146
+
147
+ it 'waits for 5 seconds for responses' do
148
+ before = Time.now
149
+
150
+ SSDP.search
151
+
152
+ after = Time.now
153
+ (after - before).should < 5.1
154
+ (after - before).should > 5.0
155
+ end
156
+ end
157
+
158
+ context "finds 'upnp:rootdevice's" do
159
+ it "by using the spec's string 'upnp:rootdevice'" do
160
+ SSDP.search('upnp:rootdevice').should == [
161
+ {
162
+ :cache_control=>'max-age=1200',
163
+ :date=>'Mon, 26 Sep 2011 06:40:19 GMT',
164
+ :location=>'http://192.168.10.3:5001/description/fetch',
165
+ :server=>'Linux-i386-2.6.38-10-generic-pae, UPnP/1.0, PMS/1.25.1',
166
+ :st=>'upnp:rootdevice',
167
+ :ext=>'',
168
+ :usn=>'uuid:3c202906-992d-3f0f-b94c-90e1902a136d::upnp:rootdevice',
169
+ :content_length=>'0'
170
+ }
171
+ ]
172
+ end
173
+
174
+ it 'by using :root' do
175
+ pending
176
+ end
177
+ end
178
+
179
+ it 'can wait for user-defined seconds for responses' do
180
+ before = Time.now
181
+
182
+ SSDP.search(:all, 1)
183
+
184
+ after = Time.now
185
+ (after - before).should < 1.1
186
+ (after - before).should > 1.0
187
+ end
188
+
189
+ it 'finds a device by its URN' do
190
+ pending
191
+ end
192
+
193
+ it 'finds a device by its UUID' do
194
+ pending
195
+ end
196
+
197
+ it 'finds a device by its UPnP device type' do
198
+ pending
199
+ end
200
+
201
+ it 'finds a device by its UPnP device type using a non-standard domain name' do
202
+ pending
203
+ end
204
+
205
+ it 'finds a service by its UPnP service type' do
206
+ pending
207
+ end
208
+
209
+ it 'find a service by its UPnP service type using a non-standard domain name' do
210
+ pending
211
+ end
212
+ =end
213
+ end
214
+