virtualbox 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -1
- data/Gemfile +1 -1
- data/Rakefile +1 -1
- data/Readme.md +5 -21
- data/VERSION +1 -1
- data/docs/WhatsNew.md +9 -47
- data/lib/virtualbox.rb +7 -30
- data/lib/virtualbox/abstract_model.rb +25 -5
- data/lib/virtualbox/abstract_model/attributable.rb +5 -1
- data/lib/virtualbox/abstract_model/dirty.rb +2 -0
- data/lib/virtualbox/abstract_model/interface_attributes.rb +96 -0
- data/lib/virtualbox/abstract_model/relatable.rb +19 -8
- data/lib/virtualbox/appliance.rb +59 -0
- data/lib/virtualbox/audio_adapter.rb +44 -0
- data/lib/virtualbox/bios.rb +44 -0
- data/lib/virtualbox/com.rb +23 -0
- data/lib/virtualbox/com/abstract_enum.rb +42 -0
- data/lib/virtualbox/com/abstract_implementer.rb +43 -0
- data/lib/virtualbox/com/abstract_interface.rb +165 -0
- data/lib/virtualbox/com/ffi/interface.rb +141 -0
- data/lib/virtualbox/com/ffi/interfaces.rb +42 -0
- data/lib/virtualbox/com/ffi/util.rb +101 -0
- data/lib/virtualbox/com/ffi/vboxxpcomc.rb +31 -0
- data/lib/virtualbox/com/ffi_interface.rb +65 -0
- data/lib/virtualbox/com/implementer/base.rb +52 -0
- data/lib/virtualbox/com/implementer/ffi.rb +350 -0
- data/lib/virtualbox/com/implementer/mscom.rb +165 -0
- data/lib/virtualbox/com/implementer/nil.rb +10 -0
- data/lib/virtualbox/com/interface/appliance.rb +20 -0
- data/lib/virtualbox/com/interface/audio_adapter.rb +13 -0
- data/lib/virtualbox/com/interface/audio_controller_type.rb +9 -0
- data/lib/virtualbox/com/interface/audio_driver_type.rb +9 -0
- data/lib/virtualbox/com/interface/bios_boot_menu_mode.rb +9 -0
- data/lib/virtualbox/com/interface/bios_settings.rb +19 -0
- data/lib/virtualbox/com/interface/clipboard_mode.rb +9 -0
- data/lib/virtualbox/com/interface/console.rb +48 -0
- data/lib/virtualbox/com/interface/cpu_property_type.rb +9 -0
- data/lib/virtualbox/com/interface/device_type.rb +9 -0
- data/lib/virtualbox/com/interface/dhcp_server.rb +20 -0
- data/lib/virtualbox/com/interface/firmware_type.rb +9 -0
- data/lib/virtualbox/com/interface/guest_os_type.rb +21 -0
- data/lib/virtualbox/com/interface/host.rb +40 -0
- data/lib/virtualbox/com/interface/host_network_interface.rb +28 -0
- data/lib/virtualbox/com/interface/host_network_interface_medium_type.rb +9 -0
- data/lib/virtualbox/com/interface/host_network_interface_status.rb +9 -0
- data/lib/virtualbox/com/interface/host_network_interface_type.rb +9 -0
- data/lib/virtualbox/com/interface/host_usb_device.rb +11 -0
- data/lib/virtualbox/com/interface/host_usb_device_filter.rb +11 -0
- data/lib/virtualbox/com/interface/hw_virt_ex_property_type.rb +9 -0
- data/lib/virtualbox/com/interface/machine.rb +103 -0
- data/lib/virtualbox/com/interface/machine_state.rb +12 -0
- data/lib/virtualbox/com/interface/medium.rb +48 -0
- data/lib/virtualbox/com/interface/medium_attachment.rb +16 -0
- data/lib/virtualbox/com/interface/medium_format.rb +16 -0
- data/lib/virtualbox/com/interface/medium_state.rb +9 -0
- data/lib/virtualbox/com/interface/medium_type.rb +9 -0
- data/lib/virtualbox/com/interface/medium_variant.rb +9 -0
- data/lib/virtualbox/com/interface/network_adapter.rb +28 -0
- data/lib/virtualbox/com/interface/network_adapter_type.rb +9 -0
- data/lib/virtualbox/com/interface/network_attachment_type.rb +9 -0
- data/lib/virtualbox/com/interface/nsiexception.rb +21 -0
- data/lib/virtualbox/com/interface/nsisupports.rb +13 -0
- data/lib/virtualbox/com/interface/parallel_port.rb +15 -0
- data/lib/virtualbox/com/interface/port_mode.rb +9 -0
- data/lib/virtualbox/com/interface/progress.rb +58 -0
- data/lib/virtualbox/com/interface/serial_port.rb +17 -0
- data/lib/virtualbox/com/interface/session.rb +16 -0
- data/lib/virtualbox/com/interface/session_state.rb +9 -0
- data/lib/virtualbox/com/interface/session_type.rb +9 -0
- data/lib/virtualbox/com/interface/shared_folder.rb +15 -0
- data/lib/virtualbox/com/interface/snapshot.rb +18 -0
- data/lib/virtualbox/com/interface/storage_bus.rb +9 -0
- data/lib/virtualbox/com/interface/storage_controller.rb +21 -0
- data/lib/virtualbox/com/interface/storage_controller_type.rb +9 -0
- data/lib/virtualbox/com/interface/system_properties.rb +35 -0
- data/lib/virtualbox/com/interface/usb_controller.rb +18 -0
- data/lib/virtualbox/com/interface/usb_device.rb +22 -0
- data/lib/virtualbox/com/interface/usb_device_filter.rb +21 -0
- data/lib/virtualbox/com/interface/usb_device_filter_action.rb +9 -0
- data/lib/virtualbox/com/interface/usb_device_state.rb +9 -0
- data/lib/virtualbox/com/interface/virtual_box_error_info.rb +15 -0
- data/lib/virtualbox/com/interface/virtual_system_description.rb +17 -0
- data/lib/virtualbox/com/interface/virtual_system_description_type.rb +12 -0
- data/lib/virtualbox/com/interface/virtual_system_description_value_type.rb +9 -0
- data/lib/virtualbox/com/interface/virtualbox.rb +54 -0
- data/lib/virtualbox/com/interface/vrdp_auth_type.rb +9 -0
- data/lib/virtualbox/com/interface/vrdp_server.rb +17 -0
- data/lib/virtualbox/com/mscom_interface.rb +22 -0
- data/lib/virtualbox/com/util.rb +18 -0
- data/lib/virtualbox/dvd.rb +7 -94
- data/lib/virtualbox/exceptions.rb +24 -0
- data/lib/virtualbox/ext/glob_loader.rb +22 -0
- data/lib/virtualbox/ext/logger.rb +38 -0
- data/lib/virtualbox/ext/platform.rb +1 -1
- data/lib/virtualbox/extra_data.rb +25 -37
- data/lib/virtualbox/forwarded_port.rb +35 -13
- data/lib/virtualbox/global.rb +22 -80
- data/lib/virtualbox/hard_drive.rb +30 -97
- data/lib/virtualbox/lib.rb +82 -0
- data/lib/virtualbox/media.rb +7 -6
- data/lib/virtualbox/medium.rb +138 -0
- data/lib/virtualbox/medium_attachment.rb +61 -0
- data/lib/virtualbox/network_adapter.rb +134 -0
- data/lib/virtualbox/shared_folder.rb +53 -78
- data/lib/virtualbox/storage_controller.rb +76 -20
- data/lib/virtualbox/system_properties.rb +74 -0
- data/lib/virtualbox/usb_controller.rb +55 -0
- data/lib/virtualbox/version.rb +15 -0
- data/lib/virtualbox/virtual_system_description.rb +47 -0
- data/lib/virtualbox/vm.rb +160 -272
- data/test/test_helper.rb +0 -108
- data/test/virtualbox/abstract_model/attributable_test.rb +7 -1
- data/test/virtualbox/abstract_model/dirty_test.rb +1 -1
- data/test/virtualbox/abstract_model/interface_attributes_test.rb +169 -0
- data/test/virtualbox/abstract_model/relatable_test.rb +20 -0
- data/test/virtualbox/abstract_model_test.rb +40 -5
- data/test/virtualbox/appliance_test.rb +152 -0
- data/test/virtualbox/audio_adapter_test.rb +83 -0
- data/test/virtualbox/bios_test.rb +83 -0
- data/test/virtualbox/com/abstract_enum_test.rb +48 -0
- data/test/virtualbox/com/abstract_implementer_test.rb +39 -0
- data/test/virtualbox/com/abstract_interface_test.rb +139 -0
- data/test/virtualbox/com/ffi/interface_test.rb +249 -0
- data/test/virtualbox/com/ffi/util_test.rb +86 -0
- data/test/virtualbox/com/ffi_interface_test.rb +42 -0
- data/test/virtualbox/com/implementer/base_test.rb +37 -0
- data/test/virtualbox/com/implementer/ffi_test.rb +519 -0
- data/test/virtualbox/com/implementer/mscom_test.rb +208 -0
- data/test/virtualbox/com/mscom_interface_test.rb +17 -0
- data/test/virtualbox/com/util_test.rb +17 -0
- data/test/virtualbox/dvd_test.rb +4 -95
- data/test/virtualbox/ext/platform_test.rb +8 -0
- data/test/virtualbox/extra_data_test.rb +78 -102
- data/test/virtualbox/forwarded_port_test.rb +57 -7
- data/test/virtualbox/global_test.rb +25 -115
- data/test/virtualbox/hard_drive_test.rb +49 -212
- data/test/virtualbox/lib_test.rb +93 -0
- data/test/virtualbox/medium_attachment_test.rb +147 -0
- data/test/virtualbox/medium_test.rb +192 -0
- data/test/virtualbox/network_adapter_test.rb +160 -0
- data/test/virtualbox/shared_folder_test.rb +144 -160
- data/test/virtualbox/storage_controller_test.rb +166 -45
- data/test/virtualbox/system_properties_test.rb +87 -0
- data/test/virtualbox/usb_controller_test.rb +104 -0
- data/test/virtualbox/version_test.rb +34 -0
- data/test/virtualbox/virtual_system_description_test.rb +61 -0
- data/test/virtualbox/vm_test.rb +288 -322
- data/test/virtualbox_test.rb +1 -9
- data/virtualbox.gemspec +139 -23
- metadata +143 -27
- data/lib/virtualbox/attached_device.rb +0 -249
- data/lib/virtualbox/command.rb +0 -109
- data/lib/virtualbox/image.rb +0 -137
- data/lib/virtualbox/nic.rb +0 -111
- data/lib/virtualbox/system_property.rb +0 -55
- data/lib/virtualbox/usb.rb +0 -72
- data/test/virtualbox/attached_device_test.rb +0 -303
- data/test/virtualbox/command_test.rb +0 -152
- data/test/virtualbox/image_test.rb +0 -190
- data/test/virtualbox/nic_test.rb +0 -76
- data/test/virtualbox/system_property_test.rb +0 -71
- data/test/virtualbox/usb_test.rb +0 -35
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
|
2
|
+
|
|
3
|
+
class COMFFIUtilTest < Test::Unit::TestCase
|
|
4
|
+
setup do
|
|
5
|
+
@klass = VirtualBox::COM::FFI::Util
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
context "converting function specs to FFI parameter lists" do
|
|
9
|
+
def assert_spec(spec, expected)
|
|
10
|
+
result = @klass.spec_to_ffi(spec)
|
|
11
|
+
result.shift
|
|
12
|
+
assert_equal expected, result
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
should "leaving primitives alone" do
|
|
16
|
+
assert_spec([:int], [:int])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
should "convert any out parameters to pointers" do
|
|
20
|
+
assert_spec([[:out, :int]], [:pointer])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
should "convert unicode strings to pointers" do
|
|
24
|
+
assert_spec([:unicode_string], [:pointer])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
should "convert COM interfaces to pointers" do
|
|
28
|
+
assert_spec([:VirtualBox], [:pointer])
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
should "convert enums to ints" do
|
|
32
|
+
assert_spec([:FirmwareType], [VirtualBox::COM::T_UINT32])
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
should "convert unknown classes to pointers" do
|
|
36
|
+
assert_spec([:VirtualBoxFoo], [:pointer])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
should "convert array parameters to two params" do
|
|
40
|
+
assert_spec([[:unicode_string]], [VirtualBox::COM::T_UINT32, :pointer])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
should "add a pointer at the beginning for the `this` parameter" do
|
|
44
|
+
assert_equal [:pointer], @klass.spec_to_ffi([])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
should "turn arrays into multiple pointers (one for size and one for the array)" do
|
|
48
|
+
assert_spec([[:out, [:int]]], [:pointer, :pointer])
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context "camelizing" do
|
|
53
|
+
should "camel case strings" do
|
|
54
|
+
tests = {
|
|
55
|
+
"foo_bar" => "FooBar",
|
|
56
|
+
"foobar" => "Foobar",
|
|
57
|
+
# Special cases below
|
|
58
|
+
"guest_os_type" => "GuestOSType",
|
|
59
|
+
"dhcp_servers" => "DHCPServers",
|
|
60
|
+
"dvd_images" => "DVDImages",
|
|
61
|
+
"usb_devices" => "USBDevices",
|
|
62
|
+
"ram_size" => "RAMSize",
|
|
63
|
+
"vram_size" => "VRAMSize",
|
|
64
|
+
"accelerate_3d_enabled" => "Accelerate3DEnabled",
|
|
65
|
+
"bios_settings" => "BIOSSettings",
|
|
66
|
+
"vrdp_server" => "VRDPServer",
|
|
67
|
+
"get_hw_virt_ex_property" => "GetHWVirtExProperty",
|
|
68
|
+
"query_saved_screenshot_png_size" => "QuerySavedScreenshotPNGSize",
|
|
69
|
+
"acpi_enabled" => "ACPIEnabled",
|
|
70
|
+
"io_apic_enabled" => "IOAPICEnabled",
|
|
71
|
+
"pxe_debug_enabled" => "PXEDebugEnabled",
|
|
72
|
+
"nat_foo" => "NATFoo",
|
|
73
|
+
"ide_emulation" => "IDEEmulation",
|
|
74
|
+
"create_vfs_explorer" => "CreateVFSExplorer",
|
|
75
|
+
"ip_address" => "IPAddress",
|
|
76
|
+
"max_vdi_size" => "MaxVDISize",
|
|
77
|
+
"cpu_count" => "CPUCount",
|
|
78
|
+
"recommended_hdd" => "RecommendedHDD"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
tests.each do |arg, expected|
|
|
82
|
+
assert_equal expected, @klass.camelize(arg)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
|
2
|
+
|
|
3
|
+
class COMFFIInterfaceBaseTest < Test::Unit::TestCase
|
|
4
|
+
setup do
|
|
5
|
+
@klass = VirtualBox::COM::FFIInterface
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
context "class methods" do
|
|
9
|
+
context "setting up" do
|
|
10
|
+
should "set the ffi lib to the given path then attach function" do
|
|
11
|
+
lib = :foo
|
|
12
|
+
|
|
13
|
+
setup_seq = sequence('setup_seq')
|
|
14
|
+
@klass.expects(:ffi_lib).with(lib).in_sequence(setup_seq)
|
|
15
|
+
@klass.expects(:attach_function).with(:VBoxGetXPCOMCFunctions, anything, anything).in_sequence(setup_seq)
|
|
16
|
+
@klass.setup(lib)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "creating" do
|
|
21
|
+
should "setup the initialize" do
|
|
22
|
+
lib = :foo
|
|
23
|
+
result = mock("result")
|
|
24
|
+
create_seq = sequence("create_seq")
|
|
25
|
+
@klass.expects(:setup).with(lib).in_sequence(create_seq)
|
|
26
|
+
@klass.expects(:new).returns(result).in_sequence(create_seq)
|
|
27
|
+
assert_equal result, @klass.create(lib)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context "initialization" do
|
|
33
|
+
should "initialize com interface" do
|
|
34
|
+
@klass.any_instance.expects(:initialize_com).once
|
|
35
|
+
@klass.new
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "initializing com interface" do
|
|
40
|
+
# TODO
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
|
2
|
+
|
|
3
|
+
class COMImplementerBaseTest < Test::Unit::TestCase
|
|
4
|
+
setup do
|
|
5
|
+
@klass = VirtualBox::COM::Implementer::Base
|
|
6
|
+
@interface = mock("interface")
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
context "with an instance" do
|
|
10
|
+
setup do
|
|
11
|
+
@instance = @klass.new(@interface)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "inferring types" do
|
|
15
|
+
should "return the proper values" do
|
|
16
|
+
expectations = {
|
|
17
|
+
:int => [:int, :int],
|
|
18
|
+
:unicode_string => [:pointer, :unicode_string],
|
|
19
|
+
:Host => [:pointer, :interface]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
expectations.each do |original, result|
|
|
23
|
+
assert_equal result, @instance.infer_type(original)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "getting an interface class" do
|
|
29
|
+
should "get from COM::Interface and return" do
|
|
30
|
+
result = mock("result")
|
|
31
|
+
type_name = :foo
|
|
32
|
+
VirtualBox::COM::Interface.expects(:const_get).with(type_name).returns(result)
|
|
33
|
+
assert_equal result, @instance.interface_klass(type_name)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
|
2
|
+
|
|
3
|
+
class COMImplementerFFITest < Test::Unit::TestCase
|
|
4
|
+
setup do
|
|
5
|
+
@klass = VirtualBox::COM::Implementer::FFI
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
context "initializing" do
|
|
9
|
+
setup do
|
|
10
|
+
@interface = mock("interface")
|
|
11
|
+
@interface.stubs(:class).returns(VirtualBox::COM::Interface::Session)
|
|
12
|
+
|
|
13
|
+
@ffi = mock("ffi")
|
|
14
|
+
|
|
15
|
+
@pointer = mock("pointer")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
should "initialize the FFI interface associated with the AbstractInterface" do
|
|
19
|
+
result = mock("result")
|
|
20
|
+
VirtualBox::COM::FFI::Session.expects(:new).with(@pointer).once.returns(result)
|
|
21
|
+
instance = @klass.new(@interface, @ffi, @pointer)
|
|
22
|
+
assert_equal result, instance.ffi_interface
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context "with an instance" do
|
|
27
|
+
setup do
|
|
28
|
+
@lib_base = mock("lib_base")
|
|
29
|
+
@ffi_interface = mock("ffi_interface")
|
|
30
|
+
@ffi_class = mock("ffi_class")
|
|
31
|
+
@pointer = mock("pointer")
|
|
32
|
+
|
|
33
|
+
@ffi_class.stubs(:new).returns(@ffi_interface)
|
|
34
|
+
@klass.any_instance.stubs(:ffi_class).returns(@ffi_class)
|
|
35
|
+
|
|
36
|
+
@instance = @klass.new(@interface, @lib_base, @pointer)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "reading a property" do
|
|
40
|
+
should "call call_vtbl_function with the proper arguments" do
|
|
41
|
+
@instance.expects(:call_vtbl_function).with(:get_foo, [[:out, :bar]])
|
|
42
|
+
@instance.read_property(:foo, { :value_type => :bar })
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "writing a property" do
|
|
47
|
+
should "call call_vtbl_function with the proper arguments" do
|
|
48
|
+
@instance.expects(:call_vtbl_function).with(:set_foo, [:bar], [7])
|
|
49
|
+
@instance.write_property(:foo, 7, { :value_type => :bar })
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context "calling a function" do
|
|
54
|
+
should "call call_vtbl_function with the proper arguments" do
|
|
55
|
+
@instance.expects(:call_vtbl_function).with(:say_hello, [:int, [:out, :string]], [1, 2, 3])
|
|
56
|
+
@instance.call_function(:say_hello, [1, 2, 3], {
|
|
57
|
+
:value_type => :string,
|
|
58
|
+
:spec => [:int]
|
|
59
|
+
})
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context "calling a vtbl function" do
|
|
64
|
+
setup do
|
|
65
|
+
@vtbl = mock("vtbl")
|
|
66
|
+
@vtbl_parent = mock("vtbl_parent")
|
|
67
|
+
@ffi_interface.stubs(:vtbl).returns(@vtbl)
|
|
68
|
+
@ffi_interface.stubs(:vtbl_parent).returns(@vtbl_parent)
|
|
69
|
+
|
|
70
|
+
@proc = mock("proc")
|
|
71
|
+
|
|
72
|
+
@name = :foo
|
|
73
|
+
@spec = [:bar]
|
|
74
|
+
@args = [:baz]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
should "pass in the formal args then return the values from them" do
|
|
78
|
+
result = mock("result")
|
|
79
|
+
@formal = [:foo]
|
|
80
|
+
|
|
81
|
+
@instance.expects(:spec_to_args).with(@spec, @args).returns(@formal)
|
|
82
|
+
@vtbl.expects(:[]).with(@name).returns(@proc)
|
|
83
|
+
@instance.expects(:call_and_check).with(@proc, @vtbl_parent, *@formal)
|
|
84
|
+
@instance.expects(:values_from_formal_args).with(@spec, @formal).returns(result)
|
|
85
|
+
assert_equal result, @instance.call_vtbl_function(@name, @spec, @args)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context "function calling and error checking" do
|
|
90
|
+
setup do
|
|
91
|
+
@function = mock("function")
|
|
92
|
+
@function.stubs(:call).returns(0)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
should "raise an exception if an error occurred" do
|
|
96
|
+
@function.expects(:call).returns(0x8000_4002)
|
|
97
|
+
assert_raises(VirtualBox::Exceptions::FFIException) {
|
|
98
|
+
@instance.call_and_check(@function)
|
|
99
|
+
}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
should "not raise an exception if an error did not occur" do
|
|
103
|
+
@function.expects(:call).returns(0x0000_0000)
|
|
104
|
+
assert_nothing_raised {
|
|
105
|
+
@instance.call_and_check(@function)
|
|
106
|
+
}
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
should "not raise an exception for NS_ERROR_NOT_IMPLEMENTED" do
|
|
110
|
+
@function.expects(:call).returns(0x8000_4001)
|
|
111
|
+
assert_nothing_raised {
|
|
112
|
+
@instance.call_and_check(@function)
|
|
113
|
+
}
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
should "forward arguments" do
|
|
117
|
+
@function.expects(:call).with(1,2,3).returns(0)
|
|
118
|
+
assert_nothing_raised {
|
|
119
|
+
@instance.call_and_check(@function, 1, 2, 3)
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context "result code mapping" do
|
|
125
|
+
should "return a mapped exception object if it exists" do
|
|
126
|
+
assert_equal VirtualBox::Exceptions::ObjectNotFoundException, @instance.exception_map(0x80BB_0001)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
should "return FFIException if no mapping is found" do
|
|
130
|
+
assert_equal VirtualBox::Exceptions::FFIException, @instance.exception_map(-5)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context "spec to formal argument list" do
|
|
135
|
+
setup do
|
|
136
|
+
@pointer = mock("pointer")
|
|
137
|
+
@instance.stubs(:pointer_for_type).returns(@pointer)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
should "replace primitives with their types" do
|
|
141
|
+
assert_equal [7], @instance.spec_to_args([:int], [7])
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
should "replace booleans with 1/0" do
|
|
145
|
+
bool = VirtualBox::COM::T_BOOL
|
|
146
|
+
assert_equal [1,0], @instance.spec_to_args([bool, bool], [true, false])
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
should "replace single out items with a pointer" do
|
|
150
|
+
@instance.expects(:pointer_for_type).with(:foo).returns(@pointer)
|
|
151
|
+
assert_equal [@pointer], @instance.spec_to_args([[:out, :foo]])
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
should "convert Ruby strings into unicode strings" do
|
|
155
|
+
spec = [VirtualBox::COM::WSTRING]
|
|
156
|
+
args = ["foo"]
|
|
157
|
+
|
|
158
|
+
@instance.expects(:string_to_utf16).with(args[0]).returns("bar")
|
|
159
|
+
assert_equal ["bar"], @instance.spec_to_args(spec, args)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
should "convert interfaces with nil arguments to nil" do
|
|
163
|
+
spec = [:Machine]
|
|
164
|
+
args = [nil]
|
|
165
|
+
|
|
166
|
+
assert_equal [nil], @instance.spec_to_args(spec, args)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
should "convert enums to their property indices" do
|
|
170
|
+
spec = [:FirmwareType]
|
|
171
|
+
args = [:efi]
|
|
172
|
+
|
|
173
|
+
assert_equal [1], @instance.spec_to_args(spec, args)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
should "replace array types with two parameters" do
|
|
177
|
+
@counter_pointer = mock("count_pointer")
|
|
178
|
+
@pointer = mock("pointer")
|
|
179
|
+
|
|
180
|
+
@instance.expects(:pointer_for_type).with(VirtualBox::COM::T_UINT32).returns(@count_pointer)
|
|
181
|
+
@instance.expects(:pointer_for_type).with(:foo).returns(@pointer)
|
|
182
|
+
assert_equal [@count_pointer, @pointer], @instance.spec_to_args([[:out, [:foo]]])
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
context "values from a formal parameter list" do
|
|
187
|
+
should "return nil if there are no output parameters" do
|
|
188
|
+
spec = []
|
|
189
|
+
formal = []
|
|
190
|
+
|
|
191
|
+
assert_nil @instance.values_from_formal_args(spec, formal)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
should "dereference the pointer with proper type" do
|
|
195
|
+
pointer = mock("pointer")
|
|
196
|
+
spec = [[:out, :foo]]
|
|
197
|
+
formal = [pointer]
|
|
198
|
+
|
|
199
|
+
result = mock("result")
|
|
200
|
+
@instance.expects(:dereference_pointer).with(pointer, :foo).once.returns(result)
|
|
201
|
+
assert_equal result, @instance.values_from_formal_args(spec, formal)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
should "dereference the array pointer with the proper type" do
|
|
205
|
+
count_pointer = mock("count_pointer")
|
|
206
|
+
pointer = mock("pointer")
|
|
207
|
+
count = mock("count")
|
|
208
|
+
result = mock("result")
|
|
209
|
+
spec = [[:out, [:foo]]]
|
|
210
|
+
formal = [count_pointer, pointer]
|
|
211
|
+
|
|
212
|
+
@instance.expects(:dereference_pointer).with(count_pointer, VirtualBox::COM::T_UINT32).returns(count)
|
|
213
|
+
@instance.expects(:dereference_pointer_array).with(pointer, :foo, count).returns(result)
|
|
214
|
+
assert_equal result, @instance.values_from_formal_args(spec, formal)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
should "return an array for multiple values" do
|
|
218
|
+
spec = [:int, [:out, :foo], [:out, :bar]]
|
|
219
|
+
formal = [1,2,3]
|
|
220
|
+
|
|
221
|
+
result = mock("result")
|
|
222
|
+
@instance.stubs(:dereference_pointer).returns(result)
|
|
223
|
+
assert_equal [result, result], @instance.values_from_formal_args(spec, formal)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
context "pointers for type" do
|
|
228
|
+
setup do
|
|
229
|
+
@pointer = mock("pointer")
|
|
230
|
+
FFI::MemoryPointer.stubs(:new).returns(@pointer)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
should "create a pointer type for the given type" do
|
|
234
|
+
@instance.expects(:infer_type).with(:MyType).returns([:pointer, :struct])
|
|
235
|
+
FFI::MemoryPointer.expects(:new).with(:pointer).once.returns(@pointer)
|
|
236
|
+
@instance.pointer_for_type(:MyType) do |ptr, type|
|
|
237
|
+
assert_equal :struct, type
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
should "return the result of the yield" do
|
|
242
|
+
expected = mock("result")
|
|
243
|
+
result = @instance.pointer_for_type(:int) do |ptr, type|
|
|
244
|
+
expected
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
assert_equal expected, result
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
should "return the pointer if no block is given" do
|
|
251
|
+
assert_equal @pointer, @instance.pointer_for_type(:int)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
context "dereferencing pointers" do
|
|
256
|
+
setup do
|
|
257
|
+
@pointer = mock('pointer')
|
|
258
|
+
@pointer.stubs(:respond_to?).returns(true)
|
|
259
|
+
@pointer.stubs(:get_bar).returns("foo")
|
|
260
|
+
|
|
261
|
+
@type = :zoo
|
|
262
|
+
|
|
263
|
+
@c_type = :foo
|
|
264
|
+
@inferred_type = :bar
|
|
265
|
+
@instance.stubs(:infer_type).returns([@c_type, @inferred_type])
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
should "infer the type" do
|
|
269
|
+
@instance.expects(:infer_type).with(@type).returns([@c_type, @inferred_type])
|
|
270
|
+
@instance.dereference_pointer(@pointer, @type)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
should "call get_* method on pointer if it exists" do
|
|
274
|
+
result = mock("result")
|
|
275
|
+
@pointer.expects(:respond_to?).with("get_#{@inferred_type}".to_sym).returns(true)
|
|
276
|
+
@pointer.expects("get_#{@inferred_type}".to_sym).with(0).returns(result)
|
|
277
|
+
assert_equal result, @instance.dereference_pointer(@pointer, @type)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
should "return a false bool if type is bool and failure" do
|
|
281
|
+
@pointer.expects(:get_bar).returns(0)
|
|
282
|
+
result = @instance.dereference_pointer(@pointer, VirtualBox::COM::T_BOOL)
|
|
283
|
+
assert_equal false, result
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
should "return a true bool if type is bool and success" do
|
|
287
|
+
@pointer.expects(:get_bar).returns(1)
|
|
288
|
+
result = @instance.dereference_pointer(@pointer, VirtualBox::COM::T_BOOL)
|
|
289
|
+
assert_equal true, result
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
should "call read_* on Util if pointer doesn't support it" do
|
|
293
|
+
result = mock("result")
|
|
294
|
+
@pointer.expects(:respond_to?).with("get_#{@inferred_type}".to_sym).returns(false)
|
|
295
|
+
@instance.expects("read_#{@inferred_type}".to_sym).with(@pointer, @type).returns(result)
|
|
296
|
+
assert_equal result, @instance.dereference_pointer(@pointer, @type)
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
context "dereferencing pointer array" do
|
|
301
|
+
setup do
|
|
302
|
+
@array_pointer = mock('array_pointer')
|
|
303
|
+
@array_pointer.stubs(:respond_to?).returns(true)
|
|
304
|
+
@array_pointer.stubs(:get_array_of_bar)
|
|
305
|
+
|
|
306
|
+
@pointer = mock('pointer')
|
|
307
|
+
@pointer.stubs(:get_pointer).with(0).returns(@array_pointer)
|
|
308
|
+
|
|
309
|
+
@type = :zoo
|
|
310
|
+
@length = 3
|
|
311
|
+
|
|
312
|
+
@c_type = :foo
|
|
313
|
+
@inferred_type = :bar
|
|
314
|
+
@instance.stubs(:infer_type).returns([@c_type, @inferred_type])
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
should "infer the type" do
|
|
318
|
+
@instance.expects(:infer_type).with(@type).returns([@c_type, @inferred_type])
|
|
319
|
+
@instance.dereference_pointer_array(@pointer, @type, @length)
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
should "return an empty array if count is zero" do
|
|
323
|
+
assert_equal [], @instance.dereference_pointer_array(@pointer, @type, 0)
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
should "call get_* method on array pointer if it exists" do
|
|
327
|
+
result = mock("result")
|
|
328
|
+
@array_pointer.expects(:respond_to?).with("get_array_of_#{@inferred_type}".to_sym).returns(true)
|
|
329
|
+
@array_pointer.expects("get_array_of_#{@inferred_type}".to_sym).with(0, @length).returns(result)
|
|
330
|
+
assert_equal result, @instance.dereference_pointer_array(@pointer, @type, @length)
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
should "call read_* on Util if pointer doesn't support it" do
|
|
334
|
+
result = mock("result")
|
|
335
|
+
@array_pointer.expects(:respond_to?).with("get_array_of_#{@inferred_type}".to_sym).returns(false)
|
|
336
|
+
@instance.expects("read_array_of_#{@inferred_type}".to_sym).with(@array_pointer, @type, @length).returns(result)
|
|
337
|
+
assert_equal result, @instance.dereference_pointer_array(@pointer, @type, @length)
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
context "custom pointer dereferencers" do
|
|
342
|
+
context "reading unicode string" do
|
|
343
|
+
setup do
|
|
344
|
+
@sub_ptr = mock("sub_ptr")
|
|
345
|
+
@sub_ptr.stubs(:null?).returns(false)
|
|
346
|
+
|
|
347
|
+
@ptr = mock("pointer")
|
|
348
|
+
@ptr.stubs(:get_pointer).returns(@sub_ptr)
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
should "return empty string for null pointer" do
|
|
352
|
+
@sub_ptr.expects(:null?).returns(true)
|
|
353
|
+
@instance.expects(:utf16_to_string).never
|
|
354
|
+
assert_equal "", @instance.read_unicode_string(@ptr)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
should "call utf16_to_string on the dereferenced pointer" do
|
|
358
|
+
result = mock("result")
|
|
359
|
+
@ptr.expects(:get_pointer).with(0).returns(@sub_ptr)
|
|
360
|
+
@instance.expects(:utf16_to_string).with(@sub_ptr).returns(result)
|
|
361
|
+
assert_equal result, @instance.read_unicode_string(@ptr)
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
context "reading interfaces" do
|
|
366
|
+
setup do
|
|
367
|
+
@original_type = :foo
|
|
368
|
+
@interface_klass = mock("foo_class")
|
|
369
|
+
|
|
370
|
+
@sub_ptr = mock("sub_ptr")
|
|
371
|
+
@sub_ptr.stubs(:null?).returns(false)
|
|
372
|
+
|
|
373
|
+
@ptr = mock("pointer")
|
|
374
|
+
@ptr.stubs(:get_pointer).with(0).returns(@sub_ptr)
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
should "convert type to a const and return instance" do
|
|
378
|
+
@instance.expects(:interface_klass).with(@original_type).returns(@interface_klass)
|
|
379
|
+
@interface_klass.expects(:new).with(@klass, @instance.lib, @ptr.get_pointer(0)).returns(@instance)
|
|
380
|
+
assert_equal @instance, @instance.read_interface(@ptr, @original_type)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
should "return nil if pointer is null" do
|
|
384
|
+
@sub_ptr.expects(:null?).returns(true)
|
|
385
|
+
@instance.expects(:interface_klass).never
|
|
386
|
+
assert_nil @instance.read_interface(@ptr, @original_type)
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
context "reading an enum" do
|
|
391
|
+
setup do
|
|
392
|
+
@enum_klass = mock("enum_class")
|
|
393
|
+
@enum_klass.stubs(:[])
|
|
394
|
+
|
|
395
|
+
@original_type = :foo
|
|
396
|
+
@value = 7
|
|
397
|
+
|
|
398
|
+
@ptr = mock("ptr")
|
|
399
|
+
@ptr.stubs(:get_uint).returns(@value)
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
should "convert type to class and get the value" do
|
|
403
|
+
result = mock("result")
|
|
404
|
+
@instance.expects(:interface_klass).with(@original_type).returns(@enum_klass)
|
|
405
|
+
@enum_klass.expects(:[]).with(@value).returns(result)
|
|
406
|
+
assert_equal result, @instance.read_enum(@ptr, @original_type)
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
context "reading an array of enums" do
|
|
411
|
+
setup do
|
|
412
|
+
@type = :foo
|
|
413
|
+
@length = 3
|
|
414
|
+
|
|
415
|
+
@pointers = []
|
|
416
|
+
@length.times do |i|
|
|
417
|
+
pointer = mock("pointer#{i}")
|
|
418
|
+
@pointers << pointer
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
@pointer = mock("pointer")
|
|
422
|
+
@pointer.stubs(:get_array_of_uint).returns(@pointers)
|
|
423
|
+
|
|
424
|
+
@interface_klass = mock("foo_class")
|
|
425
|
+
|
|
426
|
+
@instance.stubs(:read_struct).returns("foo")
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
should "grab the array of pointers, then convert each to a struct" do
|
|
430
|
+
deref_seq = sequence("deref_seq")
|
|
431
|
+
@instance.expects(:interface_klass).with(@type).returns(@interface_klass)
|
|
432
|
+
@pointer.expects(:get_array_of_uint).with(0, @length).returns(@pointers).in_sequence(deref_seq)
|
|
433
|
+
return_values = @pointers.collect do |pointer|
|
|
434
|
+
value = "struct_of_pointer: #{pointer}"
|
|
435
|
+
@interface_klass.expects(:[]).with(pointer).returns(value).in_sequence(deref_seq)
|
|
436
|
+
value
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
assert_equal return_values, @instance.read_array_of_enum(@pointer, @type, @length)
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
context "reading an array of interfaces" do
|
|
444
|
+
setup do
|
|
445
|
+
@type = :foo
|
|
446
|
+
@length = 3
|
|
447
|
+
|
|
448
|
+
@pointers = []
|
|
449
|
+
@length.times do |i|
|
|
450
|
+
pointer = mock("pointer#{i}")
|
|
451
|
+
@pointers << pointer
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
@pointer = mock("pointer")
|
|
455
|
+
@pointer.stubs(:get_array_of_pointer).returns(@pointers)
|
|
456
|
+
|
|
457
|
+
@interface_klass = mock("foo_class")
|
|
458
|
+
|
|
459
|
+
@instance.stubs(:read_struct).returns("foo")
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
should "grab the array of pointers, then convert each to a struct" do
|
|
463
|
+
deref_seq = sequence("deref_seq")
|
|
464
|
+
@instance.expects(:interface_klass).with(@type).returns(@interface_klass)
|
|
465
|
+
@pointer.expects(:get_array_of_pointer).with(0, @length).returns(@pointers).in_sequence(deref_seq)
|
|
466
|
+
return_values = @pointers.collect do |pointer|
|
|
467
|
+
value = "struct_of_pointer: #{pointer}"
|
|
468
|
+
@interface_klass.expects(:new).with(@klass, @instance.lib, pointer).returns(value).in_sequence(deref_seq)
|
|
469
|
+
value
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
assert_equal return_values, @instance.read_array_of_interface(@pointer, @type, @length)
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
context "reading an array of unicode strings" do
|
|
477
|
+
setup do
|
|
478
|
+
@type = :foo
|
|
479
|
+
@length = 3
|
|
480
|
+
|
|
481
|
+
@pointers = []
|
|
482
|
+
@length.times do |i|
|
|
483
|
+
pointer = mock("pointer#{i}")
|
|
484
|
+
pointer.stubs(:null?).returns(false)
|
|
485
|
+
@pointers << pointer
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
@pointer = mock("pointer")
|
|
489
|
+
@pointer.stubs(:get_array_of_pointer).returns(@pointers)
|
|
490
|
+
|
|
491
|
+
@instance.stubs(:read_struct).returns("foo")
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
should "grab the array of pointers, then convert each to a UTF8 string" do
|
|
495
|
+
deref_seq = sequence("deref_seq")
|
|
496
|
+
@pointer.expects(:get_array_of_pointer).with(0, @length).returns(@pointers).in_sequence(deref_seq)
|
|
497
|
+
return_values = @pointers.collect do |pointer|
|
|
498
|
+
value = "struct_of_pointer: #{pointer}"
|
|
499
|
+
@instance.expects(:utf16_to_string).with(pointer).returns(value).in_sequence(deref_seq)
|
|
500
|
+
value
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
assert_equal return_values, @instance.read_array_of_unicode_string(@pointer, @type, @length)
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
should "treat nil pointers as nil" do
|
|
507
|
+
deref_seq = sequence("deref_seq")
|
|
508
|
+
@pointer.expects(:get_array_of_pointer).with(0, @length).returns(@pointers).in_sequence(deref_seq)
|
|
509
|
+
return_values = @pointers.collect do |pointer|
|
|
510
|
+
pointer.expects(:null?).returns(true)
|
|
511
|
+
nil
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
assert_equal return_values, @instance.read_array_of_unicode_string(@pointer, @type, @length)
|
|
515
|
+
end
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
end
|