virtualbox 0.7.3 → 0.7.4

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/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :gemcutter
1
+ source "http://rubygems.org"
2
2
 
3
3
  # External Dependencies
4
4
  gem "ffi"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.3
1
+ 0.7.4
@@ -1,7 +1,11 @@
1
- Given /the "(.+?)" relationship/ do |relationship|
1
+ Given /the "(.+?)" relationship$/ do |relationship|
2
2
  @relationship = @model.send(relationship)
3
3
  end
4
4
 
5
+ Given /the "(.+?)" relationship on collection item "(.+?)"/ do |key, index|
6
+ @relationship = @relationship[index.to_i - 1].send(key)
7
+ end
8
+
5
9
  Given /I reload the model/ do
6
10
  @model.reload
7
11
  end
@@ -0,0 +1,76 @@
1
+ Given /the forwarded ports are cleared/ do
2
+ VBoxManage.network_adapters(@output).each_with_index do |obj, i|
3
+ VBoxManage.forwarded_ports(@output, i+1).each do |name, data|
4
+ VBoxManage.execute("modifyvm", @name, "--natpf#{i+1}", "delete", name)
5
+ end
6
+ end
7
+ end
8
+
9
+ Given /I read the adapter in slot "(.+?)"$/ do |slot|
10
+ @slot = slot.to_i
11
+ @adapter = VBoxManage.network_adapters(@output)[slot.to_i]
12
+ @adapter.should_not be_nil
13
+
14
+ @relationship = @model.network_adapters[slot.to_i - 1].nat_driver
15
+ end
16
+
17
+ Given /I create a forwarded port named "(.+?)" from "(.+?)" to "(.+?)" via VBoxManage/ do |name, guest, host|
18
+ fp_string = "#{name},tcp,,#{host},,#{guest}"
19
+ VBoxManage.execute("modifyvm", @name, "--natpf#{@slot}", fp_string)
20
+ end
21
+
22
+ When /I create a forwarded port named "(.+?)" from "(.+?)" to "(.+?)"$/ do |name, guest, host|
23
+ @object = VirtualBox::NATForwardedPort.new
24
+ @object.name = name
25
+ @object.guestport = guest.to_i
26
+ @object.hostport = host.to_i
27
+
28
+ @relationship.forwarded_ports << @object
29
+ end
30
+
31
+ When /I update the forwarded port named "(.+?)":/ do |name, table|
32
+ fp = @relationship.forwarded_ports.find { |fp| fp.name == name }
33
+ fp.should_not be_nil
34
+
35
+ table.hashes.each do |hash|
36
+ value = hash["value"]
37
+ value = value.to_i if %W[hostport guestport].include?(hash["attribute"])
38
+ fp.send("#{hash["attribute"]}=", value)
39
+ end
40
+ end
41
+
42
+ When /I delete the forwarded port named "(.+?)"/ do |name|
43
+ @relationship.forwarded_ports.each do |fp|
44
+ if fp.name == name
45
+ fp.destroy
46
+ break
47
+ end
48
+ end
49
+ end
50
+
51
+ Then /the NAT network should exist/ do
52
+ # Temporary until we find something to really test
53
+ @relationship.should_not be_nil
54
+ end
55
+
56
+ Then /the forwarded port "(.+?)" should exist/ do |name|
57
+ ports = VBoxManage.forwarded_ports(@output, @slot)
58
+ ports.should have_key(name)
59
+ end
60
+
61
+ Then /the forwarded port "(.+?)" should not exist/ do |name|
62
+ ports = VBoxManage.forwarded_ports(@output, @slot)
63
+ ports.should_not have_key(name)
64
+ end
65
+
66
+ Then /the forwarded ports should match/ do
67
+ ports = VBoxManage.forwarded_ports(@output, @slot)
68
+
69
+ @relationship.forwarded_ports.length.should == ports.length
70
+ @relationship.forwarded_ports.each do |fp|
71
+ port = ports[fp.name]
72
+ port.should_not be_nil
73
+
74
+ test_mappings(FORWARDED_PORT_MAPPINGS, fp, port)
75
+ end
76
+ end
@@ -4,6 +4,12 @@ Given /I add a shared folder "(.+?)" with path "(.+?)" via VBoxManage/ do |name,
4
4
  "--hostpath", hostpath)
5
5
  end
6
6
 
7
+ Given /I remove all shared folders/ do
8
+ VBoxManage.shared_folders(@output).each do |name, folder|
9
+ Given %Q[I delete the shared folder "#{name}" via VBoxManage]
10
+ end
11
+ end
12
+
7
13
  Given /I delete the shared folder "(.+?)" via VBoxManage/ do |name|
8
14
  VBoxManage.execute("sharedfolder", "remove", @name,
9
15
  "--name", name)
@@ -35,12 +41,25 @@ When /I create a new shared folder "(.+?)" with path "(.+?)"/ do |name,hostpath|
35
41
  @new_record.host_path = hostpath
36
42
  end
37
43
 
44
+ When /I update the shared folder named "(.+?)":/ do |name, table|
45
+ object = @relationship.find { |o| o.name == name }
46
+ object.should_not be_nil
47
+
48
+ table.hashes.each do |hash|
49
+ object.send("#{hash["attribute"]}=", hash["value"])
50
+ end
51
+ end
52
+
38
53
  When /I delete the shared folder "(.+?)"$/ do |name|
39
54
  @relationship.each do |sf|
40
55
  sf.destroy if sf.name == name
41
56
  end
42
57
  end
43
58
 
59
+ Then /the shared folder "(.+?)" should exist/ do |name|
60
+ VBoxManage.shared_folders(@output).keys.should include(name)
61
+ end
62
+
44
63
  Then /the shared folder "(.+?)" should not exist/ do |name|
45
64
  VBoxManage.shared_folders(@output).keys.should_not include(name)
46
65
  end
