multi_movingsign 0.0.1
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/.gitignore +21 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/PAGE_DEFINITION.md +115 -0
- data/README.md +133 -0
- data/Rakefile +1 -0
- data/bin/multi_movingsign +5 -0
- data/example.jpg +0 -0
- data/fonts/7-row-normal.png +0 -0
- data/fonts/README.md +1 -0
- data/lib/multi_movingsign.rb +9 -0
- data/lib/multi_movingsign/cli.rb +81 -0
- data/lib/multi_movingsign/errors.rb +10 -0
- data/lib/multi_movingsign/page_renderer.rb +223 -0
- data/lib/multi_movingsign/server.rb +317 -0
- data/lib/multi_movingsign/settings.rb +55 -0
- data/lib/multi_movingsign/sign.rb +37 -0
- data/lib/multi_movingsign/signs.rb +39 -0
- data/lib/multi_movingsign/testrc_loader.rb +17 -0
- data/lib/multi_movingsign/version.rb +3 -0
- data/multi_movingsign.gemspec +31 -0
- data/spec/cli_spec.rb +166 -0
- data/spec/noop_movingsign_sign.rb +47 -0
- data/spec/noop_movingsign_sign.yml +7 -0
- data/spec/page_renderer/example_1/1.yml +16 -0
- data/spec/page_renderer/example_1/2.yml +28 -0
- data/spec/page_renderer/example_1/4.yml +44 -0
- data/spec/page_renderer/example_1/5.json +10 -0
- data/spec/page_renderer/example_1/example_spec.rb +23 -0
- data/spec/page_renderer/example_1/page.yml +27 -0
- data/spec/page_renderer/example_2/1.yml +7 -0
- data/spec/page_renderer/example_2/2.yml +8 -0
- data/spec/page_renderer/example_2/4.json +9 -0
- data/spec/page_renderer/example_2/example_spec.rb +24 -0
- data/spec/page_renderer/example_2/page.yml +7 -0
- data/spec/page_renderer/example_3/1.yml +9 -0
- data/spec/page_renderer/example_3/3.yml +14 -0
- data/spec/page_renderer/example_3/example_spec.rb +22 -0
- data/spec/page_renderer/example_3/page.yml +12 -0
- data/spec/page_renderer/example_4/2.yml +12 -0
- data/spec/page_renderer/example_4/4.json +9 -0
- data/spec/page_renderer/example_4/example_spec.rb +24 -0
- data/spec/page_renderer/example_4/page.yml +12 -0
- data/spec/settings_1.yml +3 -0
- data/spec/settings_spec.rb +36 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/support/doubles_support.rb +26 -0
- data/spec/support/executable_support.rb +112 -0
- metadata +244 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
#---------
|
2
|
+
#Top Drinkers
|
3
|
+
#1. mikey
|
4
|
+
#2. capn
|
5
|
+
#3. eric
|
6
|
+
#---------
|
7
|
+
#Top Drinkers
|
8
|
+
#1. 445 pints
|
9
|
+
#2. 183 pints
|
10
|
+
#3. 122 pints
|
11
|
+
#---------
|
12
|
+
#Top Drinkers
|
13
|
+
#4. whitey
|
14
|
+
#5. justin
|
15
|
+
#6. scarfjerk
|
16
|
+
#---------
|
17
|
+
#Top Drinkers
|
18
|
+
#4. 114 pints
|
19
|
+
#5. 110 pints
|
20
|
+
#6. 109 pints
|
21
|
+
#---------
|
22
|
+
---
|
23
|
+
lines: 4
|
24
|
+
signs:
|
25
|
+
- content: |-
|
26
|
+
Top Drinkers
|
27
|
+
Top Drinkers
|
28
|
+
Top Drinkers
|
29
|
+
Top Drinkers
|
30
|
+
- content: |-
|
31
|
+
1. mikey
|
32
|
+
1. 445 pints
|
33
|
+
4. whitey
|
34
|
+
4. 114 pints
|
35
|
+
- content: |-
|
36
|
+
2. capn
|
37
|
+
2. 183 pints
|
38
|
+
5. justin
|
39
|
+
5. 110 pints
|
40
|
+
- content: |-
|
41
|
+
3. eric
|
42
|
+
3. 122 pints
|
43
|
+
6. scarfjerk
|
44
|
+
6. 109 pints
|
@@ -0,0 +1,10 @@
|
|
1
|
+
{
|
2
|
+
"lines": 4,
|
3
|
+
"signs": [
|
4
|
+
{ "content": "Top Drinkers\nTop Drinkers\nTop Drinkers\nTop Drinkers" },
|
5
|
+
{ "content": "1. mikey\n1. 445 pints\n5. justin\n5. 110 pints" },
|
6
|
+
{ "content": "2. capn\n2. 183 pints\n6. scarfjerk\n6. 109 pints" },
|
7
|
+
{ "content": "3. eric\n3. 122 pints\n \n " },
|
8
|
+
{ "content": "4. whitey\n4. 114 pints\n \n " }
|
9
|
+
]
|
10
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yaml'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
describe "PageRenderer - Example 1" do
|
6
|
+
|
7
|
+
[1, 2, 4, 5].each do |screens|
|
8
|
+
describe "#{screens} screen(s)" do
|
9
|
+
it "Renders as Expected" do
|
10
|
+
page = YAML.load(File.read(File.join(File.dirname(__FILE__), 'page.yml')))
|
11
|
+
|
12
|
+
expected = nil
|
13
|
+
if File.exists?(path = File.join(File.dirname(__FILE__), "#{screens}.yml"))
|
14
|
+
expected = YAML.load(File.read(path))
|
15
|
+
else
|
16
|
+
expected = JSON.load(File.read(File.join(File.dirname(__FILE__), "#{screens}.json")))
|
17
|
+
end
|
18
|
+
|
19
|
+
expect(MultiMovingsign::PageRenderer.new.render(page, :count => screens)).to eq(expected)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
---
|
2
|
+
title: Top Drinkers
|
3
|
+
lines:
|
4
|
+
- prefix: '1. '
|
5
|
+
content:
|
6
|
+
- mikey
|
7
|
+
- 445 pints
|
8
|
+
- prefix: '2. '
|
9
|
+
content:
|
10
|
+
- capn
|
11
|
+
- 183 pints
|
12
|
+
- prefix: '3. '
|
13
|
+
content:
|
14
|
+
- eric
|
15
|
+
- 122 pints
|
16
|
+
- prefix: '4. '
|
17
|
+
content:
|
18
|
+
- whitey
|
19
|
+
- 114 pints
|
20
|
+
- prefix: '5. '
|
21
|
+
content:
|
22
|
+
- justin
|
23
|
+
- 110 pints
|
24
|
+
- prefix: '6. '
|
25
|
+
content:
|
26
|
+
- scarfjerk
|
27
|
+
- 109 pints
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yaml'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
describe "PageRenderer - Example 2" do
|
6
|
+
|
7
|
+
[1, 2, 4].each do |screens|
|
8
|
+
describe "#{screens} screen(s)" do
|
9
|
+
it "Renders as Expected" do
|
10
|
+
page = YAML.load(File.read(File.join(File.dirname(__FILE__), 'page.yml')))
|
11
|
+
|
12
|
+
expected = nil
|
13
|
+
if File.exists?(path = File.join(File.dirname(__FILE__), "#{screens}.yml"))
|
14
|
+
expected = YAML.load(File.read(path))
|
15
|
+
else
|
16
|
+
expected = JSON.load(File.read(File.join(File.dirname(__FILE__), "#{screens}.json")))
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
expect(MultiMovingsign::PageRenderer.new.render(page, :count => screens)).to eq(expected)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yaml'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
describe "PageRenderer - Example 3" do
|
6
|
+
[1, 3].each do |screens|
|
7
|
+
describe "#{screens} screen(s)" do
|
8
|
+
it "Renders as Expected" do
|
9
|
+
page = YAML.load(File.read(File.join(File.dirname(__FILE__), 'page.yml')))
|
10
|
+
|
11
|
+
expected = nil
|
12
|
+
if File.exists?(path = File.join(File.dirname(__FILE__), "#{screens}.yml"))
|
13
|
+
expected = YAML.load(File.read(path))
|
14
|
+
else
|
15
|
+
expected = JSON.load(File.read(File.join(File.dirname(__FILE__), "#{screens}.json")))
|
16
|
+
end
|
17
|
+
|
18
|
+
expect(MultiMovingsign::PageRenderer.new.render(page, :count => screens)).to eq(expected)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yaml'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
describe "PageRenderer - Example 3" do
|
6
|
+
[2,4].each do |screens|
|
7
|
+
describe "#{screens} screen(s)" do
|
8
|
+
it "Renders as Expected" do
|
9
|
+
page = nil
|
10
|
+
|
11
|
+
page = YAML.load(File.read(File.join(File.dirname(__FILE__), 'page.yml')))
|
12
|
+
|
13
|
+
expected = nil
|
14
|
+
if File.exists?(path = File.join(File.dirname(__FILE__), "#{screens}.yml"))
|
15
|
+
expected = YAML.load(File.read(path))
|
16
|
+
else
|
17
|
+
expected = JSON.load(File.read(File.join(File.dirname(__FILE__), "#{screens}.json")))
|
18
|
+
end
|
19
|
+
|
20
|
+
expect(MultiMovingsign::PageRenderer.new.render(page, :count => screens)).to eq(expected)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/settings_1.yml
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
describe MultiMovingsign::Settings do
|
5
|
+
let(:tempfile) { Tempfile.new(['spec_settings', '.yml']) }
|
6
|
+
|
7
|
+
describe "Empty Settings File" do
|
8
|
+
subject { described_class.load (tempfile.path) }
|
9
|
+
|
10
|
+
it "#signs returns []" do
|
11
|
+
expect(subject.signs.length).to eq 0
|
12
|
+
end
|
13
|
+
|
14
|
+
it "#signs? returns false" do
|
15
|
+
expect(subject.signs?).to be_false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "Example Settings File - 1" do
|
20
|
+
subject { described_class.load(File.join(File.dirname(__FILE__), 'settings_1.yml'))}
|
21
|
+
|
22
|
+
it "#signs? returns true" do
|
23
|
+
expect(subject.signs?).to be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "#signs.length == 1" do
|
27
|
+
expect(subject.signs.length).to eq 1
|
28
|
+
end
|
29
|
+
|
30
|
+
it "#signs contains path '/dev/ttyUSB0'" do
|
31
|
+
paths = subject.signs.map { |s| s.path }
|
32
|
+
expect(paths.include?('/dev/ttyUSB0')).to be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'multi_movingsign'
|
2
|
+
require 'support/executable_support'
|
3
|
+
require 'support/doubles_support'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
ruby_version = "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
|
7
|
+
puts "Ruby Version: #{ruby_version}"
|
8
|
+
|
9
|
+
# Setup logging
|
10
|
+
rspec_log_path = "rspec.log"
|
11
|
+
RSPEC_LOGGER = Logger.new rspec_log_path
|
12
|
+
|
13
|
+
puts "Logging to #{rspec_log_path}"
|
14
|
+
RSPEC_LOGGER.info "Starting #{Time.now}"
|
15
|
+
RSPEC_LOGGER.info "Ruby Version: #{ruby_version}"
|
16
|
+
|
17
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
18
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
19
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
20
|
+
# loaded once.
|
21
|
+
#
|
22
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
23
|
+
RSpec.configure do |config|
|
24
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
25
|
+
config.run_all_when_everything_filtered = true
|
26
|
+
config.filter_run :focus
|
27
|
+
|
28
|
+
# Run specs in random order to surface order dependencies. If you find an
|
29
|
+
# order dependency and want to debug it, you can fix the order by providing
|
30
|
+
# the seed, which is printed after each run.
|
31
|
+
# --seed 1234
|
32
|
+
config.order = 'random'
|
33
|
+
|
34
|
+
config.include ExecutableHelpers
|
35
|
+
config.include MultiMoviginsignDoubles
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module MultiMoviginsignDoubles
|
2
|
+
# Overrides MovingsignApi::Sign recording all calls to it's methods (for testing/validation)
|
3
|
+
def double_movingsign_sign
|
4
|
+
MovingsignApi::Sign.class_exec do
|
5
|
+
@@mutex = Mutex.new
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_accessor :calls
|
9
|
+
end
|
10
|
+
|
11
|
+
(MovingsignApi::Sign.public_instance_methods.to_a - Object.public_instance_methods.to_a - [:device_path]).each do |method|
|
12
|
+
define_method(method) do |*args|
|
13
|
+
@@mutex.synchronize do
|
14
|
+
self.calls << [self.device_path, method, args]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def calls
|
20
|
+
self.class.calls
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
MovingsignApi::Sign.calls = []
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'hashie/mash'
|
3
|
+
|
4
|
+
module ExecutableHelpers
|
5
|
+
# Executes a given command string, collecting both stdout and stderr, along with the exit status.
|
6
|
+
# @return [ExecutationResult] container of the execution results
|
7
|
+
def execute(command)
|
8
|
+
out_path = File.join(Dir.mktmpdir('execute-'), 'stdout.log')
|
9
|
+
out_file = File.open(out_path, 'w')
|
10
|
+
|
11
|
+
pid = Kernel.spawn(command, [:out, :err] => out_file.fileno, :in => :close)
|
12
|
+
RSPEC_LOGGER.info "[#{pid}] Executed '#{command}' > #{out_file.path}"
|
13
|
+
Process.waitpid(pid)
|
14
|
+
|
15
|
+
out_file.flush
|
16
|
+
out_file.close
|
17
|
+
|
18
|
+
out = File.read out_file.path
|
19
|
+
|
20
|
+
result = ExecutationResult.new
|
21
|
+
result.status = $?
|
22
|
+
result.stdout = out
|
23
|
+
|
24
|
+
result
|
25
|
+
end
|
26
|
+
|
27
|
+
# This never really worked well for testing. Keeping for now.
|
28
|
+
## Executes a given block in this procress
|
29
|
+
#def execute_in_process(&block)
|
30
|
+
# exit_status = 1
|
31
|
+
# stdout = ""
|
32
|
+
#
|
33
|
+
# stdout = capture do
|
34
|
+
# begin
|
35
|
+
# begin
|
36
|
+
# yield
|
37
|
+
# rescue ScriptError => e
|
38
|
+
# report_raise e
|
39
|
+
# exit 1
|
40
|
+
# rescue SignalException => e
|
41
|
+
# report_raise e
|
42
|
+
# exit 1
|
43
|
+
# rescue StandardError => e
|
44
|
+
# report_raise e
|
45
|
+
# exit 1
|
46
|
+
# end
|
47
|
+
# rescue SystemExit => e
|
48
|
+
# exit_status = e.status
|
49
|
+
# else
|
50
|
+
# exit_status = 0
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# status_double = Object.new
|
55
|
+
# status_double.instance_exec(exit_status) do |status|
|
56
|
+
# @exit_status = status
|
57
|
+
#
|
58
|
+
# def success?
|
59
|
+
# @exit_status == 0
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# def exitstatus
|
63
|
+
# @exit_status
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# result = ExecutationResult.new
|
68
|
+
# result.status = status_double
|
69
|
+
# result.stdout = stdout
|
70
|
+
#
|
71
|
+
# result
|
72
|
+
#end
|
73
|
+
|
74
|
+
def expect_command_success(command_results)
|
75
|
+
expect(command_results).to be_success, "Expected command successs but it failed. Got: \n#{command_results.stdout}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def report_raise(e)
|
79
|
+
$stderr.puts e.message
|
80
|
+
$stderr.puts e.backtrace.join "\n"
|
81
|
+
end
|
82
|
+
|
83
|
+
def capture(&code)
|
84
|
+
out = StringIO.new
|
85
|
+
|
86
|
+
og_stdout = $stdout
|
87
|
+
og_stderr = $stderr
|
88
|
+
begin
|
89
|
+
$stdout = out
|
90
|
+
$stderr = out
|
91
|
+
|
92
|
+
yield
|
93
|
+
ensure
|
94
|
+
$stdout = og_stdout
|
95
|
+
$stderr = og_stderr
|
96
|
+
end
|
97
|
+
|
98
|
+
out.string
|
99
|
+
end
|
100
|
+
|
101
|
+
# Container for the execution results returned by {ExecutableHelpers::execute}
|
102
|
+
class ExecutationResult
|
103
|
+
# Execution status (as returned by $?)
|
104
|
+
attr_accessor :status
|
105
|
+
# STDOUT + STDERR as a string
|
106
|
+
attr_accessor :stdout
|
107
|
+
|
108
|
+
def success?
|
109
|
+
self.status.success?
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|