tenderloin 0.2.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/LICENCE +21 -0
- data/README.md +50 -0
- data/Version +1 -0
- data/bin/loin +5 -0
- data/config/default.rb +26 -0
- data/lib/tenderloin/actions/base.rb +93 -0
- data/lib/tenderloin/actions/box/add.rb +22 -0
- data/lib/tenderloin/actions/box/destroy.rb +14 -0
- data/lib/tenderloin/actions/box/download.rb +63 -0
- data/lib/tenderloin/actions/box/unpackage.rb +46 -0
- data/lib/tenderloin/actions/runner.rb +138 -0
- data/lib/tenderloin/actions/vm/boot.rb +52 -0
- data/lib/tenderloin/actions/vm/destroy.rb +18 -0
- data/lib/tenderloin/actions/vm/halt.rb +14 -0
- data/lib/tenderloin/actions/vm/import.rb +32 -0
- data/lib/tenderloin/actions/vm/move_hard_drive.rb +53 -0
- data/lib/tenderloin/actions/vm/provision.rb +71 -0
- data/lib/tenderloin/actions/vm/reload.rb +17 -0
- data/lib/tenderloin/actions/vm/shared_folders.rb +47 -0
- data/lib/tenderloin/actions/vm/start.rb +17 -0
- data/lib/tenderloin/actions/vm/up.rb +55 -0
- data/lib/tenderloin/box.rb +143 -0
- data/lib/tenderloin/busy.rb +73 -0
- data/lib/tenderloin/cli.rb +59 -0
- data/lib/tenderloin/commands.rb +154 -0
- data/lib/tenderloin/config.rb +144 -0
- data/lib/tenderloin/downloaders/base.rb +13 -0
- data/lib/tenderloin/downloaders/file.rb +21 -0
- data/lib/tenderloin/downloaders/http.rb +47 -0
- data/lib/tenderloin/env.rb +156 -0
- data/lib/tenderloin/fusion_vm.rb +85 -0
- data/lib/tenderloin/ssh.rb +49 -0
- data/lib/tenderloin/util.rb +51 -0
- data/lib/tenderloin/vm.rb +63 -0
- data/lib/tenderloin/vmx_file.rb +28 -0
- data/lib/tenderloin.rb +14 -0
- data/script/tenderloin-ssh-expect.sh +23 -0
- data/templates/Tenderfile +8 -0
- data/test/tenderloin/actions/base_test.rb +32 -0
- data/test/tenderloin/actions/box/add_test.rb +37 -0
- data/test/tenderloin/actions/box/destroy_test.rb +18 -0
- data/test/tenderloin/actions/box/download_test.rb +118 -0
- data/test/tenderloin/actions/box/unpackage_test.rb +100 -0
- data/test/tenderloin/actions/runner_test.rb +262 -0
- data/test/tenderloin/actions/vm/boot_test.rb +55 -0
- data/test/tenderloin/actions/vm/destroy_test.rb +24 -0
- data/test/tenderloin/actions/vm/down_test.rb +32 -0
- data/test/tenderloin/actions/vm/export_test.rb +88 -0
- data/test/tenderloin/actions/vm/forward_ports_test.rb +50 -0
- data/test/tenderloin/actions/vm/halt_test.rb +27 -0
- data/test/tenderloin/actions/vm/import_test.rb +36 -0
- data/test/tenderloin/actions/vm/move_hard_drive_test.rb +108 -0
- data/test/tenderloin/actions/vm/package_test.rb +181 -0
- data/test/tenderloin/actions/vm/provision_test.rb +103 -0
- data/test/tenderloin/actions/vm/reload_test.rb +44 -0
- data/test/tenderloin/actions/vm/resume_test.rb +27 -0
- data/test/tenderloin/actions/vm/shared_folders_test.rb +117 -0
- data/test/tenderloin/actions/vm/start_test.rb +28 -0
- data/test/tenderloin/actions/vm/suspend_test.rb +27 -0
- data/test/tenderloin/actions/vm/up_test.rb +98 -0
- data/test/tenderloin/box_test.rb +139 -0
- data/test/tenderloin/busy_test.rb +83 -0
- data/test/tenderloin/commands_test.rb +269 -0
- data/test/tenderloin/config_test.rb +123 -0
- data/test/tenderloin/downloaders/base_test.rb +20 -0
- data/test/tenderloin/downloaders/file_test.rb +32 -0
- data/test/tenderloin/downloaders/http_test.rb +40 -0
- data/test/tenderloin/env_test.rb +345 -0
- data/test/tenderloin/ssh_test.rb +103 -0
- data/test/tenderloin/util_test.rb +64 -0
- data/test/tenderloin/vm_test.rb +89 -0
- data/test/test_helper.rb +92 -0
- metadata +241 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
2
|
+
|
3
|
+
class SharedFoldersActionTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
@mock_vm, @vm, @action = mock_action(Tenderloin::Actions::VM::SharedFolders)
|
6
|
+
mock_config
|
7
|
+
end
|
8
|
+
|
9
|
+
def stub_shared_folders
|
10
|
+
folders = [%w{foo from to}, %w{bar bfrom bto}]
|
11
|
+
@action.expects(:shared_folders).returns(folders)
|
12
|
+
folders
|
13
|
+
end
|
14
|
+
|
15
|
+
context "collecting shared folders" do
|
16
|
+
should "return the arrays that the callback returns" do
|
17
|
+
result = [[1,2,3],[4,5,6]]
|
18
|
+
@mock_vm.expects(:invoke_callback).with(:collect_shared_folders).once.returns(result)
|
19
|
+
assert_equal result, @action.shared_folders
|
20
|
+
end
|
21
|
+
|
22
|
+
should "filter out invalid results" do
|
23
|
+
result = [[1,2,3],[4,5]]
|
24
|
+
@mock_vm.expects(:invoke_callback).with(:collect_shared_folders).once.returns(result)
|
25
|
+
assert_equal [[1,2,3]], @action.shared_folders
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "setting up shared folder metadata" do
|
30
|
+
setup do
|
31
|
+
@folders = stub_shared_folders
|
32
|
+
end
|
33
|
+
|
34
|
+
should "add all shared folders to the VM" do
|
35
|
+
share_seq = sequence("share_seq")
|
36
|
+
shared_folders = mock("shared_folders")
|
37
|
+
shared_folders.expects(:<<).in_sequence(share_seq).with() { |sf| sf.name == "foo" && sf.hostpath == "from" }
|
38
|
+
shared_folders.expects(:<<).in_sequence(share_seq).with() { |sf| sf.name == "bar" && sf.hostpath == "bfrom" }
|
39
|
+
@vm.stubs(:shared_folders).returns(shared_folders)
|
40
|
+
@vm.expects(:save).with(true).once
|
41
|
+
|
42
|
+
@action.before_boot
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "mounting the shared folders" do
|
47
|
+
setup do
|
48
|
+
@folders = stub_shared_folders
|
49
|
+
end
|
50
|
+
|
51
|
+
should "mount all shared folders to the VM" do
|
52
|
+
mount_seq = sequence("mount_seq")
|
53
|
+
ssh = mock("ssh")
|
54
|
+
@folders.each do |name, hostpath, guestpath|
|
55
|
+
ssh.expects(:exec!).with("sudo mkdir -p #{guestpath}").in_sequence(mount_seq)
|
56
|
+
@action.expects(:mount_folder).with(ssh, name, guestpath).in_sequence(mount_seq)
|
57
|
+
ssh.expects(:exec!).with("sudo chown #{Tenderloin.config.ssh.username} #{guestpath}").in_sequence(mount_seq)
|
58
|
+
end
|
59
|
+
Tenderloin::SSH.expects(:execute).yields(ssh)
|
60
|
+
|
61
|
+
@action.after_boot
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "mounting the main folder" do
|
66
|
+
setup do
|
67
|
+
@ssh = mock("ssh")
|
68
|
+
@name = "foo"
|
69
|
+
@guestpath = "bar"
|
70
|
+
@sleeptime = 0
|
71
|
+
@limit = 10
|
72
|
+
|
73
|
+
@success_return = false
|
74
|
+
end
|
75
|
+
|
76
|
+
def mount_folder
|
77
|
+
@action.mount_folder(@ssh, @name, @guestpath, @sleeptime)
|
78
|
+
end
|
79
|
+
|
80
|
+
should "execute the proper mount command" do
|
81
|
+
@ssh.expects(:exec!).with("sudo mount -t vboxsf #{@name} #{@guestpath}").returns(@success_return)
|
82
|
+
mount_folder
|
83
|
+
end
|
84
|
+
|
85
|
+
should "test type of text and text string to detect error" do
|
86
|
+
data = mock("data")
|
87
|
+
data.expects(:[]=).with(:result, !@success_return)
|
88
|
+
|
89
|
+
@ssh.expects(:exec!).yields(data, :stderr, "No such device").returns(@success_return)
|
90
|
+
mount_folder
|
91
|
+
end
|
92
|
+
|
93
|
+
should "test type of text and test string to detect success" do
|
94
|
+
data = mock("data")
|
95
|
+
data.expects(:[]=).with(:result, @success_return)
|
96
|
+
|
97
|
+
@ssh.expects(:exec!).yields(data, :stdout, "Nothing such device").returns(@success_return)
|
98
|
+
mount_folder
|
99
|
+
end
|
100
|
+
|
101
|
+
should "raise an ActionException if the command fails constantly" do
|
102
|
+
@ssh.expects(:exec!).times(@limit).returns(!@success_return)
|
103
|
+
|
104
|
+
assert_raises(Tenderloin::Actions::ActionException) {
|
105
|
+
mount_folder
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
should "not raise any exception if the command succeeded" do
|
110
|
+
@ssh.expects(:exec!).once.returns(@success_return)
|
111
|
+
|
112
|
+
assert_nothing_raised {
|
113
|
+
mount_folder
|
114
|
+
}
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
2
|
+
|
3
|
+
class StartActionTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
@mock_vm, @vm, @action = mock_action(Tenderloin::Actions::VM::Start)
|
6
|
+
mock_config
|
7
|
+
end
|
8
|
+
|
9
|
+
context "sub-actions" do
|
10
|
+
setup do
|
11
|
+
File.stubs(:file?).returns(true)
|
12
|
+
File.stubs(:exist?).returns(true)
|
13
|
+
@default_order = [Tenderloin::Actions::VM::ForwardPorts, Tenderloin::Actions::VM::SharedFolders, Tenderloin::Actions::VM::Boot]
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup_action_expectations
|
17
|
+
default_seq = sequence("default_seq")
|
18
|
+
@default_order.each do |action|
|
19
|
+
@mock_vm.expects(:add_action).with(action).once.in_sequence(default_seq)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
should "do the proper actions by default" do
|
24
|
+
setup_action_expectations
|
25
|
+
@action.prepare
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
2
|
+
|
3
|
+
class SuspendActionTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
@runner, @vm, @action = mock_action(Tenderloin::Actions::VM::Suspend)
|
6
|
+
mock_config
|
7
|
+
end
|
8
|
+
|
9
|
+
context "executing" do
|
10
|
+
setup do
|
11
|
+
@vm.stubs(:running?).returns(true)
|
12
|
+
end
|
13
|
+
|
14
|
+
should "save the state of the VM" do
|
15
|
+
@vm.expects(:save_state).with(true).once
|
16
|
+
@action.execute!
|
17
|
+
end
|
18
|
+
|
19
|
+
should "raise an ActionException if the VM is not running" do
|
20
|
+
@vm.expects(:running?).returns(false)
|
21
|
+
@vm.expects(:save_state).never
|
22
|
+
assert_raises(Tenderloin::Actions::ActionException) {
|
23
|
+
@action.execute!
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
2
|
+
|
3
|
+
class UpActionTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
@mock_vm, @vm, @action = mock_action(Tenderloin::Actions::VM::Up)
|
6
|
+
mock_config
|
7
|
+
end
|
8
|
+
|
9
|
+
context "sub-actions" do
|
10
|
+
setup do
|
11
|
+
File.stubs(:file?).returns(true)
|
12
|
+
File.stubs(:exist?).returns(true)
|
13
|
+
@default_order = [Tenderloin::Actions::VM::Import, Tenderloin::Actions::VM::ForwardPorts, Tenderloin::Actions::VM::SharedFolders, Tenderloin::Actions::VM::Boot]
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup_action_expectations
|
17
|
+
default_seq = sequence("default_seq")
|
18
|
+
@default_order.each do |action|
|
19
|
+
@mock_vm.expects(:add_action).with(action).once.in_sequence(default_seq)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
should "raise an ActionException if a dotfile exists but is not a file" do
|
24
|
+
File.expects(:file?).with(Tenderloin::Env.dotfile_path).returns(false)
|
25
|
+
assert_raises(Tenderloin::Actions::ActionException) {
|
26
|
+
@action.prepare
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
should "not raise an ActionException if dotfile doesn't exist" do
|
31
|
+
setup_action_expectations
|
32
|
+
File.stubs(:exist?).returns(false)
|
33
|
+
assert_nothing_raised { @action.prepare }
|
34
|
+
end
|
35
|
+
|
36
|
+
should "not raise an ActionException if dotfile exists but is a file" do
|
37
|
+
File.stubs(:file?).returns(true)
|
38
|
+
File.stubs(:exist?).returns(true)
|
39
|
+
setup_action_expectations
|
40
|
+
assert_nothing_raised { @action.prepare }
|
41
|
+
end
|
42
|
+
|
43
|
+
should "do the proper actions by default" do
|
44
|
+
setup_action_expectations
|
45
|
+
@action.prepare
|
46
|
+
end
|
47
|
+
|
48
|
+
should "add in the provisioning step if enabled" do
|
49
|
+
mock_config do |config|
|
50
|
+
config.chef.enabled = true
|
51
|
+
end
|
52
|
+
|
53
|
+
@default_order.push(Tenderloin::Actions::VM::Provision)
|
54
|
+
setup_action_expectations
|
55
|
+
@action.prepare
|
56
|
+
end
|
57
|
+
|
58
|
+
should "add in the action to move hard drive if config is set" do
|
59
|
+
mock_config do |config|
|
60
|
+
File.expects(:directory?).with("foo").returns(true)
|
61
|
+
config.vm.hd_location = "foo"
|
62
|
+
end
|
63
|
+
|
64
|
+
@default_order.insert(0, Tenderloin::Actions::VM::MoveHardDrive)
|
65
|
+
setup_action_expectations
|
66
|
+
@action.prepare
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "callbacks" do
|
71
|
+
should "call persist and mac address setup after import" do
|
72
|
+
boot_seq = sequence("boot")
|
73
|
+
@action.expects(:persist).once.in_sequence(boot_seq)
|
74
|
+
@action.expects(:setup_mac_address).once.in_sequence(boot_seq)
|
75
|
+
@action.after_import
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "persisting" do
|
80
|
+
should "persist the VM with Env" do
|
81
|
+
@vm.stubs(:uuid)
|
82
|
+
Tenderloin::Env.expects(:persist_vm).with(@vm).once
|
83
|
+
@action.persist
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "setting up MAC address" do
|
88
|
+
should "match the mac address with the base" do
|
89
|
+
nic = mock("nic")
|
90
|
+
nic.expects(:macaddress=).once
|
91
|
+
|
92
|
+
@vm.expects(:nics).returns([nic]).once
|
93
|
+
@vm.expects(:save).with(true).once
|
94
|
+
|
95
|
+
@action.setup_mac_address
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class BoxTest < Test::Unit::TestCase
|
4
|
+
context "class methods" do
|
5
|
+
context "listing all boxes" do
|
6
|
+
setup do
|
7
|
+
Dir.stubs(:open)
|
8
|
+
File.stubs(:directory?).returns(true)
|
9
|
+
|
10
|
+
@boxes_path = "foo"
|
11
|
+
Tenderloin::Env.stubs(:boxes_path).returns(@boxes_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
should "open the boxes directory" do
|
15
|
+
Dir.expects(:open).with(Tenderloin::Env.boxes_path)
|
16
|
+
Tenderloin::Box.all
|
17
|
+
end
|
18
|
+
|
19
|
+
should "return an array" do
|
20
|
+
result = Tenderloin::Box.all
|
21
|
+
assert result.is_a?(Array)
|
22
|
+
end
|
23
|
+
|
24
|
+
should "not return the '.' and '..' directories" do
|
25
|
+
dir = [".", "..", "..", ".", ".."]
|
26
|
+
Dir.expects(:open).yields(dir)
|
27
|
+
result = Tenderloin::Box.all
|
28
|
+
assert result.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
should "return the other directories" do
|
32
|
+
dir = [".", "foo", "bar", "baz"]
|
33
|
+
Dir.expects(:open).yields(dir)
|
34
|
+
result = Tenderloin::Box.all
|
35
|
+
assert_equal ["foo", "bar", "baz"], result
|
36
|
+
end
|
37
|
+
|
38
|
+
should "ignore the files" do
|
39
|
+
dir = ["foo", "bar"]
|
40
|
+
files = [true, false]
|
41
|
+
Dir.expects(:open).yields(dir)
|
42
|
+
dir_sequence = sequence("directory")
|
43
|
+
dir.each_with_index do |dir, index|
|
44
|
+
File.expects(:directory?).with(File.join(@boxes_path, dir)).returns(files[index]).in_sequence(dir_sequence)
|
45
|
+
end
|
46
|
+
|
47
|
+
result = Tenderloin::Box.all
|
48
|
+
assert_equal ["foo"], result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "finding" do
|
53
|
+
setup do
|
54
|
+
@dir = "foo"
|
55
|
+
@name = "bar"
|
56
|
+
Tenderloin::Box.stubs(:directory).with(@name).returns(@dir)
|
57
|
+
end
|
58
|
+
|
59
|
+
should "return nil if the box doesn't exist" do
|
60
|
+
File.expects(:directory?).with(@dir).once.returns(false)
|
61
|
+
assert_nil Tenderloin::Box.find(@name)
|
62
|
+
end
|
63
|
+
|
64
|
+
should "return a box object with the proper name set" do
|
65
|
+
File.expects(:directory?).with(@dir).once.returns(true)
|
66
|
+
result = Tenderloin::Box.find(@name)
|
67
|
+
assert result
|
68
|
+
assert_equal @name, result.name
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "adding" do
|
73
|
+
setup do
|
74
|
+
@name = "foo"
|
75
|
+
@uri = "bar"
|
76
|
+
end
|
77
|
+
|
78
|
+
should "create a new instance, set the variables, and add it" do
|
79
|
+
box = mock("box")
|
80
|
+
box.expects(:name=).with(@name)
|
81
|
+
box.expects(:uri=).with(@uri)
|
82
|
+
box.expects(:add).once
|
83
|
+
Tenderloin::Box.expects(:new).returns(box)
|
84
|
+
Tenderloin::Box.add(@name, @uri)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "box directory" do
|
89
|
+
setup do
|
90
|
+
@name = "foo"
|
91
|
+
@box_dir = File.join(Tenderloin::Env.boxes_path, @name)
|
92
|
+
end
|
93
|
+
|
94
|
+
should "return the boxes_path joined with the name" do
|
95
|
+
assert_equal @box_dir, Tenderloin::Box.directory(@name)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "instance methods" do
|
101
|
+
setup do
|
102
|
+
@box = Tenderloin::Box.new
|
103
|
+
end
|
104
|
+
|
105
|
+
should "execute the Add action when add is called" do
|
106
|
+
@box.expects(:execute!).with(Tenderloin::Actions::Box::Add).once
|
107
|
+
@box.add
|
108
|
+
end
|
109
|
+
|
110
|
+
context "box directory" do
|
111
|
+
setup do
|
112
|
+
@box.name = "foo"
|
113
|
+
end
|
114
|
+
|
115
|
+
should "return the boxes_path joined with the name" do
|
116
|
+
result = mock("object")
|
117
|
+
Tenderloin::Box.expects(:directory).with(@box.name).returns(result)
|
118
|
+
assert result.equal?(@box.directory)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "destroying" do
|
123
|
+
should "execute the destroy action" do
|
124
|
+
@box.expects(:execute!).with(Tenderloin::Actions::Box::Destroy).once
|
125
|
+
@box.destroy
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "ovf file" do
|
130
|
+
setup do
|
131
|
+
@box.stubs(:directory).returns("foo")
|
132
|
+
end
|
133
|
+
|
134
|
+
should "be the directory joined with the config ovf file" do
|
135
|
+
assert_equal File.join(@box.directory, Tenderloin.config.vm.box_ovf), @box.ovf_file
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class BusyTest < Test::Unit::TestCase
|
4
|
+
context "waiting for not busy" do
|
5
|
+
setup do
|
6
|
+
Tenderloin::Busy.reset_trap_thread!
|
7
|
+
end
|
8
|
+
|
9
|
+
should "run in a thread" do
|
10
|
+
Thread.expects(:new).once.returns(nil)
|
11
|
+
Tenderloin::Busy.wait_for_not_busy
|
12
|
+
end
|
13
|
+
|
14
|
+
should "not start a thread multiple times" do
|
15
|
+
Thread.expects(:new).once.returns("foo")
|
16
|
+
Tenderloin::Busy.wait_for_not_busy
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "during an action in a busy block" do
|
21
|
+
should "report as busy" do
|
22
|
+
Tenderloin.busy do
|
23
|
+
# Inside the block Tenderloin.busy? should be true
|
24
|
+
assert Tenderloin.busy?
|
25
|
+
end
|
26
|
+
|
27
|
+
#After the block finishes Tenderloin.busy? should be false
|
28
|
+
assert !Tenderloin.busy?
|
29
|
+
end
|
30
|
+
|
31
|
+
should "set busy to false upon exception and reraise the error" do
|
32
|
+
assert_raise Exception do
|
33
|
+
Tenderloin.busy do
|
34
|
+
assert Tenderloin.busy?
|
35
|
+
raise Exception
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
assert !Tenderloin.busy?
|
40
|
+
end
|
41
|
+
|
42
|
+
should "complete the trap thread even if an exception occurs" do
|
43
|
+
trap_thread = mock("trap_thread")
|
44
|
+
trap_thread.expects(:join).once
|
45
|
+
Tenderloin::Busy.stubs(:trap_thread).returns(trap_thread)
|
46
|
+
|
47
|
+
assert_raise Exception do
|
48
|
+
Tenderloin.busy do
|
49
|
+
raise Exception
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
should "report busy to the outside world regardless of thread" do
|
55
|
+
Thread.new do
|
56
|
+
Tenderloin.busy do
|
57
|
+
sleep(2)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
# Give the thread time to start
|
61
|
+
sleep(1)
|
62
|
+
|
63
|
+
# While the above thread is executing tenderloin should be busy
|
64
|
+
assert Tenderloin.busy?
|
65
|
+
end
|
66
|
+
|
67
|
+
should "run the action in a new thread" do
|
68
|
+
runner_thread = nil
|
69
|
+
Tenderloin.busy do
|
70
|
+
runner_thread = Thread.current
|
71
|
+
end
|
72
|
+
|
73
|
+
assert_not_equal Thread.current, runner_thread
|
74
|
+
end
|
75
|
+
|
76
|
+
should "trap INT" do
|
77
|
+
trap_seq = sequence("trap_seq")
|
78
|
+
Signal.expects(:trap).with("INT", anything).once.in_sequence(trap_seq)
|
79
|
+
Signal.expects(:trap).with("INT", "DEFAULT").once.in_sequence(trap_seq)
|
80
|
+
Tenderloin.busy do; end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|