@@ -0,0 +1,74 @@
1
+ Given /the snapshots are cleared/ do
2
+ snapshot_map(VBoxManage.snapshots(@output)) do |snapshot|
3
+ VBoxManage.execute("snapshot", @name, "delete", snapshot[:name])
4
+ end
5
+ end
6
+
7
+ Given /the following snapshot tree is created:$/ do |tree|
8
+ tree.hashes.each do |hash|
9
+ restore_parent = lambda do
10
+ VBoxManage.execute("snapshot", @name, "restore", hash["key"])
11
+ end
12
+
13
+ begin
14
+ restore_parent.call
15
+ rescue Exception
16
+ VBoxManage.execute("snapshot", @name, "take", hash["key"])
17
+ end
18
+
19
+ hash["children"].split(",").each do |child|
20
+ VBoxManage.execute("snapshot", @name, "take", child)
21
+ restore_parent.call
22
+ end
23
+ end
24
+ end
25
+
26
+ Given /the snapshot "(.+?)" is created/ do |name|
27
+ VBoxManage.execute("snapshot", @name, "take", name)
28
+ end
29
+
30
+ When /I find the snapshot named "(.+?)"/ do |name|
31
+ @snapshot = @model.find_snapshot(name)
32
+ @snapshot.should be
33
+ end
34
+
35
+ When /I take a snapshot "(.+?)"/ do |name|
36
+ @model.take_snapshot(name)
37
+ end
38
+
39
+ When /I destroy the snapshot/ do
40
+ @snapshot.destroy
41
+ end
42
+
43
+ Then /the snapshot "(.+?)" should exist/ do |name|
44
+ result = false
45
+ snapshot_map(VBoxManage.snapshots(@output)) do |snapshot|
46
+ result = true if snapshot[:name] == name
47
+ end
48
+
49
+ result.should be
50
+ end
51
+
52
+ Then /the snapshot "(.+?)" should not exist/ do |name|
53
+ result = false
54
+ snapshot_map(VBoxManage.snapshots(@output)) do |snapshot|
55
+ result = true if snapshot[:name] == name
56
+ end
57
+
58
+ result.should_not be
59
+ end
60
+
61
+ Then /the snapshots should match/ do
62
+ @root = @model.root_snapshot
63
+
64
+ match_tester = lambda do |current, expected|
65
+ current.uuid.should == expected[:uuid]
66
+ current.children.length.should == expected[:children].length
67
+
68
+ current.children.each_with_index do |current_child, i|
69
+ match_tester.call(current_child, expected[:children][i])
70
+ end
71
+ end
72
+
73
+ match_tester.call(@root, VBoxManage.snapshots(@output))
74
+ end
@@ -54,3 +54,9 @@ NETWORK_ADAPTER_MAPPINGS = {
54
54
  :mac_address => "macaddress",
55
55
  :cable_connected => "cableconnected"
56
56
  }
57
+
58
+ FORWARDED_PORT_MAPPINGS = {
59
+ :protocol => "protocol",
60
+ :hostport => "hostport",
61
+ :guestport => "guestport"
62
+ }
@@ -3,7 +3,7 @@ module VirtualBox
3
3
  # Tests that given a mappings hash (see `VM_MAPPINGS` in env.rb),
4
4
  # a model, and an output hash (string to string), that all the
5
5
  # mappings from model match output.
6
- def test_mappings(mappings, model, output, match=true)
6
+ def test_mappings(mappings, model, output)
7
7
  mappings.each do |model_key, output_key|
8
8
  value = model.send(model_key)
9
9
 
@@ -17,6 +17,21 @@ module VirtualBox
17
17
  value.to_s.should == output_value
18
18
  end
19
19
  end
20
+
21
+ # Applies a function to every snapshot.
22
+ def snapshot_map(snapshots, &block)
23
+ applier = lambda do |snapshot|
24
+ return if !snapshot || snapshot.empty?
25
+
26
+ snapshot[:children].each do |child|
27
+ applier.call(child)
28
+ end
29
+
30
+ block.call(snapshot)
31
+ end
32
+
33
+ applier.call(snapshots)
34
+ end
20
35
  end
21
36
  end
22
37
 
@@ -0,0 +1,49 @@
1
+ # A super simple ordered hash implementation. This class probably
2
+ # isn't useful outside of these testing scripts, since only the bare
3
+ # minimum is implemented.
4
+ #
5
+ # The ordered hash is implemented by keeping the key/values in an
6
+ # array where each element is an array of format [key,value]. This
7
+ # forces the keys to be in the proper order, paired with their
8
+ # values.
9
+ class OrderedHash
10
+ include Enumerable
11
+
12
+ def initialize
13
+ @items = []
14
+ end
15
+
16
+ def []=(key,value)
17
+ # Try to update it in the array if it exists
18
+ @items.each_with_index do |data, index|
19
+ return @items[index][1] = value if data[0] == key
20
+ end
21
+
22
+ # Otherwise just add it to the list
23
+ @items << [key, value]
24
+ end
25
+
26
+ def [](key)
27
+ @items.each do |k, v|
28
+ return v if k == key
29
+ end
30
+
31
+ nil
32
+ end
33
+
34
+ def each(&block)
35
+ @items.each(&block)
36
+ end
37
+
38
+ def empty?
39
+ @items.empty?
40
+ end
41
+
42
+ def has_key?(key)
43
+ @items.each do |k,v|
44
+ return true if k == key
45
+ end
46
+
47
+ false
48
+ end
49
+ end
@@ -32,7 +32,7 @@ class VBoxManage
32
32
  ""
33
33
  end
34
34
 
35
- output.split("\n").inject({}) do |acc, line|
35
+ output.split("\n").inject(OrderedHash.new) do |acc, line|
36
36
  if line =~ /^"?(.+?)"?=(.+?)$/
37
37
  key = $1.to_s
38
38
  value = $2.to_s
@@ -106,5 +106,86 @@ class VBoxManage
106
106
  acc
107
107
  end
108
108
  end
109
+
110
+ # Parses the forwarded ports out of the VM info output and returns
111
+ # it in a hash.
112
+ def forwarded_ports(info, slot)
113
+ seen = false
114
+ info.inject({}) do |acc, data|
115
+ k,v = data
116
+
117
+ seen = true if k == "nic#{slot}"
118
+ if seen && k =~ /^Forwarding\((\d+)\)$/
119
+ keys = [:name, :protocol, :hostip, :hostport, :guestip, :guestport]
120
+ v = v.split(",")
121
+
122
+ temp = {}
123
+ keys.each_with_index do |key, i|
124
+ temp[key] = v[i]
125
+ end
126
+
127
+ acc[temp.delete(:name)] = temp
128
+ end
129
+
130
+ acc
131
+ end
132
+ end
133
+
134
+ # Parses the snapshots out of the VM info output and returns it in
135
+ # a hash.
136
+ def snapshots(info)
137
+ info.inject({}) do |acc, data|
138
+ k,v = data
139
+
140
+ if k =~ /^Snapshot(.+?)(-(.+?))?$/
141
+ current = { $1.to_s.downcase.to_sym => v }
142
+
143
+ if $3
144
+ # This is a child snapshot
145
+ keys = $3.to_s.split("-").map do |key|
146
+ key.to_i - 1
147
+ end
148
+ final = keys.pop
149
+
150
+ location = acc
151
+ keys.each { |index| location = location[:children][index.to_i] }
152
+
153
+ parent = location
154
+ location = location[:children]
155
+ location[final] ||= {}
156
+ location[final].merge!(current)
157
+ location[final][:parent] = parent
158
+ location[final][:children] ||= []
159
+ else
160
+ acc ||= {}
161
+ acc.merge!(current)
162
+ acc[:children] ||= []
163
+ end
164
+ end
165
+
166
+ acc
167
+ end
168
+ end
169
+
170
+ # Gets the current snapshot.
171
+ def current_snapshot(info)
172
+ seen = false
173
+ uuid = nil
174
+ VBoxManage.execute("showvminfo", info["UUID"]).split("\n").each do |line|
175
+ seen = true if line =~ /^Snapshots:/
176
+ uuid = $2.to_s if seen && line =~ /Name:\s+(.+?)\s+\(UUID:\s+(.+?)\)\s+\*/
177
+ end
178
+
179
+ # The recursive sub-method which finds a snapshot by UUID
180
+ finder = lambda do |snapshot|
181
+ return snapshot if snapshot[:uuid] == uuid
182
+
183
+ snapshot[:children].find do |child|
184
+ finder.call(child)
185
+ end
186
+ end
187
+
188
+ finder.call(snapshots(info))
189
+ end
109
190
  end
