noam_lemma 0.2.1.2 → 0.2.1.3
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.
- 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
|