virtualbox 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
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