110
191
  end
@@ -0,0 +1,57 @@
1
+ Feature: Virtual Machine NAT Engine
2
+ As a virtualbox library user
3
+ I want to read and update the NAT engine on a network adapter
4
+
5
+ Background:
6
+ Given I find a VM identified by "test_vm_A"
7
+ And the forwarded ports are cleared
8
+ And the adapters are reset
9
+ And the following adapters are set:
10
+ | slot | type |
11
+ | 1 | nat |
12
+ And the "network_adapters" relationship
13
+ And the "nat_driver" relationship on collection item "1"
14
+
15
+ Scenario: Reading the NAT engine
16
+ Then the NAT network should exist
17
+
18
+ @unsafe
19
+ Scenario: Reading Forwarded Ports
20
+ Given I read the adapter in slot "1"
21
+ And I create a forwarded port named "ssh" from "22" to "2222" via VBoxManage
22
+ And I reload the VM
23
+ And I read the adapter in slot "1"
24
+ Then the forwarded port "ssh" should exist
25
+ And the forwarded ports should match
26
+
27
+ @unsafe
28
+ Scenario: Creating Forwarded Ports
29
+ Given I read the adapter in slot "1"
30
+ When I create a forwarded port named "ssh" from "22" to "2222"
31
+ And I save the relationship
32
+ And I reload the VM info
33
+ Then the forwarded port "ssh" should exist
34
+ And the forwarded ports should match
35
+
36
+ @unsafe
37
+ Scenario: Updating Forwarded Ports
38
+ Given I read the adapter in slot "1"
39
+ And I create a forwarded port named "ssh" from "22" to "2222" via VBoxManage
40
+ And I reload the VM
41
+ And I read the adapter in slot "1"
42
+ When I update the forwarded port named "ssh":
43
+ | attribute | value |
44
+ | hostport | 3333 |
45
+ And I save the relationship
46
+ And I reload the VM info
47
+ Then the forwarded ports should match
48
+
49
+ @unsafe
50
+ Scenario: Deleting Forwarded Ports
51
+ Given I read the adapter in slot "1"
52
+ And I create a forwarded port named "ssh" from "22" to "2222" via VBoxManage
53
+ And I reload the VM
54
+ And I read the adapter in slot "1"
55
+ When I delete the forwarded port named "ssh"
56
+ And I reload the VM info
57
+ Then the forwarded port "ssh" should not exist
@@ -4,6 +4,8 @@ Feature: Virtual Machine Shared Folders
4
4
 
5
5
  Background:
6
6
  Given I find a VM identified by "test_vm_A"
7
+ And I remove all shared folders
8
+ And I reload the VM
7
9
  And the "shared_folders" relationship
8
10
 
9
11
  @unsafe
@@ -18,6 +20,17 @@ Feature: Virtual Machine Shared Folders
18
20
  And I add the new record to the relationship
19
21
  And I save the model
20
22
  And I reload the VM info
23
+ Then the shared folder "bar" should exist
24
+ Then the shared folder properties should match
25
+
26
+ @unsafe
27
+ Scenario: Updating Shared Folders
28
+ Given a shared folder "foo" exists
29
+ When I update the shared folder named "foo":
30
+ | attribute | value |
31
+ | host_path | /new_path |
32
+ And I save the model
33
+ And I reload the VM info
21
34
  Then the shared folder properties should match
22
35
 
23
36
  @unsafe
@@ -0,0 +1,29 @@
1
+ Feature: Virtual Machine Snapshots
2
+ As a virtualbox library user
3
+ I want to manage a VM's snapshots
4
+
5
+ Background:
6
+ Given I find a VM identified by "test_vm_A"
7
+ And the snapshots are cleared
8
+ And the "current_snapshot" relationship
9
+
10
+ Scenario: Reading the snapshots
11
+ Given the following snapshot tree is created:
12
+ | key | children |
13
+ | foo | bar,baz |
14
+ | bar | bar1,bar2 |
15
+ And I reload the VM
16
+ Then the snapshots should match
17
+
18
+ Scenario: Taking a snapshot
19
+ When I take a snapshot "foo"
20
+ And I reload the VM info
21
+ Then the snapshot "foo" should exist
22
+
23
+ Scenario: Deleting a snapshot
24
+ Given the snapshot "foo" is created
25
+ And I reload the VM
26
+ When I find the snapshot named "foo"
27
+ And I destroy the snapshot
28
+ And I reload the VM info
29
+ Then the snapshot "foo" should not exist
@@ -35,6 +35,13 @@ module VirtualBox
35
35
  def reloaded!
36
36
  @_reload = false
37
37
  end
38
+
39
+ # Default errors for relationship implementation, since this is
40
+ # a pretty stable method.
41
+ def errors_for_relationship(caller, data)
42
+ return data.errors if data.respond_to?(:errors)
43
+ nil
44
+ end
38
45
  end
39
46
 
40
47
  # Signals to the class that it should be reloaded. This simply toggles
@@ -70,16 +77,16 @@ module VirtualBox
70
77
 
71
78
  # Returns the errors for a model.
72
79
  def errors
73
- error_hash = super
80
+ self.class.relationships.inject(super) do |acc, data|
81
+ name, options = data
74
82
 
