bmabey-vagrant 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. data/.gitignore +12 -0
  2. data/Gemfile +17 -0
  3. data/LICENSE +21 -0
  4. data/README.md +53 -0
  5. data/Rakefile +41 -0
  6. data/VERSION +1 -0
  7. data/bin/.gitignore +0 -0
  8. data/bin/vagrant +15 -0
  9. data/bin/vagrant-box +34 -0
  10. data/bin/vagrant-down +27 -0
  11. data/bin/vagrant-halt +28 -0
  12. data/bin/vagrant-init +27 -0
  13. data/bin/vagrant-package +29 -0
  14. data/bin/vagrant-reload +29 -0
  15. data/bin/vagrant-resume +27 -0
  16. data/bin/vagrant-ssh +27 -0
  17. data/bin/vagrant-status +29 -0
  18. data/bin/vagrant-suspend +27 -0
  19. data/bin/vagrant-up +29 -0
  20. data/config/default.rb +26 -0
  21. data/keys/README.md +10 -0
  22. data/keys/vagrant +27 -0
  23. data/keys/vagrant.pub +1 -0
  24. data/lib/vagrant.rb +19 -0
  25. data/lib/vagrant/actions/base.rb +118 -0
  26. data/lib/vagrant/actions/box/add.rb +22 -0
  27. data/lib/vagrant/actions/box/destroy.rb +14 -0
  28. data/lib/vagrant/actions/box/download.rb +72 -0
  29. data/lib/vagrant/actions/box/unpackage.rb +43 -0
  30. data/lib/vagrant/actions/collection.rb +36 -0
  31. data/lib/vagrant/actions/runner.rb +132 -0
  32. data/lib/vagrant/actions/vm/boot.rb +47 -0
  33. data/lib/vagrant/actions/vm/customize.rb +17 -0
  34. data/lib/vagrant/actions/vm/destroy.rb +23 -0
  35. data/lib/vagrant/actions/vm/down.rb +12 -0
  36. data/lib/vagrant/actions/vm/export.rb +41 -0
  37. data/lib/vagrant/actions/vm/forward_ports.rb +46 -0
  38. data/lib/vagrant/actions/vm/halt.rb +14 -0
  39. data/lib/vagrant/actions/vm/import.rb +18 -0
  40. data/lib/vagrant/actions/vm/move_hard_drive.rb +51 -0
  41. data/lib/vagrant/actions/vm/package.rb +65 -0
  42. data/lib/vagrant/actions/vm/provision.rb +49 -0
  43. data/lib/vagrant/actions/vm/reload.rb +17 -0
  44. data/lib/vagrant/actions/vm/resume.rb +16 -0
  45. data/lib/vagrant/actions/vm/shared_folders.rb +81 -0
  46. data/lib/vagrant/actions/vm/start.rb +18 -0
  47. data/lib/vagrant/actions/vm/suspend.rb +16 -0
  48. data/lib/vagrant/actions/vm/up.rb +40 -0
  49. data/lib/vagrant/active_list.rb +73 -0
  50. data/lib/vagrant/box.rb +152 -0
  51. data/lib/vagrant/busy.rb +73 -0
  52. data/lib/vagrant/commands.rb +219 -0
  53. data/lib/vagrant/config.rb +183 -0
  54. data/lib/vagrant/downloaders/base.rb +16 -0
  55. data/lib/vagrant/downloaders/file.rb +17 -0
  56. data/lib/vagrant/downloaders/http.rb +47 -0
  57. data/lib/vagrant/environment.rb +263 -0
  58. data/lib/vagrant/provisioners/base.rb +29 -0
  59. data/lib/vagrant/provisioners/chef.rb +103 -0
  60. data/lib/vagrant/provisioners/chef_server.rb +84 -0
  61. data/lib/vagrant/provisioners/chef_solo.rb +97 -0
  62. data/lib/vagrant/ssh.rb +104 -0
  63. data/lib/vagrant/util.rb +51 -0
  64. data/lib/vagrant/util/errors.rb +36 -0
  65. data/lib/vagrant/util/stacked_proc_runner.rb +35 -0
  66. data/lib/vagrant/util/template_renderer.rb +83 -0
  67. data/lib/vagrant/vm.rb +61 -0
  68. data/templates/Vagrantfile.erb +8 -0
  69. data/templates/errors.yml +117 -0
  70. data/test/test_helper.rb +163 -0
  71. data/test/vagrant/actions/base_test.rb +32 -0
  72. data/test/vagrant/actions/box/add_test.rb +37 -0
  73. data/test/vagrant/actions/box/destroy_test.rb +18 -0
  74. data/test/vagrant/actions/box/download_test.rb +131 -0
  75. data/test/vagrant/actions/box/unpackage_test.rb +100 -0
  76. data/test/vagrant/actions/collection_test.rb +110 -0
  77. data/test/vagrant/actions/runner_test.rb +265 -0
  78. data/test/vagrant/actions/vm/boot_test.rb +55 -0
  79. data/test/vagrant/actions/vm/customize_test.rb +16 -0
  80. data/test/vagrant/actions/vm/destroy_test.rb +36 -0
  81. data/test/vagrant/actions/vm/down_test.rb +32 -0
  82. data/test/vagrant/actions/vm/export_test.rb +88 -0
  83. data/test/vagrant/actions/vm/forward_ports_test.rb +104 -0
  84. data/test/vagrant/actions/vm/halt_test.rb +27 -0
  85. data/test/vagrant/actions/vm/import_test.rb +43 -0
  86. data/test/vagrant/actions/vm/move_hard_drive_test.rb +108 -0
  87. data/test/vagrant/actions/vm/package_test.rb +181 -0
  88. data/test/vagrant/actions/vm/provision_test.rb +108 -0
  89. data/test/vagrant/actions/vm/reload_test.rb +47 -0
  90. data/test/vagrant/actions/vm/resume_test.rb +27 -0
  91. data/test/vagrant/actions/vm/shared_folders_test.rb +176 -0
  92. data/test/vagrant/actions/vm/start_test.rb +36 -0
  93. data/test/vagrant/actions/vm/suspend_test.rb +27 -0
  94. data/test/vagrant/actions/vm/up_test.rb +107 -0
  95. data/test/vagrant/active_list_test.rb +190 -0
  96. data/test/vagrant/box_test.rb +151 -0
  97. data/test/vagrant/busy_test.rb +83 -0
  98. data/test/vagrant/commands_test.rb +307 -0
  99. data/test/vagrant/config_test.rb +256 -0
  100. data/test/vagrant/downloaders/base_test.rb +27 -0
  101. data/test/vagrant/downloaders/file_test.rb +26 -0
  102. data/test/vagrant/downloaders/http_test.rb +40 -0
  103. data/test/vagrant/environment_test.rb +607 -0
  104. data/test/vagrant/provisioners/base_test.rb +33 -0
  105. data/test/vagrant/provisioners/chef_server_test.rb +187 -0
  106. data/test/vagrant/provisioners/chef_solo_test.rb +149 -0
  107. data/test/vagrant/provisioners/chef_test.rb +117 -0
  108. data/test/vagrant/ssh_test.rb +222 -0
  109. data/test/vagrant/util/errors_test.rb +57 -0
  110. data/test/vagrant/util/stacked_proc_runner_test.rb +43 -0
  111. data/test/vagrant/util/template_renderer_test.rb +138 -0
  112. data/test/vagrant/util_test.rb +64 -0
  113. data/test/vagrant/vm_test.rb +114 -0
  114. data/vagrant.gemspec +216 -0
  115. metadata +285 -0
