noam_lemma 0.2.1.2 → 0.2.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/LICENSE.txt +1 -1
- data/examples/free_guest_publisher.rb +11 -10
- data/examples/free_guest_subscriber.rb +19 -17
- data/examples/lemma_verification.rb +2 -0
- data/examples/publisher.rb +15 -12
- data/examples/subscriber.rb +18 -13
- data/lib/noam_lemma.rb +1 -1
- data/lib/noam_lemma/lemma.rb +11 -8
- data/lib/noam_lemma/listener.rb +9 -6
- data/lib/noam_lemma/message/marco.rb +7 -13
- data/lib/noam_lemma/player.rb +14 -30
- data/lib/noam_lemma/version.rb +1 -1
- data/noam_lemma.gemspec +1 -1
- data/spec/noam_lemma/lemma_spec.rb +18 -10
- data/spec/noam_lemma/listener_spec.rb +51 -0
- data/spec/noam_lemma/message/marco_spec.rb +31 -0
- data/spec/noam_lemma/message_filter_spec.rb +2 -2
- data/spec/noam_lemma/player_spec.rb +60 -0
- data/spec/support/fake_server.rb +1 -4
- metadata +14 -11
- data/lib/noam_lemma/beacon.rb +0 -36
- data/spec/noam_lemma/beacon_spec.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
N2QwNDk0YTRlNTFkYTBkMWUwYTgwZThkZGFmNjFjYTE1ZWQ0YjAwYw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ODZiODFiMDkyMDFhZjQxOWRmOGY5ODVmMjM3OGU4ZTE1YmY0NWExZA==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
OWNmNTYyOWNiMjM0ZmFkYWY2M2QzMmQ5NTk2MWQ1ZDUwZDk3YzI2MjU2ZjEy
|
10
|
+
N2E3MzFmZWU4NzVhOTVkOWZjYjkyYjE2MTllOTkxNTgwMTkxNDJmYmY0ZGY2
|
11
|
+
YTNkZjI4OTdiYTI0MWFkZDk3NTkwNWE0MTMxMjZhMWM4NWM2NTc=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ODE2ZDJkMTRmZmVhNDVhNTI3ZDY1MTY5Y2U5MzBiZjZiNWI2OGU4OTc3ZGZh
|
14
|
+
NTFkYmRkYmNjOGNmZThjNzdmODM5MThiYmMwZjU5ODAxMWRlNjJiN2JmMzBi
|
15
|
+
YWZmYzI3ODJiMDVhNDk0OTZiYjU5NWQ1YzRiNTA4MDYyZDJmZjI=
|
data/LICENSE.txt
CHANGED
@@ -2,17 +2,15 @@ require 'noam_lemma'
|
|
2
2
|
|
3
3
|
# This is an example of a Ruby Lemma that publishes message and *also* uses the
|
4
4
|
# "Guest" model of connection. This Lemma will advertise that it's available on
|
5
|
-
# the local network
|
6
|
-
# connection from the Lemma.
|
5
|
+
# the local network, without a specified room, and will only begin speaking
|
6
|
+
# messages once a server requests a connection from the Lemma.
|
7
7
|
|
8
8
|
publisher = Noam::Lemma.new('example-guest-publisher', [], ["e3"])
|
9
9
|
|
10
|
-
# Using the `
|
10
|
+
# Using the `discover` method asks the Lemma to announce it's presence and
|
11
11
|
# wait for a message from a server that may want to connect to it.
|
12
|
-
|
13
|
-
|
14
|
-
# the same as the Lemma's advertised room name will connect automatically.
|
15
|
-
publisher.advertise("")
|
12
|
+
|
13
|
+
publisher.discover
|
16
14
|
|
17
15
|
seq = 0
|
18
16
|
e = "e3"
|
@@ -20,12 +18,15 @@ loop do
|
|
20
18
|
# Construct a value to send with the event.
|
21
19
|
v = {"seq" => seq, "time" => Time.now.to_s}
|
22
20
|
|
23
|
-
# If `speak`
|
21
|
+
# If `speak` raises a Noam::Disconnected error, we're unable to speak the message likely because
|
24
22
|
# the socket has closed. The connection would have to be restarted.
|
25
|
-
|
26
|
-
|
23
|
+
begin
|
24
|
+
publisher.speak(e, v)
|
25
|
+
rescue Noam::Disconnected
|
26
|
+
puts "Disconnectd"
|
27
27
|
break
|
28
28
|
end
|
29
|
+
|
29
30
|
puts "Wrote: #{e} -> #{v.inspect}"
|
30
31
|
|
31
32
|
seq += 1
|
@@ -2,30 +2,32 @@ require 'noam_lemma'
|
|
2
2
|
|
3
3
|
# This is an example of a Ruby Lemma that publishes message and *also* uses the
|
4
4
|
# "Guest" model of connection. This Lemma will advertise that it's available on
|
5
|
-
# the local network
|
6
|
-
# requests a connection from the Lemma.
|
5
|
+
# the local network, without a specified room, and will only begin subscribing
|
6
|
+
# to messages once a server requests a connection from the Lemma.
|
7
7
|
|
8
8
|
subscriber = Noam::Lemma.new('example-guest-subscriber', ["e3"], [])
|
9
9
|
|
10
|
-
#
|
10
|
+
# The `hear` method sets a a block of code to be called when an event is heard
|
11
|
+
# from a specific event.
|
12
|
+
subscriber.hear('e3') do |message|
|
13
|
+
puts "Heard message"
|
14
|
+
puts "Event: #{message.event}"
|
15
|
+
puts "Value: #{message.value.inspect}"
|
16
|
+
end
|
17
|
+
|
18
|
+
# Using the `discover` method asks the Lemma to announce it's presence and
|
11
19
|
# wait for a message from a server that may want to connect to it.
|
12
|
-
|
13
|
-
|
14
|
-
# the same as the Lemma's advertised room name will connect automatically.
|
15
|
-
subscriber.advertise("")
|
20
|
+
|
21
|
+
subscriber.discover
|
16
22
|
|
17
23
|
loop do
|
18
|
-
# The `listen` method will return an
|
24
|
+
# The `listen` method will return an Message::Heard object once one is received by the
|
19
25
|
# Lemma. Until an event is heard, the `listen` method blocks.
|
20
|
-
|
21
|
-
|
22
|
-
# There's one special value that's returned from `listen`: the `:cancelled`
|
23
|
-
# symbol. If this shows up, it means some one else has called the `stop`
|
24
|
-
# method on the Lemma.
|
25
|
-
if :cancelled == m
|
26
|
-
puts "Done"
|
27
|
-
break
|
28
|
-
else
|
26
|
+
begin
|
27
|
+
m = subscriber.listen
|
29
28
|
puts "Read: #{m.event} -> #{m.value.inspect}"
|
29
|
+
rescue Noam::Disconnected
|
30
|
+
puts "Disconnected"
|
31
|
+
break
|
30
32
|
end
|
31
33
|
end
|
data/examples/publisher.rb
CHANGED
@@ -6,17 +6,15 @@ require 'noam_lemma'
|
|
6
6
|
# command should work:
|
7
7
|
#
|
8
8
|
# ruby -Ilib example/publisher.rb
|
9
|
-
#
|
10
|
-
# This example _will not_ work on the same machine running the Noam server as
|
11
|
-
# both programs need to bind to UDP port 1030.
|
12
9
|
|
13
10
|
publisher = Noam::Lemma.new('example-publisher', [], ["e1", "e2"])
|
14
11
|
|
15
|
-
# Using the `
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
|
12
|
+
# Using the `advertise` method asks the Lemma to announce it's presence and
|
13
|
+
# wait for a message from a server that may want to connect to it.
|
14
|
+
#
|
15
|
+
# The "local-test" parameter is the room name. Servers with a room name that's
|
16
|
+
# the same as the Lemma's advertised room name will connect automatically.
|
17
|
+
publisher.advertise("local-test")
|
20
18
|
|
21
19
|
seq = 0
|
22
20
|
loop do
|
@@ -33,12 +31,17 @@ loop do
|
|
33
31
|
|
34
32
|
# Attempt to speak the chosen event with the value. Note, the event is either
|
35
33
|
# "e1" or "e2" based on how rand() returned.
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
begin
|
35
|
+
publisher.speak(e, v)
|
36
|
+
|
37
|
+
# If `speak` returns a Noam::Disconnected error, we're unable to speak the
|
38
|
+
# message likely because the socket has closed. The connection
|
39
|
+
# would have to be restarted.
|
40
|
+
rescue Noam::Disconnected
|
41
|
+
puts "Disconnected"
|
40
42
|
break
|
41
43
|
end
|
44
|
+
|
42
45
|
puts "Wrote: #{e} -> #{v.inspect}"
|
43
46
|
|
44
47
|
seq += 1
|
data/examples/subscriber.rb
CHANGED
@@ -12,24 +12,29 @@ require 'noam_lemma'
|
|
12
12
|
|
13
13
|
subscriber = Noam::Lemma.new('example-subscriber', ["e1", "e2"], [])
|
14
14
|
|
15
|
-
#
|
15
|
+
# The `hear` method sets a a block of code to be called when an event is heard
|
16
|
+
# from a specific event.
|
17
|
+
subscriber.hear('e1') do |message|
|
18
|
+
puts "Heard message"
|
19
|
+
puts "Event: #{message.event}"
|
20
|
+
puts "Value: #{message.value.inspect}"
|
21
|
+
end
|
22
|
+
|
23
|
+
# Using the `advertise` method asks the Lemma to proactively try and discover a
|
16
24
|
# server to connect to on the local network. Once the server is discovered, it
|
17
25
|
# will connect and send a Noam 'register' message. When `discover` returns, the
|
18
26
|
# Lemma is ready to receive events.
|
19
|
-
subscriber.
|
27
|
+
subscriber.advertise("local-test")
|
20
28
|
|
21
29
|
loop do
|
22
|
-
# The `listen` method will return
|
23
|
-
# Lemma
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# symbol. If this shows up, it means some one else has called the `stop`
|
28
|
-
# method on the Lemma.
|
29
|
-
if :cancelled == m
|
30
|
-
puts "Done"
|
31
|
-
break
|
32
|
-
else
|
30
|
+
# The `listen` method will return a Message::Heard object once one is received by the
|
31
|
+
# Lemma, after calling any blocks associated with the event through the `hear`
|
32
|
+
# method. Until an event is heard, the `listen` method blocks.
|
33
|
+
begin
|
34
|
+
m = subscriber.listen
|
33
35
|
puts "Read: #{m.event} -> #{m.value.inspect}"
|
36
|
+
rescue Noam::Disconnected
|
37
|
+
puts "Disconnected"
|
38
|
+
break
|
34
39
|
end
|
35
40
|
end
|
data/lib/noam_lemma.rb
CHANGED
@@ -7,9 +7,9 @@ module Noam
|
|
7
7
|
DEVICE_TYPE = 'ruby-script'
|
8
8
|
|
9
9
|
class NoamThreadCancelled < Exception; end
|
10
|
+
class Disconnected < StandardError; end
|
10
11
|
end
|
11
12
|
|
12
|
-
require 'noam_lemma/beacon'
|
13
13
|
require 'noam_lemma/lemma'
|
14
14
|
require 'noam_lemma/listener'
|
15
15
|
require 'noam_lemma/message'
|
data/lib/noam_lemma/lemma.rb
CHANGED
@@ -13,32 +13,35 @@ module Noam
|
|
13
13
|
initialize_message_filter(hears)
|
14
14
|
end
|
15
15
|
|
16
|
-
def discover(beacon = nil)
|
17
|
-
beacon ||= Beacon.discover
|
18
|
-
start(beacon.host, beacon.port)
|
19
|
-
end
|
20
|
-
|
21
16
|
def advertise(room_name)
|
22
17
|
marco = Noam::Message::Marco.new(room_name, @name)
|
23
18
|
polo = marco.start
|
24
19
|
start(polo.host, polo.port)
|
25
20
|
end
|
26
21
|
|
22
|
+
def discover
|
23
|
+
advertise('')
|
24
|
+
end
|
25
|
+
|
27
26
|
def hear(event_name, &block)
|
28
27
|
@message_filter.hear(event_name, &block)
|
29
28
|
end
|
30
29
|
|
31
30
|
def speak(event, value)
|
32
|
-
if @player
|
31
|
+
if @player.connected?
|
33
32
|
@player.put(Noam::Message::Playable.new(@name, event, value))
|
34
33
|
true
|
35
34
|
else
|
36
|
-
|
35
|
+
raise Noam::Disconnected.new("Player disconnected")
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
40
39
|
def listen
|
41
|
-
@
|
40
|
+
if @listener.connected?
|
41
|
+
@message_filter.receive(@listener.take)
|
42
|
+
else
|
43
|
+
raise Noam::Disconnected.new("Listener disconnected")
|
44
|
+
end
|
42
45
|
end
|
43
46
|
|
44
47
|
def stop
|
data/lib/noam_lemma/listener.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'thread'
|
1
|
+
require 'thread'
|
2
2
|
|
3
3
|
module Noam
|
4
4
|
class Listener
|
@@ -21,6 +21,10 @@ module Noam
|
|
21
21
|
@thread.join
|
22
22
|
end
|
23
23
|
|
24
|
+
def connected?
|
25
|
+
!@disconnected
|
26
|
+
end
|
27
|
+
|
24
28
|
private
|
25
29
|
|
26
30
|
def manage_queue_on_thread
|
@@ -40,16 +44,13 @@ module Noam
|
|
40
44
|
client.close
|
41
45
|
end
|
42
46
|
|
43
|
-
if exiting?
|
44
|
-
@queue.push(:cancelled)
|
45
|
-
break
|
46
|
-
end
|
47
|
+
break if exiting?
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
51
|
def listen_for_connection
|
51
52
|
timeout_sec = 0.1
|
52
|
-
available_ios = select([@server], nil, nil, timeout_sec)
|
53
|
+
available_ios = IO.select([@server], nil, nil, timeout_sec)
|
53
54
|
@server.accept if available_ios
|
54
55
|
end
|
55
56
|
|
@@ -63,6 +64,8 @@ module Noam
|
|
63
64
|
end
|
64
65
|
rescue IO::WaitReadable
|
65
66
|
retry unless exiting?
|
67
|
+
rescue EOFError
|
68
|
+
@disconnected = true
|
66
69
|
end
|
67
70
|
end
|
68
71
|
|
@@ -13,23 +13,17 @@ module Noam
|
|
13
13
|
|
14
14
|
def start
|
15
15
|
bcast_socket = UDPSocket.new
|
16
|
-
reply_socket = UDPSocket.new
|
17
|
-
reply_socket.bind("0.0.0.0", 0)
|
18
16
|
|
19
|
-
|
20
|
-
bcast_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
|
17
|
+
bcast_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
|
21
18
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
19
|
+
loop do
|
20
|
+
bcast_socket.send(noam_encode, 0, "255.255.255.255", Noam::BEACON_PORT)
|
21
|
+
if message_received?(bcast_socket)
|
22
|
+
break
|
27
23
|
end
|
28
|
-
|
29
|
-
get_polo_response(bcast_socket)
|
30
|
-
ensure
|
31
|
-
reply_socket.close
|
32
24
|
end
|
25
|
+
|
26
|
+
get_polo_response(bcast_socket)
|
33
27
|
end
|
34
28
|
|
35
29
|
def noam_encode
|
data/lib/noam_lemma/player.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'thread'
|
1
|
+
require 'thread'
|
2
2
|
|
3
3
|
module Noam
|
4
4
|
class NoamPlayerException < Exception; end
|
@@ -20,13 +20,16 @@ module Noam
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def stop
|
23
|
-
put(:
|
23
|
+
put(:exit)
|
24
24
|
@thread.join
|
25
25
|
end
|
26
26
|
|
27
27
|
def stop!
|
28
|
-
|
29
|
-
|
28
|
+
@thread.exit
|
29
|
+
end
|
30
|
+
|
31
|
+
def connected?
|
32
|
+
!@disconnected
|
30
33
|
end
|
31
34
|
|
32
35
|
private
|
@@ -37,42 +40,23 @@ module Noam
|
|
37
40
|
loop do
|
38
41
|
message = @queue.pop
|
39
42
|
break if exit?(message)
|
40
|
-
|
43
|
+
print_message(message)
|
41
44
|
end
|
45
|
+
rescue Errno::EPIPE
|
46
|
+
@disconnected = true
|
42
47
|
ensure
|
43
48
|
@socket.close
|
44
49
|
end
|
45
50
|
end
|
46
51
|
end
|
47
52
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
finish_queue
|
52
|
-
when :hard_exit
|
53
|
-
else
|
54
|
-
@socket.print(message.noam_encode)
|
55
|
-
@socket.flush
|
56
|
-
end
|
53
|
+
def print_message(message)
|
54
|
+
@socket.print(message.noam_encode)
|
55
|
+
@socket.flush
|
57
56
|
end
|
58
57
|
|
59
58
|
def exit?(message)
|
60
|
-
message == :
|
61
|
-
end
|
62
|
-
|
63
|
-
def finish_queue
|
64
|
-
queue_to_array.each do |message|
|
65
|
-
@socket.print(message.noam_encode)
|
66
|
-
@socket.flush
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def queue_to_array
|
71
|
-
result = []
|
72
|
-
while(@queue.size > 0) do
|
73
|
-
result << @queue.pop
|
74
|
-
end
|
75
|
-
result
|
59
|
+
message == :exit
|
76
60
|
end
|
77
61
|
end
|
78
62
|
end
|
data/lib/noam_lemma/version.rb
CHANGED
data/noam_lemma.gemspec
CHANGED
@@ -21,6 +21,6 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_dependency "require_all"
|
22
22
|
spec.add_development_dependency "bundler", "~> 1.3"
|
23
23
|
spec.add_development_dependency "rake", "~> 10.3"
|
24
|
-
spec.add_development_dependency "rspec", "~>
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.1.0"
|
25
25
|
spec.add_development_dependency "mocha", "~> 1.1"
|
26
26
|
end
|
@@ -49,10 +49,14 @@ describe Noam::Lemma do
|
|
49
49
|
|
50
50
|
context "with server communication" do
|
51
51
|
let(:server) { FakeManager.server }
|
52
|
+
let(:lemma) { Noam::Lemma.new("Example Lemma") }
|
52
53
|
|
53
54
|
before(:each) do
|
55
|
+
Noam::Message::Marco.any_instance.stubs(:start).returns(
|
56
|
+
Noam::Message::Polo.new('0.0.0.0', NoamTest::FakeServer::PORT)
|
57
|
+
)
|
54
58
|
FakeManager.start
|
55
|
-
lemma.
|
59
|
+
lemma.advertise('fake_beacon')
|
56
60
|
sleep(SERVER_DELAY)
|
57
61
|
end
|
58
62
|
|
@@ -61,9 +65,7 @@ describe Noam::Lemma do
|
|
61
65
|
FakeManager.stop
|
62
66
|
end
|
63
67
|
|
64
|
-
describe "#
|
65
|
-
let(:lemma) { Noam::Lemma.new("Example Lemma") }
|
66
|
-
|
68
|
+
describe "#advertise" do
|
67
69
|
it "sends a registration message" do
|
68
70
|
server.clients.length.should == 1
|
69
71
|
server.clients.first.port.should be_an(Integer)
|
@@ -77,11 +79,9 @@ describe Noam::Lemma do
|
|
77
79
|
end
|
78
80
|
|
79
81
|
describe "#hear" do
|
80
|
-
let(:lemma) { Noam::Lemma.new("Example Lemma") }
|
81
|
-
|
82
82
|
it "registers messages with blocks" do
|
83
83
|
message = nil
|
84
|
-
lemma.hear("example_event") {|event| message = event}
|
84
|
+
lemma.hear("example_event") { |event| message = event }
|
85
85
|
send_message_from_server("example_event")
|
86
86
|
lemma.listen
|
87
87
|
message.event.should == "example_event"
|
@@ -89,12 +89,15 @@ describe Noam::Lemma do
|
|
89
89
|
end
|
90
90
|
|
91
91
|
describe "#speak" do
|
92
|
-
let(:lemma) { Noam::Lemma.new("Example Lemma") }
|
93
|
-
|
94
92
|
it "sends a message to the server" do
|
95
93
|
lemma.speak("an event", "some value")
|
96
94
|
sleep(SERVER_DELAY)
|
97
|
-
server.messages.map {|m| m[2]}.include?("an event").should
|
95
|
+
server.messages.map { |m| m[2] }.include?("an event").should be_truthy
|
96
|
+
end
|
97
|
+
|
98
|
+
it "raise a disconnected error if the player is not connected" do
|
99
|
+
lemma.player.stubs(:connected?).returns(false)
|
100
|
+
expect { lemma.speak('event', 'value') }.to raise_error(Noam::Disconnected)
|
98
101
|
end
|
99
102
|
end
|
100
103
|
|
@@ -108,6 +111,11 @@ describe Noam::Lemma do
|
|
108
111
|
message.event.should == "example_event"
|
109
112
|
message.value.should == "noam event"
|
110
113
|
end
|
114
|
+
|
115
|
+
it "raises a disconnected error if the listener is not connected" do
|
116
|
+
lemma.listener.stubs(:connected?).returns(false)
|
117
|
+
expect { lemma.listen }.to raise_error(Noam::Disconnected)
|
118
|
+
end
|
111
119
|
end
|
112
120
|
|
113
121
|
def send_message_from_server(source = "test-server", value = "noam event", message)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
describe Noam::Listener do
|
2
|
+
def make_message(message)
|
3
|
+
['test', 'source', 'event', message].to_json
|
4
|
+
end
|
5
|
+
|
6
|
+
class MockTcpSocket
|
7
|
+
def queue
|
8
|
+
@queue ||= Queue.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def read_nonblock(size)
|
12
|
+
if size == ::Noam::Message::MESSAGE_LENGTH_STRING_SIZE
|
13
|
+
1
|
14
|
+
else
|
15
|
+
queue.pop
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def close; end
|
20
|
+
end
|
21
|
+
|
22
|
+
let!(:listener) { described_class.new }
|
23
|
+
let(:mock_socket) { MockTcpSocket.new }
|
24
|
+
|
25
|
+
before do
|
26
|
+
TCPServer.any_instance.stubs(:accept).returns(mock_socket)
|
27
|
+
IO.stubs(:select).returns(true)
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#connected?' do
|
31
|
+
it 'returns true if the connection is open' do
|
32
|
+
mock_socket.queue << make_message('message')
|
33
|
+
listener.stop
|
34
|
+
expect(listener.connected?).to be_truthy
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns false if a read has failed' do
|
38
|
+
mock_socket.stubs(:read_nonblock).raises(EOFError.new)
|
39
|
+
listener.stop
|
40
|
+
expect(listener.connected?).to be_falsey
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#take' do
|
45
|
+
it 'returns the next message from the queue' do
|
46
|
+
mock_socket.queue << make_message('message')
|
47
|
+
listener.stop
|
48
|
+
expect(listener.take.value).to eq('message')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
describe Noam::Message::Marco do
|
2
|
+
let(:marco) { described_class.new('test_room', 'Test Lemma') }
|
3
|
+
let(:message) { ['message', 'room', 1234].to_json }
|
4
|
+
let(:sockaddr) { [1, 2, 3, 4] }
|
5
|
+
|
6
|
+
before do
|
7
|
+
described_class.any_instance.stubs(:message_received?).returns(true)
|
8
|
+
UDPSocket.any_instance.stubs(:send)
|
9
|
+
UDPSocket.any_instance.stubs(:recvfrom).returns([message, sockaddr])
|
10
|
+
end
|
11
|
+
|
12
|
+
it "sends a marco message to the server" do
|
13
|
+
UDPSocket.any_instance.expects(:send).with(
|
14
|
+
["marco", 'Test Lemma', 'test_room', Noam::DEVICE_TYPE, Noam::VERSION].to_json,
|
15
|
+
0,
|
16
|
+
'255.255.255.255',
|
17
|
+
Noam::BEACON_PORT
|
18
|
+
)
|
19
|
+
marco.start
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns a polo with the server's host" do
|
23
|
+
polo = marco.start
|
24
|
+
expect(polo.host).to eq(3)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns a polo with the server's port" do
|
28
|
+
polo = marco.start
|
29
|
+
expect(polo.port).to eq(1234)
|
30
|
+
end
|
31
|
+
end
|
@@ -40,8 +40,8 @@ describe Noam::MessageFilter do
|
|
40
40
|
filter.hear("example_event") {|message| example_received = true}
|
41
41
|
filter.hear("sample_event") {|message| sample_received = true}
|
42
42
|
filter.receive(stub_message("example_event"))
|
43
|
-
example_received.should
|
44
|
-
sample_received.should
|
43
|
+
example_received.should be_truthy
|
44
|
+
sample_received.should be_falsy
|
45
45
|
end
|
46
46
|
|
47
47
|
it "returns the given message" do
|
@@ -0,0 +1,60 @@
|
|
1
|
+
describe Noam::Player do
|
2
|
+
def make_message(message)
|
3
|
+
Noam::Message::Playable.new('host', 'event', message)
|
4
|
+
end
|
5
|
+
|
6
|
+
class MockTcpSocket
|
7
|
+
def published_messages
|
8
|
+
@published_messages ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def print(message)
|
12
|
+
published_messages << message
|
13
|
+
end
|
14
|
+
|
15
|
+
def close; end
|
16
|
+
|
17
|
+
def flush; end
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:player) { described_class.new('0.0.0.0', 1234) }
|
21
|
+
let(:mock_socket) { MockTcpSocket.new }
|
22
|
+
|
23
|
+
before do
|
24
|
+
TCPSocket.stubs(:new).returns(mock_socket)
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "connected?" do
|
28
|
+
it "returns true if the socket is open" do
|
29
|
+
player.stop
|
30
|
+
expect(player.connected?).to be_truthy
|
31
|
+
end
|
32
|
+
|
33
|
+
it "returns false if a write to the socket has failed" do
|
34
|
+
mock_socket.stubs(:print).raises(Errno::EPIPE.new)
|
35
|
+
player.put(make_message("message"))
|
36
|
+
player.stop
|
37
|
+
expect(player.connected?).to be_falsey
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "stop" do
|
42
|
+
it "publishes the remaning messages in the queue" do
|
43
|
+
100.times do
|
44
|
+
player.put(make_message("message"))
|
45
|
+
end
|
46
|
+
player.stop
|
47
|
+
expect(mock_socket.published_messages.size).to eq(100)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "stop!" do
|
52
|
+
it "does not finish the queue" do
|
53
|
+
100.times do
|
54
|
+
player.put(make_message("message"))
|
55
|
+
end
|
56
|
+
player.stop!
|
57
|
+
expect(mock_socket.published_messages.size).to be < 100
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/spec/support/fake_server.rb
CHANGED
@@ -20,9 +20,6 @@ module NoamTest
|
|
20
20
|
@thread = Thread.new do |t|
|
21
21
|
begin
|
22
22
|
loop do
|
23
|
-
msg = ["beacon", "fake_beacon", NoamTest::FakeServer::PORT].to_json
|
24
|
-
@socket.send(msg, 0, "255.255.255.255", Noam::BEACON_PORT)
|
25
|
-
|
26
23
|
# This is normally at 5.0 seconds, but we run faster in order to
|
27
24
|
# make tests faster.
|
28
25
|
sleep(LOOP_DELAY)
|
@@ -105,7 +102,7 @@ module NoamTest
|
|
105
102
|
@client_host = @sock.peeraddr[2]
|
106
103
|
@queue = Queue.new
|
107
104
|
end
|
108
|
-
|
105
|
+
|
109
106
|
def start
|
110
107
|
@thread = Thread.new do |t|
|
111
108
|
begin
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: noam_lemma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.1.
|
4
|
+
version: 0.2.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Van Enk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: require_all
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - '>='
|
17
|
+
- - ! '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - '>='
|
24
|
+
- - ! '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 3.1.0
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 3.1.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: mocha
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,7 +100,6 @@ files:
|
|
100
100
|
- examples/publisher.rb
|
101
101
|
- examples/subscriber.rb
|
102
102
|
- lib/noam_lemma.rb
|
103
|
-
- lib/noam_lemma/beacon.rb
|
104
103
|
- lib/noam_lemma/lemma.rb
|
105
104
|
- lib/noam_lemma/listener.rb
|
106
105
|
- lib/noam_lemma/message.rb
|
@@ -113,13 +112,15 @@ files:
|
|
113
112
|
- lib/noam_lemma/player.rb
|
114
113
|
- lib/noam_lemma/version.rb
|
115
114
|
- noam_lemma.gemspec
|
116
|
-
- spec/noam_lemma/beacon_spec.rb
|
117
115
|
- spec/noam_lemma/lemma_spec.rb
|
116
|
+
- spec/noam_lemma/listener_spec.rb
|
118
117
|
- spec/noam_lemma/message/heard_spec.rb
|
118
|
+
- spec/noam_lemma/message/marco_spec.rb
|
119
119
|
- spec/noam_lemma/message/playable_spec.rb
|
120
120
|
- spec/noam_lemma/message/register_spec.rb
|
121
121
|
- spec/noam_lemma/message_filter_spec.rb
|
122
122
|
- spec/noam_lemma/message_spec.rb
|
123
|
+
- spec/noam_lemma/player_spec.rb
|
123
124
|
- spec/spec_helper.rb
|
124
125
|
- spec/support/fake_server.rb
|
125
126
|
homepage: https://github.com/noam-io/lemma-ruby
|
@@ -132,12 +133,12 @@ require_paths:
|
|
132
133
|
- lib
|
133
134
|
required_ruby_version: !ruby/object:Gem::Requirement
|
134
135
|
requirements:
|
135
|
-
- - '>='
|
136
|
+
- - ! '>='
|
136
137
|
- !ruby/object:Gem::Version
|
137
138
|
version: '0'
|
138
139
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
140
|
requirements:
|
140
|
-
- - '>='
|
141
|
+
- - ! '>='
|
141
142
|
- !ruby/object:Gem::Version
|
142
143
|
version: '0'
|
143
144
|
requirements: []
|
@@ -147,12 +148,14 @@ signing_key:
|
|
147
148
|
specification_version: 4
|
148
149
|
summary: A lemma factory for the Noam pub-sub system.
|
149
150
|
test_files:
|
150
|
-
- spec/noam_lemma/beacon_spec.rb
|
151
151
|
- spec/noam_lemma/lemma_spec.rb
|
152
|
+
- spec/noam_lemma/listener_spec.rb
|
152
153
|
- spec/noam_lemma/message/heard_spec.rb
|
154
|
+
- spec/noam_lemma/message/marco_spec.rb
|
153
155
|
- spec/noam_lemma/message/playable_spec.rb
|
154
156
|
- spec/noam_lemma/message/register_spec.rb
|
155
157
|
- spec/noam_lemma/message_filter_spec.rb
|
156
158
|
- spec/noam_lemma/message_spec.rb
|
159
|
+
- spec/noam_lemma/player_spec.rb
|
157
160
|
- spec/spec_helper.rb
|
158
161
|
- spec/support/fake_server.rb
|
data/lib/noam_lemma/beacon.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
module Noam
|
2
|
-
class Beacon
|
3
|
-
attr_reader :name, :host, :port
|
4
|
-
|
5
|
-
def initialize(name, host, port)
|
6
|
-
@name = name
|
7
|
-
@host = host
|
8
|
-
@port = port
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.discover(net = "0.0.0.0")
|
12
|
-
socket = UDPSocket.new
|
13
|
-
begin
|
14
|
-
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
|
15
|
-
socket.bind(net, Noam::BEACON_PORT)
|
16
|
-
|
17
|
-
raise "Didn't see beacon after #{WAIT_TIME} seconds." unless message_received?(socket)
|
18
|
-
|
19
|
-
data, addr = socket.recvfrom(MAX_RESPONSE_LENGTH)
|
20
|
-
parsed_data = JSON.parse(data)
|
21
|
-
Beacon.new(parsed_data[1], addr[2], parsed_data[2])
|
22
|
-
ensure
|
23
|
-
socket.close
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
MAX_RESPONSE_LENGTH = 1600
|
30
|
-
WAIT_TIME = 10.0
|
31
|
-
|
32
|
-
def self.message_received?(socket)
|
33
|
-
IO.select([socket], [], [], WAIT_TIME) != nil
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
describe Noam::Beacon do
|
2
|
-
describe "#new" do
|
3
|
-
it "creates a new beacon" do
|
4
|
-
beacon = Noam::Beacon.new(:name, :host, :noam)
|
5
|
-
beacon.name.should == :name
|
6
|
-
beacon.host.should == :host
|
7
|
-
beacon.port.should == :noam
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
describe "::discover" do
|
12
|
-
before do
|
13
|
-
FakeManager.start
|
14
|
-
end
|
15
|
-
|
16
|
-
after do
|
17
|
-
FakeManager.stop
|
18
|
-
end
|
19
|
-
|
20
|
-
it "creates a Beacon based on server beacons" do
|
21
|
-
beacon = Noam::Beacon.discover
|
22
|
-
beacon.should be_a(Noam::Beacon)
|
23
|
-
beacon.port.should == NoamTest::FakeServer::PORT
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|