75
- self.class.relationships.each do |name, options|
76
- next unless options && options[:klass].respond_to?(:errors_for_relationship)
77
- relationship_errors = options[:klass].errors_for_relationship(self, relationship_data[name])
83
+ if options && options[:klass].respond_to?(:errors_for_relationship)
84
+ errors = options[:klass].errors_for_relationship(self, relationship_data[name])
85
+ acc.merge!(name => errors) if errors && !errors.empty?
86
+ end
78
87
 
79
- error_hash.merge!({ :foos => relationship_errors }) if relationship_errors.length > 0
88
+ acc
80
89
  end
81
-
82
- error_hash
83
90
  end
84
91
 
85
92
  # Validates the model and relationships.
@@ -116,6 +123,15 @@ module VirtualBox
116
123
 
117
124
  # No longer a new record
118
125
  @new_record = false
126
+
127
+ true
128
+ end
129
+
130
+ # Saves the model and raises an {Exceptions::ValidationFailedException}
131
+ # if the model is invalid, instead of returning false.
132
+ def save!(*args)
133
+ raise Exceptions::ValidationFailedException.new(errors.inspect) if !save(*args)
134
+ true
119
135
  end
120
136
 
121
137
  # Saves a single attribute of the model. This method on the abstract
@@ -206,9 +206,13 @@ module VirtualBox
206
206
  # In addition to those two args, any arbitrary args may be tacked on to the
207
207
  # end and they'll be pushed through to the `save_relationship` method.
208
208
  def save_relationships(*args)
209
- self.class.relationships.each do |name, options|
210
- save_relationship(name, *args)
209
+ # Can't use `all?` here since it short circuits
210
+ results = self.class.relationships.collect do |data|
211
+ name, options = data
212
+ !!save_relationship(name, *args)
211
213
  end
214
+
215
+ !results.include?(false)
212
216
  end
213
217
 
214
218
  # Saves a single relationship. It is up to the relationship class to
@@ -164,4 +164,4 @@ module VirtualBox
164
164
  end
165
165
  end
166
166
  end
167
- end
167
+ end
@@ -16,11 +16,30 @@ module VirtualBox
16
16
  def initialize_mscom
17
17
  require 'win32ole'
18
18
 
19
- # TODO: Dynamic version finding
20
- COM::Util.set_interface_version("3.1.x")
19
+ interface_dir = File.expand_path(File.join(File.dirname(__FILE__), "interface"))
20
+ Dir[File.join(interface_dir, "*")].each do |f|
21
+ p "Checking: #{f}"
22
+ return if File.directory?(f) && initialize_for_version(File.basename(f))
23
+ end
24
+ end
25
+
26
+ def initialize_for_version(version)
27
+ COM::Util.set_interface_version(version)
21
28
 
22
29
  @virtualbox = COM::Util.versioned_interface(:VirtualBox).new(Implementer::MSCOM, self, WIN32OLE.new("VirtualBox.VirtualBox"))
23
30
  @session = COM::Util.versioned_interface(:Session).new(Implementer::MSCOM, self, WIN32OLE.new("VirtualBox.Session"))
31
+
32
+ vb_version = @virtualbox.version
33
+
34
+ # Check if they match or not.
35
+ return false if vb_version.length == version.length
36
+ (0...(version.length)).each do |i|
37
+ p "Checking: #{version[i,1]} to #{vb_version[i,1]}"
38
+ next if version[i,1] == "x"
39
+ return false if version[i,1] != vb_version[i,1]
40
+ end
41
+
42
+ true
24
43
  end
25
44
  end
26
45
  end
@@ -91,8 +91,8 @@ module VirtualBox
91
91
  :parent_collection => relation,
92
92
  :name => parts[0],
93
93
  :protocol => COM::Util.versioned_interface(:NATProtocol).index(parts[1]),
94
- :guestport => parts[5],
95
- :hostport => parts[3]
94
+ :guestport => parts[5].to_i,
95
+ :hostport => parts[3].to_i
96
96
  })
97
97
 
98
98
  port.existing_record!
@@ -136,7 +136,7 @@ module VirtualBox
136
136
  def save
137
137
  return true if !new_record? && !changed?
138
138
  raise Exceptions::ValidationFailedException.new(errors) if !valid?
139
- destroy if !new_record?
139
+ destroy(false) if !new_record?
140
140
 
141
141
  parent.modify_engine do |nat|
142
142
  nat.add_redirect(name, protocol, "", hostport, "", guestport)
@@ -150,13 +150,13 @@ module VirtualBox
150
150
  # Destroys the port forwarding mapping.
151
151
  #
152
152
  # @return [Boolean] True if command was successful, false otherwise.
153
- def destroy
153
+ def destroy(update_collection=true)
154
154
  return if new_record?
155
155
  previous_name = name_changed? ? name_was : name
156
156
  parent.modify_engine do |nat|
157
157
  nat.remove_redirect(previous_name)
158
158
  end
159
- parent_collection.delete(self, true) if parent_collection
159
+ parent_collection.delete(self, true) if parent_collection && update_collection
160
160
  new_record!
161
161
  true
162
162
  end
@@ -1,19 +1,30 @@
1
1
  module VirtualBox
2
2
  # Represents a single NIC (Network Interface Card) of a virtual machine.
3
3
  #
4
- # **Currently, new NICs can't be created, so the only way to get this
5
- # object is through a {VM}'s `nics` relationship.**
4
+ # # Create a Network Adapter
6
5
  #
7
- # # Editing a NIC
6
+ # There is no need to have the ability to create a network adapter,
7
+ # since when creating a VM from scratch, all eight network adapter
8
+ # slots are created, but set to `attachment_type` `nil`. Simply
9
+ # modify the adapter you're interested in and save.
8
10
  #
9
- # Nics can be modified directly in their relationship to other
11
+ #
12
+ # # Editing a Network Adapter
13
+ #
14
+ # Network adapters can be modified directly in their relationship to other
10
15
  # virtual machines. When {VM#save} is called, it will also save any
11
- # changes to its relationships.
16
+ # changes to its relationships. Additionally, you may call {#save}
17
+ # on the relationship itself.
12
18
  #
13
19
  # vm = VirtualBox::VM.find("foo")
14
- # vm.nics[0].macaddress = @new_mac_address
20
+ # vm.network_adapters[0].macaddress = @new_mac_address
15
21
  # vm.save
16
22
  #
23
+ # # Destroying a Network Adapter
24
+ #
25
+ # Network adapters can not actually be "destroyed" but can be
26
+ # removed by setting the `attachment_type` to `nil` and saving.
27
+ #
17
28
  # # Attributes
