vmsim 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +27 -0
- data/README.txt +1 -0
- data/Rakefile +40 -0
- data/VERSION +1 -0
- data/bin/vmdeploy +23 -0
- data/bin/vmsim +37 -0
- data/doc/actuators_and_sensors.txt +32 -0
- data/doc/handout.odt +0 -0
- data/doc/machine.jpg +0 -0
- data/doc/todo.txt +25 -0
- data/lib/adapter/actuator_collection.rb +61 -0
- data/lib/adapter/sensor_collection.rb +57 -0
- data/lib/archive_builder.rb +64 -0
- data/lib/control/main.rb +21 -0
- data/lib/control.rb +3 -0
- data/lib/deploy/deployer.rb +96 -0
- data/lib/deploy.rb +1 -0
- data/lib/devices/devices.rb +73 -0
- data/lib/devices.rb +1 -0
- data/lib/gui/SimulatorGui.gtk +289 -0
- data/lib/gui/simulator_gtk.rb +57 -0
- data/lib/gui/simulator_gui.rb +64 -0
- data/lib/gui.rb +2 -0
- data/lib/hardware/bin.rb +28 -0
- data/lib/hardware/button.rb +18 -0
- data/lib/hardware/can.rb +9 -0
- data/lib/hardware/cash_register.rb +79 -0
- data/lib/hardware/component.rb +56 -0
- data/lib/hardware/display.rb +29 -0
- data/lib/hardware/drawer.rb +45 -0
- data/lib/hardware/enum.rb +20 -0
- data/lib/hardware/simulator.rb +98 -0
- data/lib/hardware.rb +10 -0
- data/lib/hardware_adapter.rb +11 -0
- data/lib/vmlog.rb +5 -0
- data/test/adapter/actuator_collection_test.rb +106 -0
- data/test/adapter/sensor_collection_test.rb +51 -0
- data/test/deploy/deployer_test.rb +114 -0
- data/test/deploy/was_run.sh +5 -0
- data/test/devices/devices_test.rb +78 -0
- data/test/hardware/bin_test.rb +57 -0
- data/test/hardware/button_test.rb +23 -0
- data/test/hardware/can_test.rb +11 -0
- data/test/hardware/cash_register_test.rb +157 -0
- data/test/hardware/component_test.rb +37 -0
- data/test/hardware/display_test.rb +94 -0
- data/test/hardware/drawer_test.rb +100 -0
- data/test/hardware/enum_test.rb +33 -0
- data/test/hardware/simulator_test.rb +189 -0
- data/test/test_helper.rb +5 -0
- data/vmsim.gemspec +89 -0
- metadata +131 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
module Hardware
|
2
|
+
class Enum
|
3
|
+
def initialize(type)
|
4
|
+
@type = type
|
5
|
+
end
|
6
|
+
def inspect
|
7
|
+
return "#{self.class.name}.#{@type}"
|
8
|
+
end
|
9
|
+
def self.method_missing(method)
|
10
|
+
begin
|
11
|
+
self.send('class_variable_get',"@@#{method}")
|
12
|
+
rescue
|
13
|
+
raise "Enum constant '#{method}' not defined in #{self}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
def self.values(*values)
|
17
|
+
values.each{|value| send('class_variable_set',"@@#{value}", new(value.to_s))}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'hardware_adapter'
|
2
|
+
module Hardware
|
3
|
+
class Simulator
|
4
|
+
attr_reader :bin, :cash_register, :display
|
5
|
+
|
6
|
+
def initialize(actuators = Adapter.actuators, sensors = Adapter.sensors)
|
7
|
+
@components = {}
|
8
|
+
@actuators = actuators
|
9
|
+
@sensors = sensors
|
10
|
+
end
|
11
|
+
|
12
|
+
def component(component_name)
|
13
|
+
@components[component_name]
|
14
|
+
end
|
15
|
+
|
16
|
+
def assemble_hardware_component(component_name, component)
|
17
|
+
@components[component_name] = component
|
18
|
+
component.configure
|
19
|
+
end
|
20
|
+
|
21
|
+
def assemble_hardware_components(basename, components)
|
22
|
+
components.each_with_index do |component, sequence_number|
|
23
|
+
assemble_hardware_component(component_name(basename, sequence_number), component)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def monitor_changes(component_name, &block)
|
28
|
+
component(component_name).monitor_changes(&block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def assemble_hardware
|
32
|
+
assemble_hardware_component :bin, create_bin
|
33
|
+
assemble_hardware_component :display, create_display
|
34
|
+
assemble_hardware_component :cash_register, create_cash_register
|
35
|
+
assemble_hardware_components :drawer, create_drawers
|
36
|
+
assemble_hardware_components :button, create_buttons
|
37
|
+
end
|
38
|
+
|
39
|
+
def drawer(no)
|
40
|
+
@drawers[no]
|
41
|
+
end
|
42
|
+
|
43
|
+
def button(no)
|
44
|
+
@buttons[no]
|
45
|
+
end
|
46
|
+
|
47
|
+
def reset
|
48
|
+
@components.each { |name, component| component.reset }
|
49
|
+
sensors.remove_fire_listeners
|
50
|
+
boot
|
51
|
+
end
|
52
|
+
|
53
|
+
def boot
|
54
|
+
call_boot_block
|
55
|
+
end
|
56
|
+
|
57
|
+
def on_boot(&block)
|
58
|
+
@boot_block = block
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
private
|
63
|
+
attr_reader :actuators, :sensors
|
64
|
+
|
65
|
+
def call_boot_block
|
66
|
+
@boot_block.call if @boot_block
|
67
|
+
end
|
68
|
+
def component_name(basename, sequence_number)
|
69
|
+
"#{basename}_#{sequence_number}".to_sym
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_display
|
73
|
+
@display = Hardware::Display.new(actuators)
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_cash_register
|
77
|
+
@cash_register = Hardware::CashRegister.new(bin, sensors, actuators)
|
78
|
+
end
|
79
|
+
|
80
|
+
def create_drawers
|
81
|
+
@drawers = [ Hardware::Drawer.new(bin,sensors,actuators, 0),
|
82
|
+
Hardware::Drawer.new(bin,sensors,actuators, 1),
|
83
|
+
Hardware::Drawer.new(bin,sensors,actuators, 2),
|
84
|
+
Hardware::Drawer.new(bin,sensors,actuators, 3)]
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_buttons
|
88
|
+
@buttons = [ Hardware::Button.new(sensors, 0),
|
89
|
+
Hardware::Button.new(sensors, 1),
|
90
|
+
Hardware::Button.new(sensors, 2),
|
91
|
+
Hardware::Button.new(sensors, 3)]
|
92
|
+
end
|
93
|
+
|
94
|
+
def create_bin
|
95
|
+
@bin = Hardware::Bin.new(sensors)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/hardware.rb
ADDED
data/lib/vmlog.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','test_helper')
|
2
|
+
require 'hardware_adapter'
|
3
|
+
|
4
|
+
module Adapter
|
5
|
+
class ActuatorCollectionTest < Test::Unit::TestCase
|
6
|
+
attr_reader :actuator_collection, :actuator_called, :other_actuator_called
|
7
|
+
def setup
|
8
|
+
@actuator_collection = ActuatorCollection.new(SynchronousFirer)
|
9
|
+
@actuator_called = false
|
10
|
+
@other_actuator_called = false
|
11
|
+
actuator_collection.create_actuator_for('some_actuator') do
|
12
|
+
@actuator_called = true
|
13
|
+
end
|
14
|
+
actuator_collection.create_actuator_for(:some_other_actuator) do
|
15
|
+
@other_actuator_called = true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_list_lists_actuators
|
20
|
+
assert_equal [:some_actuator, :some_other_actuator], actuator_collection.list
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_actuators_not_called_if_not_fired
|
24
|
+
assert_equal false, actuator_called, "this actuator should not be called yet"
|
25
|
+
assert_equal false, other_actuator_called, "this actuator should not be called yet"
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_calls_block_given_for_any_actuator
|
29
|
+
actuator_collection.fire(:some_actuator)
|
30
|
+
actuator_collection.fire(:some_other_actuator)
|
31
|
+
|
32
|
+
assert actuator_called, "actuator should be called on fire"
|
33
|
+
assert other_actuator_called, "actuator should be called on fire"
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_actuator_block_can_accept_parameters
|
37
|
+
int_val = -1
|
38
|
+
string_val = ""
|
39
|
+
actuator_collection.create_actuator_for(:parametarized_actuator) do |param1, param2|
|
40
|
+
int_val = param1
|
41
|
+
string_val = param2
|
42
|
+
end
|
43
|
+
actuator_collection.fire(:parametarized_actuator, 34, "gijs")
|
44
|
+
|
45
|
+
assert_equal 34, int_val
|
46
|
+
assert_equal "gijs", string_val
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_actuator_block_may_skip_parameters
|
50
|
+
int_val = -1
|
51
|
+
string_val = ""
|
52
|
+
actuator_collection.create_actuator_for(:parametarized_actuator) do |param1, param2|
|
53
|
+
int_val = param1
|
54
|
+
string_val = param2
|
55
|
+
end
|
56
|
+
actuator_collection.fire(:parametarized_actuator, 34, "gijs", "truus")
|
57
|
+
|
58
|
+
assert_equal 34, int_val
|
59
|
+
assert_equal "gijs", string_val
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_raises_exception_on_firing_unknown_actuator
|
63
|
+
assert_raises NoSuchActuatorException do
|
64
|
+
actuator_collection.fire(:unknown_actuator)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_raises_exception_on_no_block_given
|
69
|
+
assert_raises NoActuatorBlockGiven do
|
70
|
+
actuator_collection.create_actuator_for(:actuator_no_block)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_raises_exception_on_duplicate_actuator
|
75
|
+
assert_raises DuplicateActuatorException do
|
76
|
+
actuator_collection.create_actuator_for(:some_actuator) {}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class AsynchronousFirerTest < Test::Unit::TestCase
|
82
|
+
def test_fires_on_other_thread
|
83
|
+
fired = false
|
84
|
+
firer = AsynchronousFirer.new do
|
85
|
+
sleep(0.1)
|
86
|
+
fired = true
|
87
|
+
end
|
88
|
+
t = firer.fire
|
89
|
+
assert_equal false, fired, "should not be fired"
|
90
|
+
t.join
|
91
|
+
assert fired, "should be fired"
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_fires_on_other_thread_with_parameters
|
95
|
+
fired = ''
|
96
|
+
firer = AsynchronousFirer.new do |value|
|
97
|
+
sleep(0.1)
|
98
|
+
fired = value
|
99
|
+
end
|
100
|
+
t = firer.fire('passed string value')
|
101
|
+
assert_equal '', fired, "should not be fired"
|
102
|
+
t.join
|
103
|
+
assert_equal 'passed string value', fired, "should be fired"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','test_helper')
|
2
|
+
require 'hardware_adapter'
|
3
|
+
|
4
|
+
module Adapter
|
5
|
+
|
6
|
+
class SensorCollectionFireTest < Test::Unit::TestCase
|
7
|
+
attr_reader :sensors
|
8
|
+
def setup
|
9
|
+
@sensors = SensorCollection.new
|
10
|
+
sensors.create_sensor_for(:bin_entry)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_list_lists_sensor
|
14
|
+
sensors.create_sensor_for(:something_entry)
|
15
|
+
assert_equal [:bin_entry, :something_entry], sensors.list
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_calls_block_given_for_a_sensor
|
19
|
+
bin_entry_fired = false
|
20
|
+
sensors.on(:bin_entry) do
|
21
|
+
bin_entry_fired = true
|
22
|
+
end
|
23
|
+
sensors.fire(:bin_entry)
|
24
|
+
assert bin_entry_fired, "bin_entry should be fired"
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_swallows_fire_silently_when_no_handler_defined
|
28
|
+
sensors.fire(:bin_entry)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
class SensorCollectionFireWithoutReceptorsCreatedTest < Test::Unit::TestCase
|
34
|
+
attr_reader :sensors
|
35
|
+
def setup
|
36
|
+
@sensors = SensorCollection.new
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_swallows_fire_silently_when_no_handler_defined
|
40
|
+
sensors.fire(:bin_entry)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_on_raises_a_no_such_sensor_exception
|
44
|
+
assert_raises NoSuchSensorException do
|
45
|
+
sensors.on(:bin_entry) {}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','test_helper')
|
2
|
+
require 'deploy'
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'archive_builder'
|
5
|
+
|
6
|
+
module Deploy
|
7
|
+
module DeployerTestHelper
|
8
|
+
attr_reader :deployer
|
9
|
+
def create_deployer
|
10
|
+
@deployer = Deployer.new(File.expand_path(File.join(File.dirname(__FILE__), 'was_run.sh')))
|
11
|
+
end
|
12
|
+
def deploy(archive)
|
13
|
+
create_deployer
|
14
|
+
deployer.deploy archive
|
15
|
+
end
|
16
|
+
def is_running(pid)
|
17
|
+
begin
|
18
|
+
Process.kill(0, pid)
|
19
|
+
return true
|
20
|
+
rescue
|
21
|
+
return false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class DeployerDeployTest < Test::Unit::TestCase
|
27
|
+
include ArchiveBuilder
|
28
|
+
include DeployerTestHelper
|
29
|
+
include FileUtils
|
30
|
+
def teardown
|
31
|
+
rm_r './tmp' if File.exists?('./tmp')
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_unzips_the_archive_and_fires_the_executable
|
35
|
+
deploy an_archive('controlcode.pkg') {
|
36
|
+
a_file("main.rb").with("puts 'was unpacked'")
|
37
|
+
}
|
38
|
+
assert is_running(deployer.current_pid)
|
39
|
+
assert_match /was started.*was unpacked/m, deployer.wait_for.run_log
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_unzips_the_archive_with_relative_path_and_fires_the_executable
|
43
|
+
deploy an_archive('controlcode.pkg', 'tmp') {
|
44
|
+
a_file("main.rb").with("puts 'was unpacked'")
|
45
|
+
}
|
46
|
+
assert is_running(deployer.current_pid)
|
47
|
+
assert_match /was started.*was unpacked/m, deployer.wait_for.run_log
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_clears_current_pid_on_exit
|
51
|
+
deploy an_archive('controlcode.pkg') {
|
52
|
+
a_file("main.rb").with("puts 'was unpacked'")
|
53
|
+
}
|
54
|
+
assert_nil deployer.wait_for.current_pid
|
55
|
+
assert !File.exists?(Deployer::PIDFILE), "PIDFILE should be gone"
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_removes_previous_files
|
59
|
+
deploy an_archive('controlcode.pkg') {
|
60
|
+
a_file("loaded_class.rb").with("class LoadedClass; end")
|
61
|
+
a_file("main.rb").with("require 'loaded_class'")
|
62
|
+
}
|
63
|
+
|
64
|
+
deploy an_archive('controlcode.pkg') {
|
65
|
+
a_file("main.rb").with("puts 'was unpacked'")
|
66
|
+
}
|
67
|
+
|
68
|
+
assert !File.exists?(File.join(Deployer::DEPLOYED_DIR, 'loaded_class.rb')), "loaded class should be removed"
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_removes_previous_directories
|
72
|
+
deploy an_archive('controlcode.pkg') {
|
73
|
+
a_file("lib/loaded_class.rb").with("class LoadedClass; end")
|
74
|
+
a_file("main.rb").with("require 'lib/loaded_class'")
|
75
|
+
}
|
76
|
+
|
77
|
+
deploy an_archive('controlcode.pkg') {
|
78
|
+
a_file("main.rb").with("puts 'was unpacked'")
|
79
|
+
}
|
80
|
+
|
81
|
+
assert !File.exists?(File.join(Deployer::DEPLOYED_DIR, 'loaded_class.rb')), "loaded class should be removed"
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_kills_the_current_running_process_and_starts_new_one
|
85
|
+
deploy an_archive('controlcode.pkg') {
|
86
|
+
a_file("main.rb").with("sleep 1")
|
87
|
+
}
|
88
|
+
old_process_id = deployer.current_pid
|
89
|
+
|
90
|
+
deploy an_archive('controlcode.pkg') {
|
91
|
+
a_file("main.rb").with("puts 'was unpacked'")
|
92
|
+
}
|
93
|
+
|
94
|
+
assert !is_running(old_process_id), "process should be stopped before starting new"
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
class DeployerKillTest < Test::Unit::TestCase
|
100
|
+
include ArchiveBuilder
|
101
|
+
include DeployerTestHelper
|
102
|
+
|
103
|
+
def test_kills_the_current_running_process
|
104
|
+
deploy an_archive('controlcode.pkg') {
|
105
|
+
a_file("main.rb").with("sleep 20")
|
106
|
+
}
|
107
|
+
process_id = deployer.current_pid
|
108
|
+
create_deployer
|
109
|
+
deployer.kill
|
110
|
+
assert !is_running(process_id), "process should be stopped"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','test_helper')
|
2
|
+
require 'mocha'
|
3
|
+
require 'devices'
|
4
|
+
|
5
|
+
module Devices
|
6
|
+
class DevicesTest < Test::Unit::TestCase
|
7
|
+
attr_reader :actuators, :sensors, :devices, :handler
|
8
|
+
def setup
|
9
|
+
@actuators = mock('actuatorcollection')
|
10
|
+
@sensors = mock('sensorcollection')
|
11
|
+
@devices = Devices.new(actuators, sensors)
|
12
|
+
@handler = 'not called'
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_display_show
|
16
|
+
actuators.expects(:fire).with(:display_show, 1, "test message")
|
17
|
+
devices.display_show(1, "test message")
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_button_on_press
|
21
|
+
sensors.expects(:on).with(:button_press_1).yields
|
22
|
+
devices.on_button_pressed(1) { handler_called }
|
23
|
+
assert_equal 'called', handler
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_bin_entry
|
27
|
+
sensors.expects(:on).with(:bin_entry).yields
|
28
|
+
devices.on_bin_entry { handler_called }
|
29
|
+
assert_equal 'called', handler
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_bin_fetch_all
|
33
|
+
sensors.expects(:on).with(:bin_fetch_all).yields
|
34
|
+
devices.on_bin_fetch_all { handler_called }
|
35
|
+
assert_equal 'called', handler
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_cash_register_fill_money
|
39
|
+
sensors.expects(:on).with(:cash_fill_100).yields
|
40
|
+
devices.on_cash_filled(100) { handler_called }
|
41
|
+
assert_equal 'called', handler
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_cash_register_insert_money
|
45
|
+
sensors.expects(:on).with(:cash_insert_100).yields
|
46
|
+
devices.on_cash_inserted(100) { handler_called }
|
47
|
+
assert_equal 'called', handler
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_cash_drop_drops_coin
|
51
|
+
actuators.expects(:fire).with(:cash_drop_100)
|
52
|
+
devices.cash_drop_coin(100)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_drawer_register_can_dropped
|
56
|
+
sensors.expects(:on).with(:drawer_drop_can_0).yields
|
57
|
+
devices.on_drawer_dropped(0) { handler_called }
|
58
|
+
assert_equal 'called', handler
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_drawer_register_can_filled
|
62
|
+
sensors.expects(:on).with(:drawer_fill_can_0).yields
|
63
|
+
devices.on_drawer_filled(0) { handler_called }
|
64
|
+
assert_equal 'called', handler
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_drawer_drop_drops_can
|
68
|
+
actuators.expects(:fire).with(:drawer_drop_can_1)
|
69
|
+
devices.drawer_drop_can(1)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def handler_called
|
75
|
+
@handler = 'called'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','test_helper')
|
2
|
+
require 'mocha'
|
3
|
+
require 'hardware'
|
4
|
+
require 'hardware_adapter'
|
5
|
+
|
6
|
+
module Hardware
|
7
|
+
class BinTest < Test::Unit::TestCase
|
8
|
+
attr_reader :bin, :sensor_collection
|
9
|
+
def setup
|
10
|
+
@sensor_collection = mock('sensor_collection')
|
11
|
+
@bin = Bin.new(sensor_collection)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_receive_fills_the_bin_with_the_item
|
15
|
+
sensor_collection.expects(:fire).with(:bin_entry)
|
16
|
+
bin.receive('some_object')
|
17
|
+
assert_equal(['some_object'], bin.contents)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_fetch_the_stuff_empties_the_bin
|
21
|
+
sensor_collection.stubs(:fire).with(:bin_entry) # firing :bin_entry tested above
|
22
|
+
bin.receive('some_object')
|
23
|
+
bin.receive('some_object')
|
24
|
+
|
25
|
+
sensor_collection.expects(:fire).with(:bin_fetch_all)
|
26
|
+
bin.fetch_all
|
27
|
+
|
28
|
+
assert_equal([], bin.contents)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_configure_configures_the_sensor_in_the_sensor_collection
|
32
|
+
sensor_collection.expects(:create_sensor_for).with(:bin_entry)
|
33
|
+
sensor_collection.expects(:create_sensor_for).with(:bin_fetch_all)
|
34
|
+
bin.configure
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_updates_ui_when_receiving_something
|
38
|
+
bin = Bin.new(Adapter::SensorCollection.null)
|
39
|
+
change_called = false
|
40
|
+
bin.monitor_changes do
|
41
|
+
change_called = true
|
42
|
+
end
|
43
|
+
bin.receive('some_object')
|
44
|
+
assert change_called, 'change was not called'
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_updates_ui_when_fetching_all
|
48
|
+
bin = Bin.new(Adapter::SensorCollection.null)
|
49
|
+
change_called = false
|
50
|
+
bin.monitor_changes do
|
51
|
+
change_called = true
|
52
|
+
end
|
53
|
+
bin.fetch_all
|
54
|
+
assert change_called, 'change was not called'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','test_helper')
|
2
|
+
require 'mocha'
|
3
|
+
require 'hardware'
|
4
|
+
|
5
|
+
module Hardware
|
6
|
+
class ButtonTest < Test::Unit::TestCase
|
7
|
+
attr_reader :sensor_collection, :button
|
8
|
+
def setup
|
9
|
+
@sensor_collection = mock('sensor_collection')
|
10
|
+
@button = Button.new(sensor_collection, 1)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_press_fires_sensor
|
14
|
+
sensor_collection.expects(:fire).with(:button_press_1)
|
15
|
+
button.press
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_configure_configures_sensor_for_button_press
|
19
|
+
sensor_collection.expects(:create_sensor_for).with(:button_press_1)
|
20
|
+
button.configure
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','test_helper')
|
2
|
+
require 'hardware'
|
3
|
+
|
4
|
+
module Hardware
|
5
|
+
class CanTest < Test::Unit::TestCase
|
6
|
+
def test_to_s_shows_can_name
|
7
|
+
assert_equal 'can of cola', Can.cola.to_s
|
8
|
+
assert_equal 'can of fanta', Can.fanta.to_s
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|