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.
Files changed (162) hide show
  1. data/.gitignore +2 -1
  2. data/Gemfile +1 -1
  3. data/Rakefile +1 -1
  4. data/Readme.md +5 -21
  5. data/VERSION +1 -1
  6. data/docs/WhatsNew.md +9 -47
  7. data/lib/virtualbox.rb +7 -30
  8. data/lib/virtualbox/abstract_model.rb +25 -5
  9. data/lib/virtualbox/abstract_model/attributable.rb +5 -1
  10. data/lib/virtualbox/abstract_model/dirty.rb +2 -0
  11. data/lib/virtualbox/abstract_model/interface_attributes.rb +96 -0
  12. data/lib/virtualbox/abstract_model/relatable.rb +19 -8
  13. data/lib/virtualbox/appliance.rb +59 -0
  14. data/lib/virtualbox/audio_adapter.rb +44 -0
  15. data/lib/virtualbox/bios.rb +44 -0
  16. data/lib/virtualbox/com.rb +23 -0
  17. data/lib/virtualbox/com/abstract_enum.rb +42 -0
  18. data/lib/virtualbox/com/abstract_implementer.rb +43 -0
  19. data/lib/virtualbox/com/abstract_interface.rb +165 -0
  20. data/lib/virtualbox/com/ffi/interface.rb +141 -0
  21. data/lib/virtualbox/com/ffi/interfaces.rb +42 -0
  22. data/lib/virtualbox/com/ffi/util.rb +101 -0
  23. data/lib/virtualbox/com/ffi/vboxxpcomc.rb +31 -0
  24. data/lib/virtualbox/com/ffi_interface.rb +65 -0
  25. data/lib/virtualbox/com/implementer/base.rb +52 -0
  26. data/lib/virtualbox/com/implementer/ffi.rb +350 -0
  27. data/lib/virtualbox/com/implementer/mscom.rb +165 -0
  28. data/lib/virtualbox/com/implementer/nil.rb +10 -0
  29. data/lib/virtualbox/com/interface/appliance.rb +20 -0
  30. data/lib/virtualbox/com/interface/audio_adapter.rb +13 -0
  31. data/lib/virtualbox/com/interface/audio_controller_type.rb +9 -0
  32. data/lib/virtualbox/com/interface/audio_driver_type.rb +9 -0
  33. data/lib/virtualbox/com/interface/bios_boot_menu_mode.rb +9 -0
  34. data/lib/virtualbox/com/interface/bios_settings.rb +19 -0
  35. data/lib/virtualbox/com/interface/clipboard_mode.rb +9 -0
  36. data/lib/virtualbox/com/interface/console.rb +48 -0
  37. data/lib/virtualbox/com/interface/cpu_property_type.rb +9 -0
  38. data/lib/virtualbox/com/interface/device_type.rb +9 -0
  39. data/lib/virtualbox/com/interface/dhcp_server.rb +20 -0
  40. data/lib/virtualbox/com/interface/firmware_type.rb +9 -0
  41. data/lib/virtualbox/com/interface/guest_os_type.rb +21 -0
  42. data/lib/virtualbox/com/interface/host.rb +40 -0
  43. data/lib/virtualbox/com/interface/host_network_interface.rb +28 -0
  44. data/lib/virtualbox/com/interface/host_network_interface_medium_type.rb +9 -0
  45. data/lib/virtualbox/com/interface/host_network_interface_status.rb +9 -0
  46. data/lib/virtualbox/com/interface/host_network_interface_type.rb +9 -0
  47. data/lib/virtualbox/com/interface/host_usb_device.rb +11 -0
  48. data/lib/virtualbox/com/interface/host_usb_device_filter.rb +11 -0
  49. data/lib/virtualbox/com/interface/hw_virt_ex_property_type.rb +9 -0
  50. data/lib/virtualbox/com/interface/machine.rb +103 -0
  51. data/lib/virtualbox/com/interface/machine_state.rb +12 -0
  52. data/lib/virtualbox/com/interface/medium.rb +48 -0
  53. data/lib/virtualbox/com/interface/medium_attachment.rb +16 -0
  54. data/lib/virtualbox/com/interface/medium_format.rb +16 -0
  55. data/lib/virtualbox/com/interface/medium_state.rb +9 -0
  56. data/lib/virtualbox/com/interface/medium_type.rb +9 -0
  57. data/lib/virtualbox/com/interface/medium_variant.rb +9 -0
  58. data/lib/virtualbox/com/interface/network_adapter.rb +28 -0
  59. data/lib/virtualbox/com/interface/network_adapter_type.rb +9 -0
  60. data/lib/virtualbox/com/interface/network_attachment_type.rb +9 -0
  61. data/lib/virtualbox/com/interface/nsiexception.rb +21 -0
  62. data/lib/virtualbox/com/interface/nsisupports.rb +13 -0
  63. data/lib/virtualbox/com/interface/parallel_port.rb +15 -0
  64. data/lib/virtualbox/com/interface/port_mode.rb +9 -0
  65. data/lib/virtualbox/com/interface/progress.rb +58 -0
  66. data/lib/virtualbox/com/interface/serial_port.rb +17 -0
  67. data/lib/virtualbox/com/interface/session.rb +16 -0
  68. data/lib/virtualbox/com/interface/session_state.rb +9 -0
  69. data/lib/virtualbox/com/interface/session_type.rb +9 -0
  70. data/lib/virtualbox/com/interface/shared_folder.rb +15 -0
  71. data/lib/virtualbox/com/interface/snapshot.rb +18 -0
  72. data/lib/virtualbox/com/interface/storage_bus.rb +9 -0
  73. data/lib/virtualbox/com/interface/storage_controller.rb +21 -0
  74. data/lib/virtualbox/com/interface/storage_controller_type.rb +9 -0
  75. data/lib/virtualbox/com/interface/system_properties.rb +35 -0
  76. data/lib/virtualbox/com/interface/usb_controller.rb +18 -0
  77. data/lib/virtualbox/com/interface/usb_device.rb +22 -0
  78. data/lib/virtualbox/com/interface/usb_device_filter.rb +21 -0
  79. data/lib/virtualbox/com/interface/usb_device_filter_action.rb +9 -0
  80. data/lib/virtualbox/com/interface/usb_device_state.rb +9 -0
  81. data/lib/virtualbox/com/interface/virtual_box_error_info.rb +15 -0
  82. data/lib/virtualbox/com/interface/virtual_system_description.rb +17 -0
  83. data/lib/virtualbox/com/interface/virtual_system_description_type.rb +12 -0
  84. data/lib/virtualbox/com/interface/virtual_system_description_value_type.rb +9 -0
  85. data/lib/virtualbox/com/interface/virtualbox.rb +54 -0
  86. data/lib/virtualbox/com/interface/vrdp_auth_type.rb +9 -0
  87. data/lib/virtualbox/com/interface/vrdp_server.rb +17 -0
  88. data/lib/virtualbox/com/mscom_interface.rb +22 -0
  89. data/lib/virtualbox/com/util.rb +18 -0
  90. data/lib/virtualbox/dvd.rb +7 -94
  91. data/lib/virtualbox/exceptions.rb +24 -0
  92. data/lib/virtualbox/ext/glob_loader.rb +22 -0
  93. data/lib/virtualbox/ext/logger.rb +38 -0
  94. data/lib/virtualbox/ext/platform.rb +1 -1
  95. data/lib/virtualbox/extra_data.rb +25 -37
  96. data/lib/virtualbox/forwarded_port.rb +35 -13
  97. data/lib/virtualbox/global.rb +22 -80
  98. data/lib/virtualbox/hard_drive.rb +30 -97
  99. data/lib/virtualbox/lib.rb +82 -0
  100. data/lib/virtualbox/media.rb +7 -6
  101. data/lib/virtualbox/medium.rb +138 -0
  102. data/lib/virtualbox/medium_attachment.rb +61 -0
  103. data/lib/virtualbox/network_adapter.rb +134 -0
  104. data/lib/virtualbox/shared_folder.rb +53 -78
  105. data/lib/virtualbox/storage_controller.rb +76 -20
  106. data/lib/virtualbox/system_properties.rb +74 -0
  107. data/lib/virtualbox/usb_controller.rb +55 -0
  108. data/lib/virtualbox/version.rb +15 -0
  109. data/lib/virtualbox/virtual_system_description.rb +47 -0
  110. data/lib/virtualbox/vm.rb +160 -272
  111. data/test/test_helper.rb +0 -108
  112. data/test/virtualbox/abstract_model/attributable_test.rb +7 -1
  113. data/test/virtualbox/abstract_model/dirty_test.rb +1 -1
  114. data/test/virtualbox/abstract_model/interface_attributes_test.rb +169 -0
  115. data/test/virtualbox/abstract_model/relatable_test.rb +20 -0
  116. data/test/virtualbox/abstract_model_test.rb +40 -5
  117. data/test/virtualbox/appliance_test.rb +152 -0
  118. data/test/virtualbox/audio_adapter_test.rb +83 -0
  119. data/test/virtualbox/bios_test.rb +83 -0
  120. data/test/virtualbox/com/abstract_enum_test.rb +48 -0
  121. data/test/virtualbox/com/abstract_implementer_test.rb +39 -0
  122. data/test/virtualbox/com/abstract_interface_test.rb +139 -0
  123. data/test/virtualbox/com/ffi/interface_test.rb +249 -0
  124. data/test/virtualbox/com/ffi/util_test.rb +86 -0
  125. data/test/virtualbox/com/ffi_interface_test.rb +42 -0
  126. data/test/virtualbox/com/implementer/base_test.rb +37 -0
  127. data/test/virtualbox/com/implementer/ffi_test.rb +519 -0
  128. data/test/virtualbox/com/implementer/mscom_test.rb +208 -0
  129. data/test/virtualbox/com/mscom_interface_test.rb +17 -0
  130. data/test/virtualbox/com/util_test.rb +17 -0
  131. data/test/virtualbox/dvd_test.rb +4 -95
  132. data/test/virtualbox/ext/platform_test.rb +8 -0
  133. data/test/virtualbox/extra_data_test.rb +78 -102
  134. data/test/virtualbox/forwarded_port_test.rb +57 -7
  135. data/test/virtualbox/global_test.rb +25 -115
  136. data/test/virtualbox/hard_drive_test.rb +49 -212
  137. data/test/virtualbox/lib_test.rb +93 -0
  138. data/test/virtualbox/medium_attachment_test.rb +147 -0
  139. data/test/virtualbox/medium_test.rb +192 -0
  140. data/test/virtualbox/network_adapter_test.rb +160 -0
  141. data/test/virtualbox/shared_folder_test.rb +144 -160
  142. data/test/virtualbox/storage_controller_test.rb +166 -45
  143. data/test/virtualbox/system_properties_test.rb +87 -0
  144. data/test/virtualbox/usb_controller_test.rb +104 -0
  145. data/test/virtualbox/version_test.rb +34 -0
  146. data/test/virtualbox/virtual_system_description_test.rb +61 -0
  147. data/test/virtualbox/vm_test.rb +288 -322
  148. data/test/virtualbox_test.rb +1 -9
  149. data/virtualbox.gemspec +139 -23
  150. metadata +143 -27
  151. data/lib/virtualbox/attached_device.rb +0 -249
  152. data/lib/virtualbox/command.rb +0 -109
  153. data/lib/virtualbox/image.rb +0 -137
  154. data/lib/virtualbox/nic.rb +0 -111
  155. data/lib/virtualbox/system_property.rb +0 -55
  156. data/lib/virtualbox/usb.rb +0 -72
  157. data/test/virtualbox/attached_device_test.rb +0 -303
  158. data/test/virtualbox/command_test.rb +0 -152
  159. data/test/virtualbox/image_test.rb +0 -190
  160. data/test/virtualbox/nic_test.rb +0 -76
  161. data/test/virtualbox/system_property_test.rb +0 -71
  162. 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