18
29
  #
19
30
  # Properties of the model are exposed using standard ruby instance
@@ -25,12 +36,16 @@ module VirtualBox
25
36
  # listed below. If you aren't sure what this means or you can't understand
26
37
  # why the below is listed, please read {Attributable}.
27
38
  #
28
- # attribute :parent, :readonly => :readonly
29
- # attribute :nic
30
- # attribute :nictype
31
- # attribute :macaddress
32
- # attribute :cableconnected
33
- # attribute :bridgeadapter
39
+ # attribute :slot, :readonly => true
40
+ # attribute :enabled, :boolean => true
41
+ # attribute :attachment_type
42
+ # attribute :adapter_type
43
+ # attribute :mac_address
44
+ # attribute :cable_connected, :boolean => true
45
+ # attribute :nat_network
46
+ # attribute :internal_network
47
+ # attribute :host_interface
48
+ # attribute :interface, :readonly => true, :property => false
34
49
  #
35
50
  class NetworkAdapter < AbstractModel
36
51
  attribute :parent, :readonly => true, :property => false
@@ -29,6 +29,14 @@ module VirtualBox
29
29
  item
30
30
  end
31
31
 
32
+ # Returns the errors associated with all the items in this
33
+ # collection
34
+ def errors
35
+ collect do |item|
36
+ item.respond_to?(:errors) ? item.errors : {}
37
+ end
38
+ end
39
+
32
40
  def <<(item)
33
41
  item.added_to_relationship(self) if item.respond_to?(:added_to_relationship)
34
42
  push(item)
@@ -168,7 +168,7 @@ module VirtualBox
168
168
  if !new_record?
169
169
  # If its not a new record, any changes will require a new shared
170
170
  # folder to be created, so we first destroy it then recreate it.
171
- destroy
171
+ destroy(false)
172
172
  end
173
173
 
174
174
  create
@@ -204,14 +204,14 @@ module VirtualBox
204
204
  # from the host system. Instead, it simply removes the mapping to the
205
205
  # virtual machine, meaning it will no longer be possible to mount it
206
206
  # from within the virtual machine.
207
- def destroy
207
+ def destroy(update_collection=true)
208
208
  parent.with_open_session do |session|
209
209
  machine = session.machine
210
210
  machine.remove_shared_folder(name)
211
211
  end
212
212
 
213
213
  # Remove it from it's parent collection
214
- parent_collection.delete(self, true) if parent_collection
214
+ parent_collection.delete(self, true) if parent_collection && update_collection
215
215
 
216
216
  # Mark as a new record so if it is saved again, it will create it
217
217
  new_record!
@@ -209,11 +209,11 @@ class RelatableTest < Test::Unit::TestCase
209
209
  end
210
210
 
211
211
  should "call save_relationship for all relationships" do
212
- @model.expects(:save_relationship).with(:foos)
213
- @model.expects(:save_relationship).with(:bars)
214
- @model.expects(:save_relationship).with(:bazs)
215
- @model.expects(:save_relationship).with(:vers)
216
- @model.save_relationships
212
+ @model.expects(:save_relationship).with(:foos).returns(true)
213
+ @model.expects(:save_relationship).with(:bars).returns(true)
214
+ @model.expects(:save_relationship).with(:bazs).returns(true)
215
+ @model.expects(:save_relationship).with(:vers).returns(true)
216
+ assert @model.save_relationships
217
217
  end
218
218
 
219
219
  should "not call save_relationship on non-loaded relations" do
@@ -234,8 +234,8 @@ class RelatableTest < Test::Unit::TestCase
234
234
  end
235
235
 
236
236
  should "call save_relationship on the related class" do
237
- Relatee.expects(:save_relationship).with(@model, @model.foos).once
238
- @model.save_relationship(:foos)
237
+ Relatee.expects(:save_relationship).with(@model, @model.foos).once.returns(:r)
238
+ assert_equal :r, @model.save_relationship(:foos)
239
239
  end
240
240
 
241
241
  should "forward parameters through" do
@@ -68,6 +68,23 @@ class AbstractModelTest < Test::Unit::TestCase
68
68
  end
69
69
  end
70
70
 
71
+ context "errors for relationship default implementation" do
72
+ setup do
73
+ @klass = FakeModel
74
+ end
75
+
76
+ should "return the errors on the item" do
77
+ errors = mock("errors")
78
+ item = mock("item")
79
+ item.stubs(:errors).returns(errors)
80
+ assert_equal errors, @klass.errors_for_relationship(nil, item)
81
+ end
82
+
83
+ should "return nil if the item doesn't respond to errors" do
84
+ assert_nil @klass.errors_for_relationship(nil, 7)
85
+ end
86
+ end
87
+
71
88
  context "lazy attributes and relationships" do
72
89
  class LazyModel < VirtualBox::AbstractModel
73
90
  attribute :foo, :lazy => true
@@ -285,6 +302,29 @@ class AbstractModelTest < Test::Unit::TestCase
285
302
  @model.foo = "foo2"
286
303
  @model.save("YES")
287
304
  end
305
+
306
+ should "return true if succeeds" do
307
+ assert @model.save
308
+ end
309
+ end
310
+
311
+ context "save!" do
312
+ setup do
313
+ @model = FakeModel.new
314
+ end
315
+
316
+ should "raise an exception if save failed" do
317
+ args = %W[foo bar baz]
318
+ @model.expects(:save).with(*args).returns(false)
319
+ assert_raises(VirtualBox::Exceptions::ValidationFailedException) {
320
+ @model.save!(*args)
321
+ }
322
+ end
323
+
324
+ should "not raise an exception if save succeeds" do
325
+ @model.expects(:save).returns(true)
326
+ assert_nothing_raised { @model.save! }
327
+ end
288
328
  end
289
329
 
290
330
  context "populating relationships and attributes" do
@@ -98,7 +98,7 @@ class NATForwardedPortTest < Test::Unit::TestCase
98
98
 
99
99
  should "call destroy if not a new record" do
100
100
  @port.name = "diff"
101
- @port.expects(:destroy).once
101
+ @port.expects(:destroy).with(false).once
102
102
  @port.save
103
103
  end
104
104
  end
@@ -155,6 +155,12 @@ class NATForwardedPortTest < Test::Unit::TestCase
155
155
  assert !@collection.include?(@port)
156
156
  end
157
157
 
158
+ should "not remove itself from collection if specified" do
159
+ assert @collection.include?(@port)
160
+ @port.destroy(false)
161
+ assert @collection.include?(@port)
162
+ end
163
+
158
164
  should "remove the redirect from the nat engine interface" do
