spnet 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/.document +3 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.yardopts +2 -0
- data/ChangeLog.rdoc +4 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +20 -0
- data/README.md +11 -0
- data/README.rdoc +27 -0
- data/Rakefile +33 -0
- data/lib/spnet/block.rb +42 -0
- data/lib/spnet/control_message.rb +52 -0
- data/lib/spnet/message.rb +25 -0
- data/lib/spnet/message_in_port.rb +43 -0
- data/lib/spnet/message_out_port.rb +56 -0
- data/lib/spnet/signal_in_port.rb +60 -0
- data/lib/spnet/signal_out_port.rb +54 -0
- data/lib/spnet/version.rb +4 -0
- data/lib/spnet.rb +9 -0
- data/spec/block_spec.rb +38 -0
- data/spec/control_message_spec.rb +40 -0
- data/spec/message_in_port_spec.rb +17 -0
- data/spec/message_out_port_spec.rb +57 -0
- data/spec/message_spec.rb +11 -0
- data/spec/signal_in_port_spec.rb +50 -0
- data/spec/signal_out_port_spec.rb +81 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/spnetwork_spec.rb +8 -0
- data/spnet.gemspec +29 -0
- metadata +188 -0
data/.document
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
<<<<<<< HEAD
|
4
|
+
=======
|
5
|
+
Gemfile.lock
|
6
|
+
>>>>>>> d63c31673acdeec0c776db6fc0cb787ff73a0d7a
|
7
|
+
.bundle
|
8
|
+
.config
|
9
|
+
coverage
|
10
|
+
InstalledFiles
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
|
19
|
+
# YARD artifacts
|
20
|
+
.yardoc
|
21
|
+
_yardoc
|
22
|
+
doc/
|
data/.rspec
ADDED
data/.yardopts
ADDED
data/ChangeLog.rdoc
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 James Tunnell
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
= spnet
|
2
|
+
|
3
|
+
* {Homepage}[https://rubygems.org/gems/spnet]
|
4
|
+
* {Documentation}[http://rubydoc.info/gems/spnet/frames]
|
5
|
+
* {Email}[mailto:jamestunnell at lavabit.com]
|
6
|
+
|
7
|
+
== Description
|
8
|
+
|
9
|
+
TODO: Description
|
10
|
+
|
11
|
+
== Features
|
12
|
+
|
13
|
+
== Examples
|
14
|
+
|
15
|
+
require 'spnet'
|
16
|
+
|
17
|
+
== Requirements
|
18
|
+
|
19
|
+
== Install
|
20
|
+
|
21
|
+
$ gem install spnet
|
22
|
+
|
23
|
+
== Copyright
|
24
|
+
|
25
|
+
Copyright (c) 2013 James Tunnell
|
26
|
+
|
27
|
+
See LICENSE.txt for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler'
|
7
|
+
rescue LoadError => e
|
8
|
+
warn e.message
|
9
|
+
warn "Run `gem install bundler` to install Bundler."
|
10
|
+
exit -1
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
Bundler.setup(:development)
|
15
|
+
rescue Bundler::BundlerError => e
|
16
|
+
warn e.message
|
17
|
+
warn "Run `bundle install` to install missing gems."
|
18
|
+
exit e.status_code
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake'
|
22
|
+
|
23
|
+
require 'rspec/core/rake_task'
|
24
|
+
RSpec::Core::RakeTask.new
|
25
|
+
|
26
|
+
task :test => :spec
|
27
|
+
task :default => :spec
|
28
|
+
|
29
|
+
require 'yard'
|
30
|
+
YARD::Rake::YardocTask.new
|
31
|
+
task :doc => :yard
|
32
|
+
|
33
|
+
require "bundler/gem_tasks"
|
data/lib/spnet/block.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
module SPNet
|
3
|
+
class Block
|
4
|
+
include Hashmake::HashMakeable
|
5
|
+
|
6
|
+
attr_reader :name, :signal_in_ports, :signal_out_ports, :message_in_ports, :message_out_ports
|
7
|
+
|
8
|
+
DO_NOTHING = ->(){}
|
9
|
+
|
10
|
+
HASHED_ARG_SPECS = [
|
11
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
|
12
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :algorithm, :type => Proc, :default => DO_NOTHING),
|
13
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :signal_in_ports, :type => SignalInPort, :array => true, :default => ->(){ Array.new } ),
|
14
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :signal_out_ports, :type => SignalOutPort, :array => true, :default => ->(){ Array.new }),
|
15
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :message_in_ports, :type => MessageInPort, :array => true, :default => ->(){ Array.new }),
|
16
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :message_out_ports, :type => MessageOutPort, :array => true, :default => ->(){ Array.new })
|
17
|
+
]
|
18
|
+
|
19
|
+
def initialize args = {}
|
20
|
+
hash_make Block::HASHED_ARG_SPECS, args
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_ports name, ignore_case = true
|
24
|
+
matches = (@signal_in_ports + @signal_out_ports + @message_in_ports + @message_out_ports).select do |port|
|
25
|
+
if ignore_case
|
26
|
+
port.name.casecmp(name) == 0
|
27
|
+
else
|
28
|
+
port.name == name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
return matches
|
32
|
+
end
|
33
|
+
|
34
|
+
def find_first_port name, ignore_case = true
|
35
|
+
return find_ports(name, ignore_case).first
|
36
|
+
end
|
37
|
+
|
38
|
+
def step count
|
39
|
+
@algorithm.call count
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'hashmake'
|
2
|
+
|
3
|
+
module SPNet
|
4
|
+
class ControlMessage < Message
|
5
|
+
|
6
|
+
include Hashmake::HashMakeable
|
7
|
+
|
8
|
+
GET = :controlMessageSubtypeGet
|
9
|
+
SET = :controlMessageSubtypeSet
|
10
|
+
|
11
|
+
SUBTYPES = [
|
12
|
+
GET,
|
13
|
+
SET
|
14
|
+
]
|
15
|
+
|
16
|
+
HASHED_ARGS_SPECS = [
|
17
|
+
Hashmake::HashedArg.new(:reqd => true, :key => :subtype, :type => Symbol, :validator => ->(a){ SUBTYPES.include?(a) } )
|
18
|
+
]
|
19
|
+
|
20
|
+
attr_reader :subtype
|
21
|
+
|
22
|
+
def initialize hashed_args
|
23
|
+
hash_make ControlMessage::HASHED_ARGS_SPECS, hashed_args
|
24
|
+
super_hashed_args = hashed_args.merge! :type => Message::CONTROL
|
25
|
+
super(super_hashed_args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.make_handler get_handler, set_handler
|
29
|
+
handler = lambda do |message|
|
30
|
+
raise ArgumentError, "message is not a ControlMessage" unless message.is_a?(ControlMessage)
|
31
|
+
|
32
|
+
if message.subtype == GET
|
33
|
+
return get_handler.call message
|
34
|
+
elsif message.subtype == SET
|
35
|
+
return set_handler.call message
|
36
|
+
else
|
37
|
+
raise ArgumentError, "message subtype #{message.subtype} is not valid"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
return handler
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.make_set_message data
|
45
|
+
ControlMessage.new :subtype => SET, :data => data
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.make_get_message
|
49
|
+
ControlMessage.new :subtype => GET
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'hashmake'
|
2
|
+
|
3
|
+
module SPNet
|
4
|
+
class Message
|
5
|
+
|
6
|
+
include Hashmake::HashMakeable
|
7
|
+
|
8
|
+
CONTROL = :messageTypeControl
|
9
|
+
COMMAND = :messageTypeCommand
|
10
|
+
|
11
|
+
TYPES = [ CONTROL, COMMAND ]
|
12
|
+
|
13
|
+
HASHED_ARGS_SPECS = [
|
14
|
+
Hashmake::HashedArg.new(:reqd => true, :key => :type, :type => Symbol, :validator => ->(a){ TYPES.include?(a) } ),
|
15
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :data, :type => Object, :default => nil),
|
16
|
+
]
|
17
|
+
|
18
|
+
attr_accessor :data
|
19
|
+
attr_reader :type
|
20
|
+
|
21
|
+
def initialize hashed_args = {}
|
22
|
+
hash_make Message::HASHED_ARGS_SPECS, hashed_args
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'hashmake'
|
2
|
+
|
3
|
+
module SPNet
|
4
|
+
class MessageInPort
|
5
|
+
include Hashmake::HashMakeable
|
6
|
+
|
7
|
+
DEFAULT_VALIDATOR = ->(a){ true }
|
8
|
+
|
9
|
+
ARG_SPECS = [
|
10
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
|
11
|
+
Hashmake::HashedArg.new(:reqd => true, :key => :processor, :type => Proc),
|
12
|
+
Hashmake::HashedArg.new(:reqd => true, :key => :message_type, :type => Symbol, :validator => ->(a){ Message::TYPES.include?(a) })
|
13
|
+
]
|
14
|
+
|
15
|
+
attr_reader :name, :link
|
16
|
+
|
17
|
+
def initialize args
|
18
|
+
hash_make MessageInPort::ARG_SPECS, args
|
19
|
+
@queue = []
|
20
|
+
@link = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def recv_message message
|
24
|
+
raise ArgumentError, "message is not a Message" unless message.is_a?(Message)
|
25
|
+
if message.type == @message_type
|
26
|
+
return @processor.call(message)
|
27
|
+
else
|
28
|
+
raise ArgumentError, "message.type #{message.type} is not supported on this port"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def clear_link
|
34
|
+
@link = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_link link
|
38
|
+
raise ArgumentError, "link #{link} is not a MessageOutPort" unless link.is_a?(MessageOutPort)
|
39
|
+
@link = link
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'hashmake'
|
3
|
+
|
4
|
+
module SPNet
|
5
|
+
class MessageOutPort
|
6
|
+
include Hashmake::HashMakeable
|
7
|
+
|
8
|
+
ARG_SPECS = [
|
9
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
|
10
|
+
]
|
11
|
+
|
12
|
+
attr_reader :name, :links
|
13
|
+
|
14
|
+
def initialize args = {}
|
15
|
+
hash_make MessageOutPort::ARG_SPECS, args
|
16
|
+
@links = Set.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def send_message message
|
20
|
+
rvs = []
|
21
|
+
@links.each do |link|
|
22
|
+
rvs.push link.recv_message message
|
23
|
+
end
|
24
|
+
return rvs
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_link link
|
28
|
+
raise ArgumentError, "link #{link} is not a MessageInPort" unless link.is_a?(MessageInPort)
|
29
|
+
raise ArgumentError, "link #{link} is already linked to a MessageInPort" if link.link
|
30
|
+
@links.add link
|
31
|
+
link.set_link self
|
32
|
+
end
|
33
|
+
|
34
|
+
def remove_link link
|
35
|
+
raise ArgumentError, "link #{link} is not a MessageInPort" unless link.is_a?(MessageInPort)
|
36
|
+
raise ArgumentError, "@links does not include link #{link}" unless @links.include? link
|
37
|
+
@links.delete link
|
38
|
+
link.clear_link
|
39
|
+
end
|
40
|
+
|
41
|
+
def remove_bad_links
|
42
|
+
marked_for_removal = []
|
43
|
+
|
44
|
+
@links.each do |link|
|
45
|
+
bad = (link.link == nil) or (link.link != self)
|
46
|
+
if bad
|
47
|
+
marked_for_removal.push link
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
marked_for_removal.each do |link|
|
52
|
+
@links.delete link
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'hashmake'
|
2
|
+
|
3
|
+
module SPNet
|
4
|
+
class SignalInPort
|
5
|
+
include Hashmake::HashMakeable
|
6
|
+
|
7
|
+
DEFAULT_LIMITS = (-Float::MAX..Float::MAX)
|
8
|
+
|
9
|
+
ARG_SPECS = [
|
10
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
|
11
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :limits, :type => Range, :default => DEFAULT_LIMITS)
|
12
|
+
]
|
13
|
+
|
14
|
+
attr_reader :name, :limits, :link, :queue
|
15
|
+
|
16
|
+
def make_range_limiter range
|
17
|
+
return lambda do |input|
|
18
|
+
if input < range.first
|
19
|
+
return range.first
|
20
|
+
elsif input > range.last
|
21
|
+
return range.last
|
22
|
+
else
|
23
|
+
return input
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize args = {}
|
29
|
+
hash_make SignalInPort::ARG_SPECS, args
|
30
|
+
@queue = []
|
31
|
+
@skip_limiting = (@limits == DEFAULT_LIMITS)
|
32
|
+
@limiter = make_range_limiter @limits
|
33
|
+
@link = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def enqueue_values values
|
37
|
+
unless @skip_limiting
|
38
|
+
for i in 0...values.count
|
39
|
+
values[i] = @limiter.call(values[i])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
@queue.concat values
|
44
|
+
end
|
45
|
+
|
46
|
+
def dequeue_values count = @queue.count
|
47
|
+
raise ArgumentError, "count is greater than @queue.count" if count > @queue.count
|
48
|
+
@queue.slice!(0...count)
|
49
|
+
end
|
50
|
+
|
51
|
+
def clear_link
|
52
|
+
@link = nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def set_link link
|
56
|
+
raise ArgumentError, "link #{link} is not a SignalOutPort" unless link.is_a?(SignalOutPort)
|
57
|
+
@link = link
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'hashmake'
|
3
|
+
|
4
|
+
module SPNet
|
5
|
+
class SignalOutPort
|
6
|
+
include Hashmake::HashMakeable
|
7
|
+
|
8
|
+
ARG_SPECS = [
|
9
|
+
Hashmake::HashedArg.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
|
10
|
+
]
|
11
|
+
|
12
|
+
attr_reader :name, :links
|
13
|
+
|
14
|
+
def initialize args = {}
|
15
|
+
hash_make SignalOutPort::ARG_SPECS, args
|
16
|
+
@links = Set.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def send_values values
|
20
|
+
@links.each do |link|
|
21
|
+
link.enqueue_values values
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_link link
|
26
|
+
raise ArgumentError, "link #{link} is not a SignalInPort" unless link.is_a?(SignalInPort)
|
27
|
+
raise ArgumentError, "link #{link} is already linked to a SignalOutPort" if link.link
|
28
|
+
@links.add link
|
29
|
+
link.set_link self
|
30
|
+
end
|
31
|
+
|
32
|
+
def remove_link link
|
33
|
+
raise ArgumentError, "link #{link} is not a SignalInPort" unless link.is_a?(SignalInPort)
|
34
|
+
raise ArgumentError, "@links does not include link #{link}" unless @links.include? link
|
35
|
+
@links.delete link
|
36
|
+
link.clear_link
|
37
|
+
end
|
38
|
+
|
39
|
+
def remove_bad_links
|
40
|
+
marked_for_removal = []
|
41
|
+
|
42
|
+
@links.each do |link|
|
43
|
+
bad = (link.link == nil) or (link.link != self)
|
44
|
+
if bad
|
45
|
+
marked_for_removal.push link
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
marked_for_removal.each do |link|
|
50
|
+
@links.delete link
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/spnet.rb
ADDED
data/spec/block_spec.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe SPNet::Block do
|
4
|
+
context '.new' do
|
5
|
+
context 'no I/O ports given' do
|
6
|
+
before :all do
|
7
|
+
@block = SPNet::Block.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should have no input ports' do
|
11
|
+
@block.signal_in_ports.should be_empty
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should have no output ports' do
|
15
|
+
@block.signal_out_ports.should be_empty
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context '1 signal in and 1 signal out port given' do
|
20
|
+
before :all do
|
21
|
+
@block = SPNet::Block.new(
|
22
|
+
:signal_in_ports => [SPNet::SignalInPort.new(:name => "IN")],
|
23
|
+
:signal_out_ports => [SPNet::SignalOutPort.new(:name => "OUT")],
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should have no input ports' do
|
28
|
+
@block.signal_in_ports.count.should be 1
|
29
|
+
@block.signal_in_ports.first.name.should eq("IN")
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should have no output ports' do
|
33
|
+
@block.signal_out_ports.count.should be 1
|
34
|
+
@block.signal_out_ports.first.name.should eq("OUT")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe SPNet::ControlMessage do
|
4
|
+
describe '.new' do
|
5
|
+
it 'should set type to Message::CONTROL' do
|
6
|
+
message = SPNet::ControlMessage.new :subtype => SPNet::ControlMessage::GET
|
7
|
+
message.type.should eq(SPNet::Message::CONTROL)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should ignore attempt to override type' do
|
11
|
+
message = SPNet::ControlMessage.new :subtype => SPNet::ControlMessage::GET, :type => :fakeType
|
12
|
+
message.type.should eq(SPNet::Message::CONTROL)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should allow data to be set' do
|
16
|
+
message = SPNet::ControlMessage.new :subtype => SPNet::ControlMessage::GET, :data => 17
|
17
|
+
message.data.should eq(17)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.make_set_message' do
|
22
|
+
it 'should set data' do
|
23
|
+
message = SPNet::ControlMessage.make_set_message 18
|
24
|
+
message.data.should eq(18)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should set subtype to ControlMessage::SET' do
|
28
|
+
message = SPNet::ControlMessage.make_set_message 18
|
29
|
+
message.subtype.should eq(SPNet::ControlMessage::SET)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '.make_get_message' do
|
34
|
+
it 'should set subtype to ControlMessage::GET' do
|
35
|
+
message = SPNet::ControlMessage.make_get_message
|
36
|
+
message.subtype.should eq(SPNet::ControlMessage::GET)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe SPNet::MessageInPort do
|
4
|
+
describe '#recv_message' do
|
5
|
+
before :all do
|
6
|
+
processor = lambda do |message|
|
7
|
+
return message
|
8
|
+
end
|
9
|
+
@port = SPNet::MessageInPort.new :processor => processor, :message_type => SPNet::Message::CONTROL
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should pass the given message to the processing callback' do
|
13
|
+
rv = @port.recv_message SPNet::ControlMessage.make_set_message(5)
|
14
|
+
rv.data.should eq(5)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe SPNet::MessageOutPort do
|
4
|
+
before :all do
|
5
|
+
processor = lambda do |message|
|
6
|
+
return message
|
7
|
+
end
|
8
|
+
@in_port = SPNet::MessageInPort.new :processor => processor, :message_type => SPNet::Message::CONTROL
|
9
|
+
end
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
processor = lambda do |message|
|
13
|
+
return message
|
14
|
+
end
|
15
|
+
@in_port = SPNet::MessageInPort.new :processor => processor, :message_type => SPNet::Message::CONTROL
|
16
|
+
@out_port = SPNet::MessageOutPort.new
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#add_link' do
|
20
|
+
it 'should add the given input port to links' do
|
21
|
+
@out_port.add_link @in_port
|
22
|
+
@out_port.links.count.should be 1
|
23
|
+
@out_port.links.first.should eq(@in_port)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should also link the output port to the given input port' do
|
27
|
+
@out_port.add_link @in_port
|
28
|
+
@in_port.link.should eq(@out_port)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should raise ArgumentError if the given input port is already linked' do
|
32
|
+
@out_port.add_link @in_port
|
33
|
+
lambda { @out_port.add_link(@in_port) }.should raise_error(ArgumentError)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should raise ArgumentError if port is not input port' do
|
37
|
+
@out_port2 = SPNet::MessageOutPort.new
|
38
|
+
lambda { @out_port.add_link(@out_port2) }.should raise_error(ArgumentError)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#remove_link' do
|
43
|
+
it 'should remove the given input port (if it is already linked to the output port)' do
|
44
|
+
@out_port.add_link @in_port
|
45
|
+
@out_port.remove_link @in_port
|
46
|
+
@out_port.links.should be_empty
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#send_message' do
|
51
|
+
it 'should pass the given message via recv_message to the processing callback' do
|
52
|
+
@out_port.add_link @in_port
|
53
|
+
rv = @out_port.send_message SPNet::ControlMessage.make_set_message(5)
|
54
|
+
rv.first.data.should eq(5)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe SPNet::Message do
|
4
|
+
describe '.new' do
|
5
|
+
it 'should set data and type' do
|
6
|
+
message = SPNet::Message.new :type => SPNet::Message::CONTROL, :data => 9
|
7
|
+
message.type.should eq(SPNet::Message::CONTROL)
|
8
|
+
message.data.should eq(9)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe SPNet::SignalInPort do
|
4
|
+
describe '.new' do
|
5
|
+
it 'should have an empty queue' do
|
6
|
+
port = SPNet::SignalInPort.new
|
7
|
+
port.queue.should be_empty
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'enqueue_values' do
|
12
|
+
it 'should add values to queue' do
|
13
|
+
port = SPNet::SignalInPort.new
|
14
|
+
values = [2.4, 2.6, 4.9, 5.1]
|
15
|
+
|
16
|
+
port.enqueue_values(values.clone)
|
17
|
+
values.should eq(port.queue)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should limit all values before queuing them' do
|
21
|
+
port = SPNet::SignalInPort.new(:limits => (2.5..5.0))
|
22
|
+
port.enqueue_values([2.4, 2.6, 4.9, 5.1])
|
23
|
+
port.queue.each do |value|
|
24
|
+
value.should be_between(2.5, 5.0)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'dequeue_values' do
|
30
|
+
it 'should remove N values from queue' do
|
31
|
+
port = SPNet::SignalInPort.new
|
32
|
+
values = [2.4, 2.6, 4.9, 5.1]
|
33
|
+
port.enqueue_values(values.clone)
|
34
|
+
values2 = port.dequeue_values 2
|
35
|
+
port.queue.count.should be 2
|
36
|
+
values2.count.should be 2
|
37
|
+
values2.first.should eq(values.first)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should remove all values from queue if no count is given' do
|
41
|
+
port = SPNet::SignalInPort.new
|
42
|
+
values = [2.4, 2.6, 4.9, 5.1]
|
43
|
+
port.enqueue_values(values.clone)
|
44
|
+
values2 = port.dequeue_values
|
45
|
+
port.queue.should be_empty
|
46
|
+
values2.should eq(values)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe SPNet::SignalOutPort do
|
4
|
+
before :each do
|
5
|
+
@out_port = SPNet::SignalOutPort.new
|
6
|
+
@in_port = SPNet::SignalInPort.new
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '.new' do
|
10
|
+
it 'should have no links' do
|
11
|
+
@out_port = SPNet::SignalOutPort.new
|
12
|
+
@out_port.links.should be_empty
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#add_link' do
|
17
|
+
it 'should add the given input port to links' do
|
18
|
+
@out_port.add_link @in_port
|
19
|
+
@out_port.links.count.should be 1
|
20
|
+
@out_port.links.first.should eq(@in_port)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should also link the output port to the given input port' do
|
24
|
+
@out_port.add_link @in_port
|
25
|
+
@in_port.link.should eq(@out_port)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should raise ArgumentError if the given input port is already linked' do
|
29
|
+
@out_port.add_link @in_port
|
30
|
+
lambda { @out_port.add_link(@in_port) }.should raise_error(ArgumentError)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should raise ArgumentError if port is not input port' do
|
34
|
+
out_port2 = SPNet::SignalOutPort.new
|
35
|
+
lambda { @out_port.add_link(out_port2) }.should raise_error(ArgumentError)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#remove_link' do
|
40
|
+
it 'should remove the given input port (if it is already linked to the output port)' do
|
41
|
+
@out_port.add_link @in_port
|
42
|
+
@out_port.remove_link @in_port
|
43
|
+
@out_port.links.should be_empty
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#send_values' do
|
48
|
+
context 'single linked input port' do
|
49
|
+
it 'should enqueue the values on the linked input port' do
|
50
|
+
@out_port.add_link @in_port
|
51
|
+
|
52
|
+
@in_port.queue.should be_empty
|
53
|
+
@out_port.send_values [1,2,3,4]
|
54
|
+
@in_port.queue.should eq([1,2,3,4])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'several linked input ports' do
|
59
|
+
it 'should enqueue the values on each linked input port' do
|
60
|
+
in_port1 = SPNet::SignalInPort.new
|
61
|
+
in_port2 = SPNet::SignalInPort.new(:name => 'def')
|
62
|
+
in_port3 = SPNet::SignalInPort.new(:name => 'ghi')
|
63
|
+
|
64
|
+
@out_port.add_link in_port1
|
65
|
+
@out_port.add_link in_port2
|
66
|
+
@out_port.add_link in_port3
|
67
|
+
|
68
|
+
in_port1.queue.should be_empty
|
69
|
+
in_port2.queue.should be_empty
|
70
|
+
in_port3.queue.should be_empty
|
71
|
+
|
72
|
+
@out_port.send_values [1,2,3,4]
|
73
|
+
|
74
|
+
in_port1.queue.should eq([1,2,3,4])
|
75
|
+
in_port2.queue.should eq([1,2,3,4])
|
76
|
+
in_port3.queue.should eq([1,2,3,4])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spnet.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path('../lib/spnet/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = "spnet"
|
7
|
+
gem.version = SPNet::VERSION
|
8
|
+
gem.summary = %q{Provide infrastructure for forming processing networks.}
|
9
|
+
gem.description = <<DESCRIPTION
|
10
|
+
Provide infrastructure for forming processing networks.
|
11
|
+
DESCRIPTION
|
12
|
+
gem.license = "MIT"
|
13
|
+
gem.authors = ["James Tunnell"]
|
14
|
+
gem.email = "jamestunnell@lavabit.com"
|
15
|
+
gem.homepage = "https://rubygems.org/gems/spnet"
|
16
|
+
|
17
|
+
gem.files = `git ls-files`.split($/)
|
18
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
|
+
gem.require_paths = ['lib']
|
21
|
+
|
22
|
+
gem.add_dependency 'hashmake'
|
23
|
+
|
24
|
+
gem.add_development_dependency 'bundler', '~> 1.0'
|
25
|
+
gem.add_development_dependency 'rake', '~> 0.8'
|
26
|
+
gem.add_development_dependency 'rspec', '~> 2.4'
|
27
|
+
gem.add_development_dependency 'yard', '~> 0.8'
|
28
|
+
gem.add_development_dependency 'pry'
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spnet
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- James Tunnell
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: hashmake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0.8'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.8'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '2.4'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '2.4'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: yard
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0.8'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0.8'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: pry
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: ! 'Provide infrastructure for forming processing networks.
|
111
|
+
|
112
|
+
'
|
113
|
+
email: jamestunnell@lavabit.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- .document
|
119
|
+
- .gitignore
|
120
|
+
- .rspec
|
121
|
+
- .yardopts
|
122
|
+
- ChangeLog.rdoc
|
123
|
+
- Gemfile
|
124
|
+
- LICENSE.txt
|
125
|
+
- README.md
|
126
|
+
- README.rdoc
|
127
|
+
- Rakefile
|
128
|
+
- lib/spnet.rb
|
129
|
+
- lib/spnet/block.rb
|
130
|
+
- lib/spnet/control_message.rb
|
131
|
+
- lib/spnet/message.rb
|
132
|
+
- lib/spnet/message_in_port.rb
|
133
|
+
- lib/spnet/message_out_port.rb
|
134
|
+
- lib/spnet/signal_in_port.rb
|
135
|
+
- lib/spnet/signal_out_port.rb
|
136
|
+
- lib/spnet/version.rb
|
137
|
+
- spec/block_spec.rb
|
138
|
+
- spec/control_message_spec.rb
|
139
|
+
- spec/message_in_port_spec.rb
|
140
|
+
- spec/message_out_port_spec.rb
|
141
|
+
- spec/message_spec.rb
|
142
|
+
- spec/signal_in_port_spec.rb
|
143
|
+
- spec/signal_out_port_spec.rb
|
144
|
+
- spec/spec_helper.rb
|
145
|
+
- spec/spnetwork_spec.rb
|
146
|
+
- spnet.gemspec
|
147
|
+
homepage: https://rubygems.org/gems/spnet
|
148
|
+
licenses:
|
149
|
+
- MIT
|
150
|
+
post_install_message:
|
151
|
+
rdoc_options: []
|
152
|
+
require_paths:
|
153
|
+
- lib
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
|
+
none: false
|
156
|
+
requirements:
|
157
|
+
- - ! '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
segments:
|
161
|
+
- 0
|
162
|
+
hash: -728008657
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
none: false
|
165
|
+
requirements:
|
166
|
+
- - ! '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
segments:
|
170
|
+
- 0
|
171
|
+
hash: -728008657
|
172
|
+
requirements: []
|
173
|
+
rubyforge_project:
|
174
|
+
rubygems_version: 1.8.23
|
175
|
+
signing_key:
|
176
|
+
specification_version: 3
|
177
|
+
summary: Provide infrastructure for forming processing networks.
|
178
|
+
test_files:
|
179
|
+
- spec/block_spec.rb
|
180
|
+
- spec/control_message_spec.rb
|
181
|
+
- spec/message_in_port_spec.rb
|
182
|
+
- spec/message_out_port_spec.rb
|
183
|
+
- spec/message_spec.rb
|
184
|
+
- spec/signal_in_port_spec.rb
|
185
|
+
- spec/signal_out_port_spec.rb
|
186
|
+
- spec/spec_helper.rb
|
187
|
+
- spec/spnetwork_spec.rb
|
188
|
+
has_rdoc:
|