virtualbox 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.
Files changed (36) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +11 -0
  3. data/Rakefile +32 -0
  4. data/Readme.md +75 -0
  5. data/TODO +13 -0
  6. data/VERSION +1 -0
  7. data/lib/virtualbox.rb +11 -0
  8. data/lib/virtualbox/abstract_model.rb +95 -0
  9. data/lib/virtualbox/abstract_model/attributable.rb +193 -0
  10. data/lib/virtualbox/abstract_model/dirty.rb +164 -0
  11. data/lib/virtualbox/abstract_model/relatable.rb +163 -0
  12. data/lib/virtualbox/attached_device.rb +104 -0
  13. data/lib/virtualbox/command.rb +54 -0
  14. data/lib/virtualbox/dvd.rb +31 -0
  15. data/lib/virtualbox/errors.rb +7 -0
  16. data/lib/virtualbox/ext/subclass_listing.rb +24 -0
  17. data/lib/virtualbox/hard_drive.rb +169 -0
  18. data/lib/virtualbox/image.rb +94 -0
  19. data/lib/virtualbox/nic.rb +150 -0
  20. data/lib/virtualbox/storage_controller.rb +122 -0
  21. data/lib/virtualbox/vm.rb +287 -0
  22. data/test/test_helper.rb +25 -0
  23. data/test/virtualbox/abstract_model/attributable_test.rb +150 -0
  24. data/test/virtualbox/abstract_model/dirty_test.rb +66 -0
  25. data/test/virtualbox/abstract_model/relatable_test.rb +141 -0
  26. data/test/virtualbox/abstract_model_test.rb +146 -0
  27. data/test/virtualbox/attached_device_test.rb +92 -0
  28. data/test/virtualbox/command_test.rb +30 -0
  29. data/test/virtualbox/dvd_test.rb +58 -0
  30. data/test/virtualbox/ext/subclass_listing_test.rb +25 -0
  31. data/test/virtualbox/hard_drive_test.rb +161 -0
  32. data/test/virtualbox/image_test.rb +113 -0
  33. data/test/virtualbox/nic_test.rb +119 -0
  34. data/test/virtualbox/storage_controller_test.rb +79 -0
  35. data/test/virtualbox/vm_test.rb +313 -0
  36. metadata +103 -0