159
165
  @nat.expects(:remove_redirect).with(@port.name).once
160
166
  @port.destroy
@@ -202,8 +208,8 @@ class NATForwardedPortTest < Test::Unit::TestCase
202
208
 
203
209
  should "have the proper data" do
204
210
  object = @objects.first
205
- assert_equal "22", object.guestport
206
- assert_equal "2222", object.hostport
211
+ assert_equal 22, object.guestport
212
+ assert_equal 2222, object.hostport
207
213
  assert_equal :tcp, object.protocol
208
214
  assert_equal @objects, object.parent_collection
209
215
  end
@@ -40,6 +40,21 @@ class CollectionTest < Test::Unit::TestCase
40
40
  end
41
41
  end
42
42
 
43
+ context "errors" do
44
+ should "return the errors of all the elements" do
45
+ errors = []
46
+ 3.times do |i|
47
+ error = "error#{i}"
48
+ item = mock("item")
49
+ item.stubs(:errors).returns(error)
50
+ errors << error
51
+ @collection << item
52
+ end
53
+
54
+ assert_equal errors, @collection.errors
55
+ end
56
+ end
57
+
43
58
  context "element callbacks" do
44
59
  setup do
45
60
  @item = mock("item")
@@ -130,7 +130,7 @@ class SharedFolderTest < Test::Unit::TestCase
130
130
  assert !@instance.new_record? # sanity
131
131
 
132
132
  save_seq = sequence("save_seq")
133
- @instance.expects(:destroy).once.in_sequence(save_seq)
133
+ @instance.expects(:destroy).with(false).once.in_sequence(save_seq)
134
134
  @instance.expects(:create).once.in_sequence(save_seq)
135
135
 
136
136
  @instance.save
@@ -195,6 +195,12 @@ class SharedFolderTest < Test::Unit::TestCase
195
195
  assert !@collection.include?(@instance)
196
196
  end
197
197
 
198
+ should "not remove itself from it's collection if specified" do
199
+ assert @collection.include?(@instance)
200
+ @instance.destroy(false)
201
+ assert @collection.include?(@instance)
202
+ end
203
+
198
204
  should "destroy the shared folder on the parent" do
199
205
  destroy_seq = sequence("destroy_seq")
200
206
  @machine.expects(:remove_shared_folder).with(@name).in_sequence(destroy_seq)
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{virtualbox}
8
- s.version = "0.7.3"
8
+ s.version = "0.7.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Mitchell Hashimoto"]
12
- s.date = %q{2010-06-28}
12
+ s.date = %q{2010-07-19}
13
13
  s.description = %q{Create and modify virtual machines in VirtualBox using pure ruby.}