@@ -0,0 +1,32 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class BaseActionTest < Test::Unit::TestCase
4
+ should "include the util class so subclasses have access to it" do
5
+ assert Vagrant::Actions::Base.include?(Vagrant::Util)
6
+ end
7
+
8
+ context "base instance" do
9
+ setup do
10
+ @mock_vm = mock("vm")
11
+ @base = Vagrant::Actions::Base.new(@mock_vm)
12
+ end
13
+
14
+ should "allow read-only access to the runner" do
15
+ assert_equal @mock_vm, @base.runner
16
+ end
17
+
18
+ should "implement prepare which does nothing" do
19
+ assert_nothing_raised do
20
+ assert @base.respond_to?(:prepare)
21
+ @base.prepare
22
+ end
23
+ end
24
+
25
+ should "implement the execute! method which does nothing" do
26
+ assert_nothing_raised do
27
+ assert @base.respond_to?(:execute!)
28
+ @base.execute!
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,37 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class AddBoxActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @runner, @vm, @action = mock_action(Vagrant::Actions::Box::Add)
6
+ mock_config
7
+ end
8
+
9
+ context "prepare" do
10
+ setup do
11
+ @default_order = [Vagrant::Actions::Box::Download, Vagrant::Actions::Box::Unpackage]
12
+ @runner.stubs(:directory).returns("foo")
13
+ File.stubs(:exists?).returns(false)
14
+ end
15
+
16
+ def setup_action_expectations
17
+ default_seq = sequence("default_seq")
18
+ @default_order.each do |action|
19
+ @runner.expects(:add_action).with(action).once.in_sequence(default_seq)
20
+ end
21
+ end
22
+
23
+ should "setup the proper sequence of actions" do
24
+ setup_action_expectations
25
+ @action.prepare
26
+ end
27
+
28
+ should "result in an action exception if the box already exists" do
29
+ File.expects(:exists?).once.returns(true)
30
+ @runner.expects(:name).once.returns('foo')
31
+ @runner.expects(:add_action).never
32
+ assert_raise Vagrant::Actions::ActionException do
33
+ @action.prepare
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class DestroyBoxActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @name = "foo"
6
+ @dir = "foo"
7
+ @runner, @vm, @action = mock_action(Vagrant::Actions::Box::Destroy)
8
+ @runner.stubs(:directory).returns(@dir)
9
+ mock_config
10
+ end
11
+
12
+ context "executing" do
13
+ should "rm_rf the directory" do
14
+ FileUtils.expects(:rm_rf).with(@dir).once
15
+ @action.execute!
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,131 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class DownloadBoxActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @uri = "foo.com"
6
+ @runner, @vm, @action = mock_action(Vagrant::Actions::Box::Download)
7
+ @runner.stubs(:uri).returns(@uri)
8
+ @runner.stubs(:temp_path=)
9
+ mock_config
10
+
11
+ @runner.env.stubs(:tmp_path).returns("foo")
12
+ end
13
+
14
+ context "preparing" do
15
+ setup do
16
+ @uri = mock("uri")
17
+ @uri.stubs(:is_a?).returns(false)
18
+ URI.stubs(:parse).returns(@uri)
19
+
20
+ @downloader = mock("downloader")
21
+ Vagrant::Downloaders::File.any_instance.stubs(:prepare)
22
+ Vagrant::Downloaders::HTTP.any_instance.stubs(:prepare)
23
+ end
24
+
25
+ should "raise an exception if no URI type is matched" do
26
+ @uri.stubs(:is_a?).returns(false)
27
+ assert_raises(Vagrant::Actions::ActionException) {
28
+ @action.prepare
29
+ }
30
+ end
31
+
32
+ should "call #prepare on the downloader" do
33
+ @downloader.expects(:prepare).with(@runner.uri).once
34
+ Vagrant::Downloaders::File.expects(:new).returns(@downloader)
35
+ @uri.stubs(:is_a?).with(URI::Generic).returns(true)
36
+ @action.prepare
37
+ end
38
+
39
+ should "set the downloader to file if URI is generic" do
40
+ @uri.stubs(:is_a?).with(URI::Generic).returns(true)
41
+ @action.prepare
42
+ assert @action.downloader.is_a?(Vagrant::Downloaders::File)
43
+ end
44
+
45
+ should "set the downloader to HTTP if URI is HTTP" do
46
+ @uri.stubs(:is_a?).with(URI::HTTP).returns(true)
47
+ @action.prepare
48
+ assert @action.downloader.is_a?(Vagrant::Downloaders::HTTP)
49
+ end
50
+ end
51
+
52
+ context "executing" do
53
+ setup do
54
+ @path = "foo"
55
+
56
+ @tempfile = mock("tempfile")
57
+ @tempfile.stubs(:path).returns(@path)
58
+
59
+ @action.stubs(:with_tempfile).yields(@tempfile)
60
+ @action.stubs(:download_to)
61
+ end
62
+
63
+ should "make a tempfile and copy the URI contents to it" do
64
+ @action.expects(:with_tempfile).yields(@tempfile)
65
+ @action.expects(:download_to).with(@tempfile)
66
+ @action.execute!
67
+ end
68
+
69
+ should "save the tempfile path" do
70
+ @runner.expects(:temp_path=).with(@path).once
71
+ @action.execute!
72
+ end
73
+ end
74
+
75
+ context "rescue" do
76
+ should "call cleanup method" do
77
+ @action.expects(:cleanup).once
78
+ @action.rescue(nil)
79
+ end
80
+ end
81
+
82
+ context "tempfile" do
83
+ should "create a tempfile in the vagrant tmp directory" do
84
+ File.expects(:open).with { |name, bitmask|
85
+ name =~ /#{Vagrant::Actions::Box::Download::BASENAME}/ && name =~ /#{@runner.env.tmp_path}/
86
+ }.once
87
+ @action.with_tempfile
88
+ end
89
+
90
+ should "yield the tempfile object" do
91
+ @tempfile = mock("tempfile")
92
+ File.expects(:open).yields(@tempfile)
93
+
94
+ @action.with_tempfile do |otherfile|
95
+ assert @tempfile.equal?(otherfile)
96
+ end
97
+ end
98
+ end
99
+
100
+ context "cleaning up" do
101
+ setup do
102
+ @temp_path = "foo"
103
+ @runner.stubs(:temp_path).returns(@temp_path)
104
+ File.stubs(:exist?).returns(true)
105
+ end
106
+
107
+ should "delete the temporary file if it exists" do
108
+ File.expects(:unlink).with(@temp_path).once
109
+ @action.cleanup
110
+ end
111
+
112
+ should "not delete anything if it doesn't exist" do
113
+ File.stubs(:exist?).returns(false)
114
+ File.expects(:unlink).never
115
+ @action.cleanup
116
+ end
117
+ end
118
+
119
+ context "downloading" do
120
+ setup do
121
+ @downloader = mock("downloader")
122
+ @action.stubs(:downloader).returns(@downloader)
123
+ end
124
+
125
+ should "call download! on the download with the URI and tempfile" do
126
+ tempfile = "foo"
127
+ @downloader.expects(:download!).with(@runner.uri, tempfile)
128
+ @action.download_to(tempfile)
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,100 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class UnpackageBoxActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @runner, @vm, @action = mock_action(Vagrant::Actions::Box::Unpackage)
6
+ @runner.stubs(:name).returns("foo")
7
+ @runner.stubs(:temp_path).returns("bar")
8
+ mock_config
9
+
10
+ @runner.env.stubs(:boxes_path).returns("bar")
11
+ end
12
+
13
+ context "executing" do
14
+ setup do
15
+ @runner.stubs(:invoke_around_callback).yields
16
+ end
17
+
18
+ should "execute the proper actions in the proper order" do
19
+ exec_seq = sequence("exec_seq")
20
+ @action.expects(:setup_box_dir).in_sequence(exec_seq)
21
+ @action.expects(:decompress).in_sequence(exec_seq)
22
+ @action.execute!
23
+ end
24
+
25
+ should "execute it in a around block" do
26
+ @runner.expects(:invoke_around_callback).with(:unpackage).once
27
+ @action.execute!
28
+ end
29
+ end
30
+
31
+ context "rescuing" do
32
+ setup do
33
+ File.stubs(:directory?).returns(false)
34
+ FileUtils.stubs(:rm_rf)
35
+
36
+ @box_dir = mock("foo")
37
+ @action.stubs(:box_dir).returns(@box_dir)
38
+ end
39
+
40
+ should "do nothing if a directory doesn't exist" do
41
+ FileUtils.expects(:rm_rf).never
42
+ @action.rescue(nil)
43
+ end
44
+
45
+ should "remove the box directory if it exists" do
46
+ File.expects(:directory?).returns(true)
47
+ FileUtils.expects(:rm_rf).with(@box_dir).once
48
+ @action.rescue(nil)
49
+ end
50
+ end
51
+
52
+ context "box directory" do
53
+ should "return the runner directory" do
54
+ result = mock("object")
55
+ @runner.expects(:directory).once.returns(result)
56
+ assert result.equal?(@action.box_dir)
57
+ end
58
+ end
59
+
60
+ context "setting up the box directory" do
61
+ setup do
62
+ File.stubs(:directory?).returns(false)
63
+ FileUtils.stubs(:mkdir_p)
64
+
65
+ @box_dir = "foo"
66
+ @action.stubs(:box_dir).returns(@box_dir)
67
+ end
68
+
69
+ should "error and exit if the directory exists" do
70
+ File.expects(:directory?).returns(true)
71
+ @action.expects(:error_and_exit).with(:box_already_exists, :box_name => @runner.name).once
72
+ @action.setup_box_dir
73
+ end
74
+
75
+ should "create the directory" do
76
+ FileUtils.expects(:mkdir_p).with(@box_dir).once
77
+ @action.setup_box_dir
78
+ end
79
+ end
80
+
81
+ context "decompressing" do
82
+ setup do
83
+ @box_dir = "foo"
84
+
85
+ @action.stubs(:box_dir).returns(@box_dir)
86
+ Dir.stubs(:chdir).yields
87
+ Archive::Tar::Minitar.stubs(:unpack)
88
+ end
89
+
90
+ should "change to the box directory" do
91
+ Dir.expects(:chdir).with(@box_dir)
92
+ @action.decompress
93
+ end
94
+
95
+ should "open the tar file within the new directory, and extract it all" do
96
+ Archive::Tar::Minitar.expects(:unpack).with(@runner.temp_path, @box_dir).once
97
+ @action.decompress
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,110 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class CollectionTest < Test::Unit::TestCase
4
+ context "checking uniqueness" do
5
+ setup do
6
+ @actions = Vagrant::Actions::Collection.new([1])
7
+ end
8
+
9
+ should "return true if there are duplicate classes in the collection" do
10
+ @actions << 1
11
+ assert @actions.duplicates?
12
+ end
13
+
14
+ should "return false it all the classes are unique" do
15
+ @actions << 1.0 << "foo"
16
+ assert !@actions.duplicates?
17
+ end
18
+
19
+ should "raise an exception when there are duplicates" do
20
+ @actions << 1
21
+ assert_raise Vagrant::Actions::DuplicateActionException do
22
+ @actions.duplicates!
23
+ end
24
+ end
25
+
26
+ should "not raise an exception when there are no duplicates" do
27
+ @actions << 1.0 << "foo"
28
+ assert_nothing_raised do
29
+ @actions.duplicates!
30
+ end
31
+ end
32
+ end
33
+
34
+ context "verifying dependencies" do
35
+ setup do
36
+ @mock_action = mock('action')
37
+ @mock_action.stubs(:class).returns(MockAction)
38
+
39
+ @mock_action2 = mock('action2')
40
+ @mock_action2.stubs(:class).returns(MockActionOther)
41
+ # see test_helper
42
+ stub_default_action_dependecies(@mock_action)
43
+ stub_default_action_dependecies(@mock_action2)
44
+ end
45
+
46
+ context "that come before an action" do
47
+ setup do
48
+ @mock_action.stubs(:follows).returns([MockActionOther])
49
+ end
50
+ should "raise an exception if they are not met" do
51
+ assert_raise Vagrant::Actions::DependencyNotSatisfiedException do
52
+ collection.new([@mock_action]).dependencies!
53
+ end
54
+ end
55
+
56
+ should "not raise an exception if they are met" do
57
+ assert_nothing_raised do
58
+ collection.new([@mock_action2, @mock_action]).dependencies!
59
+ end
60
+ end
61
+ end
62
+
63
+ context "that follow an an action" do
64
+ setup do
65
+ @mock_action.stubs(:precedes).returns([MockActionOther])
66
+ end
67
+
68
+ should "raise an exception if they are not met" do
69
+ assert_raise Vagrant::Actions::DependencyNotSatisfiedException do
70
+ collection.new([@mock_action]).dependencies!
71
+ end
72
+ end
73
+
74
+ should "not raise an exception if they are met" do
75
+ assert_nothing_raised do
76
+ collection.new([@mock_action, @mock_action2]).dependencies!
77
+ end
78
+ end
79
+ end
80
+
81
+ context "that are before and after an action" do
82
+ setup do
83
+ @mock_action.stubs(:precedes).returns([MockActionOther])
84
+ @mock_action.stubs(:follows).returns([MockActionOther])
85
+ end
86
+
87
+ should "raise an exception if they are met" do
88
+ assert_raise Vagrant::Actions::DependencyNotSatisfiedException do
89
+ collection.new([@mock_action2, @mock_action]).dependencies!
90
+ end
91
+ end
92
+
93
+ should "not raise and exception if they are met" do
94
+ assert_nothing_raised do
95
+ collection.new([@mock_action2, @mock_action, @mock_action2]).dependencies!
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ context "klasses" do
102
+ should "return a list of the collection element's classes" do
103
+ @action = mock('action')
104
+ assert_equal collection.new([@action]).klasses, [@action.class]
105
+ assert_equal collection.new([@action, 1.0, "foo"]).klasses, [@action.class, Float, String]
106
+ end
107
+ end
108
+
109
+ def collection; Vagrant::Actions::Collection end
110
+ end
@@ -0,0 +1,265 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class ActionRunnerTest < Test::Unit::TestCase
4
+ def mock_fake_action(action_klass = nil, runner = nil)
5
+ action = action_klass ? action_klass.new(runner) : mock("action")
6
+ action.stubs(:prepare)
7
+ action.stubs(:execute!)
8
+ action.stubs(:cleanup)
9
+ stub_default_action_dependecies(action)
10
+ action
11
+ end
12
+
13
+ context "callbacks" do
14
+ setup do
15
+ @runner = Vagrant::Actions::Runner.new
16
+ end
17
+
18
+ context "around callbacks" do
19
+ should "invoke before/after_name for around callbacks" do
20
+ block_obj = mock("block_obj")
21
+ around_seq = sequence("around_seq")
22
+ @runner.expects(:invoke_callback).with(:before_foo).once.in_sequence(around_seq)
23
+ block_obj.expects(:foo).once.in_sequence(around_seq)
24
+ @runner.expects(:invoke_callback).with(:after_foo).once.in_sequence(around_seq)
25
+
26
+ @runner.invoke_around_callback(:foo) do
27
+ block_obj.foo
28
+ end
29
+ end
30
+
31
+ should "forward arguments to invoke_callback" do
32
+ @runner.expects(:invoke_callback).with(:before_foo, "foo").once
33
+ @runner.expects(:invoke_callback).with(:after_foo, "foo").once
34
+ @runner.invoke_around_callback(:foo, "foo") do; end
35
+ end
36
+ end
37
+
38
+ should "not invoke callback on actions which don't respond to it" do
39
+ action = mock("action")
40
+ action.stubs(:respond_to?).with(:foo).returns(false)
41
+ action.expects(:foo).never
42
+
43
+ assert_nothing_raised do
44
+ @runner.actions << action
45
+ @runner.invoke_callback(:foo)
46
+ end
47
+ end
48
+
49
+ should "invoke callback on actions which do respond to the method" do
50
+ action = mock("action")
51
+ action.expects(:foo).once
52
+
53
+ @runner.actions << action
54
+ @runner.invoke_callback(:foo)
55
+ end
56
+
57
+ should "collect all the results and return them as an array" do
58
+ result = []
59
+ 3.times do |i|
60
+ action = mock("action#{i}")
61
+ action.expects(:foo).returns("foo#{i}").once
62
+
63
+ @runner.actions << action
64
+ result << "foo#{i}"
65
+ end
66
+
67
+ assert_equal result, @runner.invoke_callback(:foo)
68
+ end
69
+ end
70
+
71
+ context "finding actions" do
72
+ setup do
73
+ @runner = Vagrant::Actions::Runner.new
74
+ end
75
+
76
+ should "return nil if the action could not be found" do
77
+ assert_nil @runner.find_action(Vagrant::Actions::VM::Export)
78
+ end
79
+
80
+ should "return the first instance of the action found" do
81
+ @runner.add_action(Vagrant::Actions::VM::Export)
82
+ @runner.add_action(Vagrant::Actions::VM::Export)
83
+
84
+ assert @runner.actions[0].equal?(@runner.find_action(Vagrant::Actions::VM::Export))
85
+ end
86
+ end
87
+
88
+ context "adding actions" do
89
+ setup do
90
+ @runner = Vagrant::Actions::Runner.new
91
+ end
92
+
93
+ should "initialize the action when added" do
94
+ action_klass = mock("action_class")
95
+ action_inst = mock("action_inst")
96
+ action_klass.expects(:new).once.returns(action_inst)
97
+ @runner.add_action(action_klass)
98
+ assert_equal 1, @runner.actions.length
99
+ end
100
+
101
+ should "initialize the action with given arguments when added" do
102
+ action_klass = mock("action_class")
103
+ action_klass.expects(:new).with(@runner, "foo", "bar").once
104
+ @runner.add_action(action_klass, "foo", "bar")
105
+ end
106
+ end
107
+
108
+ context "class method execute" do
109
+ should "run actions on class method execute!" do
110
+ vm = mock("vm")
111
+ execute_seq = sequence("execute_seq")
112
+ Vagrant::Actions::Runner.expects(:new).returns(vm).in_sequence(execute_seq)
113
+ vm.expects(:add_action).with("foo").in_sequence(execute_seq)
114
+ vm.expects(:execute!).once.in_sequence(execute_seq)
115
+
116
+ Vagrant::Actions::Runner.execute!("foo")
117
+ end
118
+
119
+ should "forward arguments to add_action on class method execute!" do
120
+ vm = mock("vm")
121
+ execute_seq = sequence("execute_seq")
122
+ Vagrant::Actions::Runner.expects(:new).returns(vm).in_sequence(execute_seq)
123
+ vm.expects(:add_action).with("foo", "bar", "baz").in_sequence(execute_seq)
124
+ vm.expects(:execute!).once.in_sequence(execute_seq)
125
+
126
+ Vagrant::Actions::Runner.execute!("foo", "bar", "baz")
127
+ end
128
+ end
129
+
130
+ context "instance method execute" do
131
+ setup do
132
+ @runner = Vagrant::Actions::Runner.new
133
+ @runner.stubs(:action_klasses).returns([Vagrant::Actions::Base])
134
+ end
135
+
136
+ should "clear the actions and run a single action if given to execute!" do
137
+ action = mock("action")
138
+ run_action = mock("action_run")
139
+ stub_default_action_dependecies(run_action)
140
+ run_class = mock("run_class")
141
+ run_class.expects(:new).once.returns(run_action)
142
+ @runner.actions << action
143
+
144
+ [:prepare, :execute!, :cleanup].each do |method|
145
+ action.expects(method).never
146
+ run_action.expects(method).once
147
+ end
148
+
149
+ @runner.execute!(run_class)
150
+ end
151
+
152
+ should "clear actions after running execute!" do
153
+ @runner.actions << mock_fake_action
154
+ assert !@runner.actions.empty? # sanity
155
+ @runner.execute!
156
+ assert @runner.actions.empty?
157
+ end
158
+
159
+ should "run #prepare on all actions, then #execute!" do
160
+ action_seq = sequence("action_seq")
161
+ actions = []
162
+ [MockAction, MockActionOther].each_with_index do |klass, i|
163
+ action = mock("action#{i}")
164
+ action.expects(:class).returns(klass)
165
+ stub_default_action_dependecies(action, klass)
166
+ @runner.actions << action
167
+ actions << action
168
+ end
169
+
170
+ [:prepare, :execute!, :cleanup].each do |method|
171
+ actions.each do |action|
172
+ action.expects(method).once.in_sequence(action_seq)
173
+ end
174
+ end
175
+
176
+ @runner.execute!
177
+ end
178
+
179
+ context "exceptions" do
180
+ setup do
181
+ @actions = [MockAction, MockActionOther].map do |klass|
182
+ action = mock_fake_action
183
+ action.expects(:class).returns(klass)
184
+ action.stubs(:rescue)
185
+ @runner.actions << action
186
+ action
187
+ end
188
+
189
+ @exception = Exception.new
190
+ end
191
+
192
+ should "call #rescue on each action if an exception is raised during execute!" do
193
+ @actions.each do |a|
194
+ a.expects(:rescue).with(@exception).once
195
+ end
196
+
197
+ @actions[0].stubs(:execute!).raises(@exception)
198
+
199
+ @runner.expects(:error_and_exit).never
200
+ assert_raises(Exception) { @runner.execute! }
201
+ end
202
+
203
+ should "call #rescue on each action if an exception is raised during prepare" do
204
+ @actions.each do |a|
205
+ a.expects(:rescue).with(@exception).once
206
+ end
207
+
208
+ @actions[0].stubs(:prepare).raises(@exception)
209
+
210
+ @runner.expects(:error_and_exit).never
211
+ assert_raises(Exception) { @runner.execute! }
212
+ end
213
+
214
+ should "call error_and_exit if it is an ActionException" do
215
+ @exception = Vagrant::Actions::ActionException.new("foo")
216
+ @actions[0].stubs(:prepare).raises(@exception)
217
+
218
+ @runner.expects(:error_and_exit).with(@exception.key, @exception.data).once
219
+ @runner.execute!
220
+ end
221
+ end
222
+ end
223
+
224
+ context "actions" do
225
+ setup do
226
+ @runner = Vagrant::Actions::Runner.new
227
+ end
228
+
229
+ should "setup actions to be an array" do
230
+ assert_nil @runner.instance_variable_get(:@actions)
231
+ actions = @runner.actions
232
+ assert actions.is_a?(Array)
233
+ assert actions.equal?(@runner.actions)
234
+ end
235
+
236
+ should "be empty initially" do
237
+ assert @runner.actions.empty?
238
+ end
239
+ end
240
+
241
+ context "duplicate action exceptions" do
242
+ setup do
243
+ @runner = Vagrant::Actions::Runner.new
244
+ end
245
+
246
+ should "should be raised when a duplicate is added" do
247
+ action = mock_fake_action
248
+ 2.times {@runner.actions << action }
249
+ assert_raise Vagrant::Actions::DuplicateActionException do
250
+ @runner.execute!
251
+ end
252
+ end
253
+
254
+ should "should not be raise when no duplicate actions are present" do
255
+ @runner.actions << mock_fake_action(Vagrant::Actions::Base, @runner)
256
+ @runner.actions << mock_fake_action(Vagrant::Actions::VM::Halt, @runner)
257
+
258
+ assert_nothing_raised { @runner.execute! }
259
+ end
260
+
261
+ should "should not raise when a single action is specified" do
262
+ assert_nothing_raised { @runner.execute!(Vagrant::Actions::Base) }
263
+ end
264
+ end
265
+ end