@@ -0,0 +1,66 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class DirtyTest < Test::Unit::TestCase
4
+ class DirtyModel
5
+ include VirtualBox::AbstractModel::Dirty
6
+
7
+ def initialize
8
+ @foo = "foo"
9
+ @bar = "bar"
10
+ end
11
+
12
+ def foo=(value)
13
+ set_dirty!(:foo, @foo, value)
14
+ @foo = value
15
+ end
16
+
17
+ def bar=(value)
18
+ set_dirty!(:bar, @bar, value)
19
+ @bar = value
20
+ end
21
+ end
22
+
23
+ context "dirty attributes" do
24
+ setup do
25
+ @model = DirtyModel.new
26
+ end
27
+
28
+ should "not be dirty initially" do
29
+ assert !@model.changed?
30
+ end
31
+
32
+ should "be dirty after changing an attribute" do
33
+ assert !@model.changed? # sanity
34
+ @model.foo = "my value"
35
+ assert @model.changed?
36
+ end
37
+
38
+ should "be able to clear dirty state" do
39
+ assert !@model.changed?
40
+ @model.foo = "my value"
41
+ assert @model.changed?
42
+ @model.clear_dirty!(:foo)
43
+ assert !@model.changed?
44
+ end
45
+
46
+ should "show changes on specific field" do
47
+ assert !@model.changed?
48
+ @model.foo = "my value"
49
+ assert @model.foo_changed?
50
+ assert_equal ["foo", "my value"], @model.foo_change
51
+ assert_equal "foo", @model.foo_was
52
+ end
53
+
54
+ should "show changes for the whole model" do
55
+ assert !@model.changed?
56
+ @model.foo = "foo2"
57
+ @model.bar = "bar2"
58
+
59
+ assert @model.changed?
60
+ changes = @model.changes
61
+ assert_equal 2, changes.length
62
+ assert_equal ["foo", "foo2"], changes[:foo]
63
+ assert_equal ["bar", "bar2"], changes[:bar]
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,141 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class RelatableTest < Test::Unit::TestCase
4
+ class Relatee
5
+ def self.populate_relationship(caller, data)
6
+ "FOO"
7
+ end
8
+ end
9
+ class BarRelatee; end
10
+
11
+ class RelatableModel
12
+ include VirtualBox::AbstractModel::Relatable
13
+
14
+ relationship :foos, Relatee
15
+ relationship :bars, BarRelatee
16
+ end
17
+
18
+ setup do
19
+ @data = {}
20
+ end
21
+
22
+ context "subclasses" do
23
+ class SubRelatableModel < RelatableModel
24
+ relationship :bars, Relatee
25
+ end
26
+
27
+ setup do
28
+ @relationships = SubRelatableModel.relationships
29
+ end
30
+
31
+ should "inherit relationships of parent" do
32
+ assert @relationships.has_key?(:foos)
33
+ assert @relationships.has_key?(:bars)
34
+ end
35
+
36
+ should "inherit options of relationships" do
37
+ assert_equal Relatee, @relationships[:foos][:klass]
38
+ end
39
+ end
40
+
41
+ context "default callbacks" do
42
+ setup do
43
+ @model = RelatableModel.new
44
+ end
45
+
46
+ should "not raise an error if populate_relationship doesn't exist" do
47
+ assert !BarRelatee.respond_to?(:populate_relationship)
48
+ assert_nothing_raised { @model.populate_relationships(nil) }
49
+ end
50
+
51
+ should "not raise an error when saving relationships if the callback doesn't exist" do
52
+ assert !Relatee.respond_to?(:save_relationship)
53
+ assert_nothing_raised { @model.save_relationships }
54
+ end
55
+
56
+ should "not raise an error in destroying relationships if the callback doesn't exist" do
57
+ assert !Relatee.respond_to?(:destroy_relationship)
58
+ assert_nothing_raised { @model.destroy_relationships }
59
+ end
60
+ end
61
+
62
+ context "destroying" do
63
+ setup do
64
+ @model = RelatableModel.new
65
+ @model.populate_relationships({})
66
+ end
67
+
68
+ context "a single relationship" do
69
+ should "call destroy_relationship only for the given relationship" do
70
+ Relatee.expects(:destroy_relationship).once
71
+ BarRelatee.expects(:destroy_relationship).never
72
+ @model.destroy_relationship(:foos)
73
+ end
74
+
75
+ should "forward any args passed into destroy_relationship" do
76
+ Relatee.expects(:destroy_relationship).with(@model, anything, "HELLO").once
77
+ @model.destroy_relationship(:foos, "HELLO")
78
+ end
79
+
80
+ should "pass the data into destroy_relationship" do
81
+ Relatee.expects(:destroy_relationship).with(@model, "FOO").once
82
+ @model.destroy_relationship(:foos)
83
+ end
84
+ end
85
+
86
+ context "all relationships" do
87
+ should "call destroy_relationship on the related class" do
88
+ Relatee.expects(:destroy_relationship).with(@model, anything).once
89
+ @model.destroy_relationships
90
+ end
91
+
92
+ should "forward any args passed into destroy relationships" do
93
+ Relatee.expects(:destroy_relationship).with(@model, anything, "HELLO").once
94
+ @model.destroy_relationships("HELLO")
95
+ end
96
+ end
97
+ end
98
+
99
+ context "saving relationships" do
100
+ setup do
101
+ @model = RelatableModel.new
102
+ end
103
+
104
+ should "call save_relationship on the related class" do
105
+ Relatee.expects(:save_relationship).with(@model, @model.foos).once
106
+ @model.save_relationships
107
+ end
108
+
109
+ should "forward parameters through" do
110
+ Relatee.expects(:save_relationship).with(@model, @model.foos, "YES").once
111
+ @model.save_relationships("YES")
112
+ end
113
+ end
114
+
115
+ context "reading relationships" do
116
+ setup do
117
+ @model = RelatableModel.new
118
+ end
119
+
120
+ should "provide a read method for relationships" do
121
+ assert_nothing_raised { @model.foos }
122
+ end
123
+ end
124
+
125
+ context "populating relationships" do
126
+ setup do
127
+ @model = RelatableModel.new
128
+ end
129
+
130
+ should "call populate_relationship on the related class" do
131
+ Relatee.expects(:populate_relationship).with(@model, @data).once
132
+ @model.populate_relationships(@data)
133
+ end
134
+
135
+ should "properly save returned value as the value for the relationship" do
136
+ Relatee.expects(:populate_relationship).once.returns("HEY")
137
+ @model.populate_relationships(@data)
138
+ assert_equal "HEY", @model.foos
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,146 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class AbstractModelTest < Test::Unit::TestCase
4
+ class Foo; end
5
+ class Bar; end
6
+
7
+ class FakeModel < VirtualBox::AbstractModel
8
+ attribute :foo
9
+ attribute :bar
10
+ relationship :foos, Foo
11
+ relationship :bars, Bar, :dependent => :destroy
12
+ end
13
+
14
+ context "new/existing records" do
15
+ setup do
16
+ @model = FakeModel.new
17
+ end
18
+
19
+ should "be a new record by default" do
20
+ assert @model.new_record?
21
+ end
22
+
23
+ should "not be a new record if populate_attributes is called" do
24
+ @model.populate_attributes({})
25
+ assert !@model.new_record?
26
+ end
27
+
28
+ should "not be a new record after saving" do
29
+ assert @model.new_record?
30
+ @model.save
31
+ assert !@model.new_record?
32
+ end
33
+ end
34
+
35
+ context "subclasses" do
36
+ class FakeTwoModel < FakeModel
37
+ attribute :baz
38
+ end
39
+
40
+ setup do
41
+ @model = FakeTwoModel.new
42
+ @model.populate_attributes({
43
+ :foo => "foo",
44
+ :bar => "bar",
45
+ :baz => "baz"
46
+ })
47
+ end
48
+
49
+ should "have access to parents attributes" do
50
+ assert_nothing_raised do
51
+ assert_equal "foo", @model.foo
52
+ end
53
+ end
54
+ end
55
+
56
+ context "destroying" do
57
+ setup do
58
+ @model = FakeModel.new
59
+ end
60
+
61
+ should "call destroy_relationship only for dependent relationships" do
62
+ Foo.expects(:destroy_relationship).never
63
+ Bar.expects(:destroy_relationship).once
64
+
65
+ @model.destroy
66
+ end
67
+
68
+ should "forward any arguments to the destroy method" do
69
+ Bar.expects(:destroy_relationship).with(@model, anything, "HELLO").once
70
+ @model.destroy("HELLO")
71
+ end
72
+ end
73
+
74
+ context "saving" do
75
+ setup do
76
+ @model = FakeModel.new
77
+ @model.populate_attributes({
78
+ :foo => "foo",
79
+ :bar => "bar"
80
+ })
81
+ end
82
+
83
+ should "call save_attribute for only attributes which have changed" do
84
+ @model.foo = "foo2"
85
+ assert @model.foo_changed?
86
+ assert !@model.bar_changed?
87
+ @model.expects(:save_attribute).with(:foo, "foo2").once
88
+ @model.save
89
+ end
90
+
91
+ should "call save_relationships" do
92
+ @model.expects(:save_relationships).once
93
+ @model.save
94
+ end
95
+
96
+ should "clear dirty state once saved" do
97
+ @model.foo = "foo2"
98
+ assert @model.foo_changed?
99
+ @model.save
100
+ assert !@model.foo_changed?
101
+ end
102
+
103
+ should "forward parameters through" do
104
+ @model.expects(:save_attribute).with(:foo, "foo2", "YES").once
105
+ Foo.expects(:save_relationship).with(@model, anything, "YES").once
106
+
107
+ @model.foo = "foo2"
108
+ @model.save("YES")
109
+ end
110
+ end
111
+
112
+ context "populating relationships and attributes" do
113
+ setup do
114
+ @model = FakeModel.new
115
+ end
116
+
117
+ should "populate relationships at the same time as attributes" do
118
+ Foo.expects(:populate_relationship).once
119
+ @model.populate_attributes({})
120
+ end
121
+ end
122
+
123
+ context "integrating attributable and dirty" do
124
+ setup do
125
+ @model = FakeModel.new
126
+ end
127
+
128
+ should "not affect dirtiness with populate_attributes" do
129
+ assert !@model.changed?
130
+ @model.populate_attributes({
131
+ :foo => "foo2"
132
+ })
133
+
134
+ assert !@model.changed?
135
+ assert_equal "foo2", @model.foo
136
+ end
137
+
138
+ should "mark dirtiness on write_attribute" do
139
+ assert !@model.changed?
140
+ @model.write_attribute(:foo, "foo2")
141
+ assert @model.changed?
142
+ assert @model.foo_changed?
143
+ assert_equal "foo2", @model.foo
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,92 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class AttachedDeviceTest < Test::Unit::TestCase
4
+ setup do
5
+ @data = {
6
+ :"foo controller-0-0" => "foomedium",
7
+ :"foo controller-imageuuid-0-0" => "322f79fd-7da6-416f-a16f-e70066ccf165",
8
+ :"foo controller-1-0" => "barmedium"
9
+ }
10
+
11
+ @vm = mock("vm")
12
+ @vm.stubs(:name).returns("foo")
13
+
14
+ @caller = mock("caller")
15
+ @caller.stubs(:parent).returns(@vm)
16
+ @caller.stubs(:name).returns("Foo Controller")
17
+
18
+ # Stub execute to make sure nothing actually happens
19
+ VirtualBox::Command.stubs(:execute).returns('')
20
+ end
21
+
22
+ context "destroying" do
23
+ setup do
24
+ @value = VirtualBox::AttachedDevice.populate_relationship(@caller, @data)
25
+ @value = @value[0]
26
+
27
+ @image = mock("image")
28
+ @value.stubs(:image).returns(@image)
29
+
30
+ VirtualBox::Command.stubs(:execute)
31
+ end
32
+
33
+ should "simply call destroy on each object when destroying the relationship" do
34
+ obj_one = mock("one")
35
+ obj_two = mock("two")
36
+
37
+ obj_one.expects(:destroy).with("HELLO").once
38
+ obj_two.expects(:destroy).with("HELLO").once
39
+
40
+ VirtualBox::AttachedDevice.destroy_relationship(self, [obj_one, obj_two], "HELLO")
41
+ end
42
+
43
+ should "shell escape VM name and storage controller name" do
44
+ shell_seq = sequence("shell_seq")
45
+ VirtualBox::Command.expects(:shell_escape).with(@vm.name).in_sequence(shell_seq)
46
+ VirtualBox::Command.expects(:shell_escape).with(@caller.name).in_sequence(shell_seq)
47
+ VirtualBox::Command.expects(:vboxmanage).in_sequence(shell_seq)
48
+ @value.destroy
49
+ end
50
+
51
+ should "not destroy image by default" do
52
+ @image.expects(:destroy).never
53
+ @value.destroy
54
+ end
55
+
56
+ should "destroy image if flag is set" do
57
+ @image.expects(:destroy).once
58
+ @value.destroy({
59
+ :destroy_image => true
60
+ })
61
+ end
62
+
63
+ should "ignore destroy image flag if image is nil" do
64
+ @value.expects(:image).once.returns(nil)
65
+ @value.destroy({
66
+ :destroy_image => true
67
+ })
68
+ end
69
+ end
70
+
71
+ context "populating relationships" do
72
+ setup do
73
+ @value = VirtualBox::AttachedDevice.populate_relationship(@caller, @data)
74
+ end
75
+
76
+ should "create the correct amount of objects" do
77
+ assert_equal 2, @value.length
78
+ end
79
+
80
+ should "create objects with proper values" do
81
+ obj = @value[0]
82
+ assert_equal "foomedium", obj.medium
83
+ assert_equal "322f79fd-7da6-416f-a16f-e70066ccf165", obj.uuid
84
+ assert_equal 0, obj.port
85
+
86
+ obj = @value[1]
87
+ assert_equal "barmedium", obj.medium
88
+ assert_nil obj.uuid
89
+ assert_equal 1, obj.port
90
+ end
91
+ end
92
+ end