14
14
  s.email = %q{mitchell.hashimoto@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -31,14 +31,17 @@ Gem::Specification.new do |s|
31
31
  "features/step_definitions/abstract_model_steps.rb",
32
32
  "features/step_definitions/extra_data_steps.rb",
33
33
  "features/step_definitions/global_steps.rb",
34
+ "features/step_definitions/nat_engine_steps.rb",
34
35
  "features/step_definitions/network_adapter_steps.rb",
35
36
  "features/step_definitions/shared_folder_steps.rb",
37
+ "features/step_definitions/snapshot_steps.rb",
36
38
  "features/step_definitions/storage_controller_steps.rb",
37
39
  "features/step_definitions/virtualbox_steps.rb",
38
40
  "features/step_definitions/vm_steps.rb",
39
41
  "features/support/env.rb",
40
42
  "features/support/helpers.rb",
41
43
  "features/support/hooks.rb",
44
+ "features/support/ordered_hash.rb",
42
45
  "features/support/vboxmanage.rb",
43
46
  "features/version.feature",
44
47
  "features/vm.feature",
@@ -46,8 +49,10 @@ Gem::Specification.new do |s|
46
49
  "features/vm_cpu.feature",
47
50
  "features/vm_extra_data.feature",
48
51
  "features/vm_hw_virt.feature",
52
+ "features/vm_nat_engine.feature",
49
53
  "features/vm_network_adapters.feature",
50
54
  "features/vm_shared_folders.feature",
55
+ "features/vm_snapshots.feature",
51
56
  "features/vm_storage_controllers.feature",
52
57
  "lib/virtualbox.rb",
53
58
  "lib/virtualbox/abstract_model.rb",
@@ -298,69 +303,69 @@ Gem::Specification.new do |s|
298
303
  s.homepage = %q{http://github.com/mitchellh/virtualbox}
299
304
  s.rdoc_options = ["--charset=UTF-8"]
300
305
  s.require_paths = ["lib"]
301
- s.rubygems_version = %q{1.3.6}
306
+ s.rubygems_version = %q{1.3.7}
302
307
  s.summary = %q{Create and modify virtual machines in VirtualBox using pure ruby.}
303
308
  s.test_files = [
304
- "test/virtualbox_test.rb",
305
- "test/test_helper.rb",
306
- "test/virtualbox/network_adapter_test.rb",
307
- "test/virtualbox/storage_controller_test.rb",
308
- "test/virtualbox/host_test.rb",
309
- "test/virtualbox/vm_test.rb",
310
- "test/virtualbox/virtual_system_description_test.rb",
311
- "test/virtualbox/vrdp_server_test.rb",
312
- "test/virtualbox/nat_forwarded_port_test.rb",
313
- "test/virtualbox/appliance_test.rb",
314
- "test/virtualbox/medium_attachment_test.rb",
315
- "test/virtualbox/audio_adapter_test.rb",
316
- "test/virtualbox/cpu_test.rb",
317
- "test/virtualbox/abstract_model/version_matcher_test.rb",
318
- "test/virtualbox/abstract_model/validatable_test.rb",
309
+ "test/test_helper.rb",
319
310
  "test/virtualbox/abstract_model/attributable_test.rb",
320
- "test/virtualbox/abstract_model/relatable_test.rb",
321
311
  "test/virtualbox/abstract_model/dirty_test.rb",
322
312
  "test/virtualbox/abstract_model/interface_attributes_test.rb",
323
- "test/virtualbox/host_network_interface_test.rb",
324
- "test/virtualbox/lib_test.rb",
325
- "test/virtualbox/system_properties_test.rb",
326
- "test/virtualbox/snapshot_test.rb",
327
- "test/virtualbox/usb_controller_test.rb",
328
- "test/virtualbox/forwarded_port_test.rb",
329
- "test/virtualbox/dvd_test.rb",
330
- "test/virtualbox/hard_drive_test.rb",
313
+ "test/virtualbox/abstract_model/relatable_test.rb",
314
+ "test/virtualbox/abstract_model/validatable_test.rb",
315
+ "test/virtualbox/abstract_model/version_matcher_test.rb",
331
316
  "test/virtualbox/abstract_model_test.rb",
332
- "test/virtualbox/dhcp_server_test.rb",
333
- "test/virtualbox/proxies/collection_test.rb",
334
- "test/virtualbox/com/implementer/base_test.rb",
335
- "test/virtualbox/com/implementer/mscom_test.rb",
336
- "test/virtualbox/com/implementer/ffi_test.rb",
337
- "test/virtualbox/com/ffi/util_test.rb",
317
+ "test/virtualbox/appliance_test.rb",
318
+ "test/virtualbox/audio_adapter_test.rb",
319
+ "test/virtualbox/bios_test.rb",
320
+ "test/virtualbox/com/abstract_enum_test.rb",
321
+ "test/virtualbox/com/abstract_implementer_test.rb",
322
+ "test/virtualbox/com/abstract_interface_test.rb",
338
323
  "test/virtualbox/com/ffi/interface_test.rb",
324
+ "test/virtualbox/com/ffi/util_test.rb",
339
325
  "test/virtualbox/com/ffi_interface_test.rb",
340
- "test/virtualbox/com/util_test.rb",
341
- "test/virtualbox/com/abstract_interface_test.rb",
326
+ "test/virtualbox/com/implementer/base_test.rb",
327
+ "test/virtualbox/com/implementer/ffi_test.rb",
328
+ "test/virtualbox/com/implementer/mscom_test.rb",
342
329
  "test/virtualbox/com/mscom_interface_test.rb",
343
- "test/virtualbox/com/abstract_enum_test.rb",
344
- "test/virtualbox/com/abstract_implementer_test.rb",
345
- "test/virtualbox/shared_folder_test.rb",
346
- "test/virtualbox/global_test.rb",
330
+ "test/virtualbox/com/util_test.rb",
331
+ "test/virtualbox/cpu_test.rb",
332
+ "test/virtualbox/dhcp_server_test.rb",
333
+ "test/virtualbox/dvd_test.rb",
334
+ "test/virtualbox/ext/byte_normalizer_test.rb",
335
+ "test/virtualbox/ext/platform_test.rb",
336
+ "test/virtualbox/ext/subclass_listing_test.rb",
347
337
  "test/virtualbox/extra_data_test.rb",
348
- "test/virtualbox/bios_test.rb",
338
+ "test/virtualbox/forwarded_port_test.rb",
339
+ "test/virtualbox/global_test.rb",
340
+ "test/virtualbox/hard_drive_test.rb",
341
+ "test/virtualbox/host_network_interface_test.rb",
342
+ "test/virtualbox/host_test.rb",
349
343
  "test/virtualbox/hw_virtualization_test.rb",
344
+ "test/virtualbox/lib_test.rb",
345
+ "test/virtualbox/medium_attachment_test.rb",
350
346
  "test/virtualbox/medium_test.rb",
347
+ "test/virtualbox/nat_engine_test.rb",
348
+ "test/virtualbox/nat_forwarded_port_test.rb",
349
+ "test/virtualbox/network_adapter_test.rb",
350
+ "test/virtualbox/proxies/collection_test.rb",
351
+ "test/virtualbox/shared_folder_test.rb",
352
+ "test/virtualbox/snapshot_test.rb",
353
+ "test/virtualbox/storage_controller_test.rb",
354
+ "test/virtualbox/system_properties_test.rb",
355
+ "test/virtualbox/usb_controller_test.rb",
351
356
  "test/virtualbox/usb_device_filter_test.rb",
352
- "test/virtualbox/ext/byte_normalizer_test.rb",
353
- "test/virtualbox/ext/subclass_listing_test.rb",
354
- "test/virtualbox/ext/platform_test.rb",
355
357
  "test/virtualbox/version_test.rb",
356
- "test/virtualbox/nat_engine_test.rb"
358
+ "test/virtualbox/virtual_system_description_test.rb",
359
+ "test/virtualbox/vm_test.rb",
360
+ "test/virtualbox/vrdp_server_test.rb",
361
+ "test/virtualbox_test.rb"
357
362
  ]
358
363
 
359
364
  if s.respond_to? :specification_version then
360
365
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
361
366
  s.specification_version = 3
362
367
 
363
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
368
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
364
369
  s.add_runtime_dependency(%q<ffi>, [">= 0.6.3"])
365
370
  else
366
371
  s.add_dependency(%q<ffi>, [">= 0.6.3"])
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: virtualbox
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 11
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 7
8
- - 3
9
- version: 0.7.3
9
+ - 4
10
+ version: 0.7.4
10
11
  platform: ruby
11
12
  authors:
12
13
  - Mitchell Hashimoto
@@ -14,16 +15,18 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-06-28 00:00:00 -07:00
18
+ date: 2010-07-19 00:00:00 -07:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: ffi
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 1
27
30
  segments:
28
31
  - 0
29
32
  - 6
@@ -55,14 +58,17 @@ files:
55
58
  - features/step_definitions/abstract_model_steps.rb
56
59
  - features/step_definitions/extra_data_steps.rb
57
60
  - features/step_definitions/global_steps.rb
61
+ - features/step_definitions/nat_engine_steps.rb
58
62
  - features/step_definitions/network_adapter_steps.rb
59
63
  - features/step_definitions/shared_folder_steps.rb
64
+ - features/step_definitions/snapshot_steps.rb
60
65
  - features/step_definitions/storage_controller_steps.rb
61
66
  - features/step_definitions/virtualbox_steps.rb
62
67
  - features/step_definitions/vm_steps.rb
63
68
  - features/support/env.rb
64
69
  - features/support/helpers.rb
65
70
  - features/support/hooks.rb
71
+ - features/support/ordered_hash.rb
66
72
  - features/support/vboxmanage.rb
67
73
  - features/version.feature
68
74
  - features/vm.feature
@@ -70,8 +76,10 @@ files:
70
76
  - features/vm_cpu.feature
71
77
  - features/vm_extra_data.feature
72
78
  - features/vm_hw_virt.feature
79
+ - features/vm_nat_engine.feature
73
80
  - features/vm_network_adapters.feature
74
81
  - features/vm_shared_folders.feature
82
+ - features/vm_snapshots.feature
75
83
  - features/vm_storage_controllers.feature
76
84
  - lib/virtualbox.rb
77
85
  - lib/virtualbox/abstract_model.rb
@@ -328,77 +336,81 @@ rdoc_options:
328
336
  require_paths:
329
337
  - lib
330
338
  required_ruby_version: !ruby/object:Gem::Requirement
339
+ none: false
331
340
  requirements:
332
341
  - - ">="
333
342
  - !ruby/object:Gem::Version
343
+ hash: 3
334
344
  segments:
335
345
  - 0
336
346
  version: "0"
337
347
  required_rubygems_version: !ruby/object:Gem::Requirement
348
+ none: false
338
349
  requirements:
339
350
  - - ">="
340
351
  - !ruby/object:Gem::Version
352
+ hash: 3
341
353
  segments:
342
354
  - 0
343
355
  version: "0"
344
356
  requirements: []
345
357
 
346
358
  rubyforge_project:
347
- rubygems_version: 1.3.6
359
+ rubygems_version: 1.3.7
348
360
  signing_key:
349
361
  specification_version: 3
350
362
  summary: Create and modify virtual machines in VirtualBox using pure ruby.
351
363
  test_files:
352
- - test/virtualbox_test.rb
353
364
  - test/test_helper.rb
354
- - test/virtualbox/network_adapter_test.rb
355
- - test/virtualbox/storage_controller_test.rb
356
- - test/virtualbox/host_test.rb
357
- - test/virtualbox/vm_test.rb
358
- - test/virtualbox/virtual_system_description_test.rb
359
- - test/virtualbox/vrdp_server_test.rb
360
- - test/virtualbox/nat_forwarded_port_test.rb
361
- - test/virtualbox/appliance_test.rb
362
- - test/virtualbox/medium_attachment_test.rb
363
- - test/virtualbox/audio_adapter_test.rb
364
- - test/virtualbox/cpu_test.rb
365
- - test/virtualbox/abstract_model/version_matcher_test.rb
366
- - test/virtualbox/abstract_model/validatable_test.rb
367
365
  - test/virtualbox/abstract_model/attributable_test.rb
368
- - test/virtualbox/abstract_model/relatable_test.rb
369
366
  - test/virtualbox/abstract_model/dirty_test.rb
370
367
  - test/virtualbox/abstract_model/interface_attributes_test.rb
371
- - test/virtualbox/host_network_interface_test.rb
372
- - test/virtualbox/lib_test.rb
373
- - test/virtualbox/system_properties_test.rb
374
- - test/virtualbox/snapshot_test.rb
375
- - test/virtualbox/usb_controller_test.rb
376
- - test/virtualbox/forwarded_port_test.rb
377
- - test/virtualbox/dvd_test.rb
378
- - test/virtualbox/hard_drive_test.rb
368
+ - test/virtualbox/abstract_model/relatable_test.rb
369
+ - test/virtualbox/abstract_model/validatable_test.rb
370
+ - test/virtualbox/abstract_model/version_matcher_test.rb
379
371
  - test/virtualbox/abstract_model_test.rb
380
- - test/virtualbox/dhcp_server_test.rb
381
- - test/virtualbox/proxies/collection_test.rb
382
- - test/virtualbox/com/implementer/base_test.rb
383
- - test/virtualbox/com/implementer/mscom_test.rb
384
- - test/virtualbox/com/implementer/ffi_test.rb
385
- - test/virtualbox/com/ffi/util_test.rb
372
+ - test/virtualbox/appliance_test.rb
373
+ - test/virtualbox/audio_adapter_test.rb
374
+ - test/virtualbox/bios_test.rb
375
+ - test/virtualbox/com/abstract_enum_test.rb
376
+ - test/virtualbox/com/abstract_implementer_test.rb
377
+ - test/virtualbox/com/abstract_interface_test.rb
386
378
  - test/virtualbox/com/ffi/interface_test.rb
379
+ - test/virtualbox/com/ffi/util_test.rb
387
380
  - test/virtualbox/com/ffi_interface_test.rb
388
- - test/virtualbox/com/util_test.rb
389
- - test/virtualbox/com/abstract_interface_test.rb
381
+ - test/virtualbox/com/implementer/base_test.rb
382
+ - test/virtualbox/com/implementer/ffi_test.rb
383
+ - test/virtualbox/com/implementer/mscom_test.rb
390
384
  - test/virtualbox/com/mscom_interface_test.rb
391
- - test/virtualbox/com/abstract_enum_test.rb
392
- - test/virtualbox/com/abstract_implementer_test.rb
393
- - test/virtualbox/shared_folder_test.rb
394
- - test/virtualbox/global_test.rb
385
+ - test/virtualbox/com/util_test.rb
386
+ - test/virtualbox/cpu_test.rb
387
+ - test/virtualbox/dhcp_server_test.rb
388
+ - test/virtualbox/dvd_test.rb
389
+ - test/virtualbox/ext/byte_normalizer_test.rb
390
+ - test/virtualbox/ext/platform_test.rb
391
+ - test/virtualbox/ext/subclass_listing_test.rb
395
392
  - test/virtualbox/extra_data_test.rb
396
- - test/virtualbox/bios_test.rb
393
+ - test/virtualbox/forwarded_port_test.rb
394
+ - test/virtualbox/global_test.rb
395
+ - test/virtualbox/hard_drive_test.rb
396
+ - test/virtualbox/host_network_interface_test.rb
397
+ - test/virtualbox/host_test.rb
397
398
  - test/virtualbox/hw_virtualization_test.rb
399
+ - test/virtualbox/lib_test.rb
400
+ - test/virtualbox/medium_attachment_test.rb
398
401
  - test/virtualbox/medium_test.rb
402
+ - test/virtualbox/nat_engine_test.rb
403
+ - test/virtualbox/nat_forwarded_port_test.rb
404
+ - test/virtualbox/network_adapter_test.rb
405
+ - test/virtualbox/proxies/collection_test.rb
406
+ - test/virtualbox/shared_folder_test.rb
407
+ - test/virtualbox/snapshot_test.rb
408
+ - test/virtualbox/storage_controller_test.rb
409
+ - test/virtualbox/system_properties_test.rb
410
+ - test/virtualbox/usb_controller_test.rb
399
411
  - test/virtualbox/usb_device_filter_test.rb
400
- - test/virtualbox/ext/byte_normalizer_test.rb
401
- - test/virtualbox/ext/subclass_listing_test.rb
402
- - test/virtualbox/ext/platform_test.rb
403
412
  - test/virtualbox/version_test.rb
404
- - test/virtualbox/nat_engine_test.rb
413
+ - test/virtualbox/virtual_system_description_test.rb
414
+ - test/virtualbox/vm_test.rb
415
+ - test/virtualbox/vrdp_server_test.rb
416
+ - test/virtualbox_test.rb