win 0.1.27 → 0.3.1

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.
@@ -1,342 +1,342 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
- require 'win/library'
3
-
4
- module WinLibraryTest
5
-
6
- include WinTest
7
-
8
- module MyLib # namespace for defined functions
9
- include Win::Library
10
- end
11
- include MyLib
12
-
13
- def should_be symbol, api
14
- case symbol
15
- when :find_window
16
- #api.dll_name.should == 'user32' # The name of the DLL that exports the API function
17
- api.effective_function_name.should == 'FindWindowA' # Actual function returned by the constructor: 'GetUserName' ->'GetUserNameA' or 'GetUserNameW'
18
- api.function_name.should == :FindWindow # The name of the function passed to the constructor
19
- api.prototype.should == [:pointer, :pointer] # The prototype, returned as an array of characters
20
- api.return_type.should == :ulong # The prototype, returned as an array of characters
21
- end
22
- end
23
-
24
- def should_count_args(*methods, rights, wrongs)
25
- rights = [rights].flatten
26
- wrongs = [wrongs].flatten
27
- methods.each do |method|
28
- (0..8).each do |n|
29
- if n == rights.size
30
- expect {send method, *rights}.to_not raise_error
31
- else
32
- args = (1..n).map {wrongs[rand(wrongs.size)]}
33
- expect {send method, *args}.
34
- to raise_error "wrong number of arguments (#{args.size} for #{rights.size})"
35
- end
36
- end
37
- end
38
- end
39
-
40
- def any_handle
41
- MyLib.function :FindWindow, 'PP', 'L' unless respond_to? :find_window
42
- find_window(nil, nil)
43
- end
44
-
45
- def redefined_methods
46
- [:FindWindow, :IsWindow, :EnumWindows, :GetComputerName, :GetForegroundWindow]
47
- end
48
-
49
- def hide_method(*names) # hide original method(s) if it is defined
50
- names.map(&:to_s).each do |name|
51
- MyLib.module_eval do
52
- # + remove_const
53
- aliases = generate_names(name).flatten + [name]
54
- aliases.map(&:to_s).each do |ali|
55
- if method_defined? ali
56
- alias_method "original_#{ali}".to_sym, ali
57
- remove_method ali
58
- end
59
- end
60
- end
61
- end
62
- end
63
-
64
- def restore_method(*names) # restore original method if it was hidden
65
- names.map(&:to_s).each do |name|
66
- MyLib.module_eval do
67
- aliases = generate_names(name).flatten + [name]
68
- aliases.map(&:to_s).each do |ali|
69
- temp = "original_#{ali}".to_sym
70
- if method_defined? temp
71
- alias_method ali, temp
72
- remove_method temp
73
- end
74
- end
75
- end
76
- end
77
- end
78
-
79
- describe Win::Library, ' defines wrappers for Win32::API functions' do
80
-
81
- before(:each) { hide_method *redefined_methods } # hide original methods if defined
82
- after(:each) { restore_method *redefined_methods } # restore original methods if hidden
83
- context '::function' do
84
- context 'defining enhanced API function method' do
85
- spec{ use{ MyLib.function(:FindWindow, 'PP', 'l', rename: nil, aliases: nil, boolean: nil, zeronil: nil, &any_block) }}
86
-
87
- it 'defines new instance methods with appropriate names' do
88
- MyLib.function :FindWindow, 'PP', 'L'
89
- respond_to?(:FindWindow).should be_true
90
- respond_to?(:find_window).should be_true
91
- end
92
-
93
- it 'constructs argument prototype from uppercase string, enforces the args count' do
94
- expect { MyLib.function :FindWindow, 'PP', 'L' }.to_not raise_error
95
- should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
96
- end
97
-
98
- it 'constructs argument prototype from (mixed) array, enforces the args count' do
99
- expect { MyLib.function :FindWindow, [:pointer, 'P'], 'L' }.to_not raise_error
100
- should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
101
- end
102
-
103
- it 'with :rename option, overrides snake_case name for defined method but leaves CamelCase intact' do
104
- MyLib.function :FindWindow, 'PP', 'L', :rename=> 'my_own_find'
105
- expect {find_window(nil, nil)}.to raise_error NoMethodError
106
- expect {FindWindow(nil, nil)}.to_not raise_error
107
- expect {my_own_find(nil, nil)}.to_not raise_error
108
- end
109
-
110
- it 'defined snake_case method returns expected value when called' do
111
- MyLib.function :FindWindow, 'PP', 'L'
112
- find_window(nil, nil).should_not == 0
113
- find_window(nil, TEST_IMPOSSIBLE).should == 0
114
- find_window(TEST_IMPOSSIBLE, nil).should == 0
115
- find_window(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE).should == 0
116
- end
117
-
118
- it 'defined CamelCase method returns expected value when called' do
119
- MyLib.function :FindWindow, 'PP', 'L'
120
- FindWindow(nil, nil).should_not == 0
121
- FindWindow(nil, TEST_IMPOSSIBLE).should == 0
122
- FindWindow(TEST_IMPOSSIBLE, nil).should == 0
123
- FindWindow(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE).should == 0
124
- end
125
-
126
- # it 'returns underlying Win32::API object if defined method is called with (:api) argument ' do
127
- # MyLib.function :FindWindow, 'PP', 'L'
128
- # expect {find_window(:api)}.to_not raise_error
129
- # should_be :find_window, find_window(:api)
130
- # end
131
-
132
- it 'returns underlying Win32::API object' do
133
- FWAPI = MyLib.function :FindWindow, 'PP', 'L'
134
- should_be :find_window, FWAPI
135
- end
136
- end
137
-
138
- context 'defining aliases' do
139
- it 'adds alias for defined method with :alias option' do
140
- MyLib.function( :FindWindow, 'PP', 'L', :alias => 'my_own_find')
141
- expect {find_window(nil, nil)}.to_not raise_error
142
- expect {my_own_find(nil, nil)}.to_not raise_error
143
- end
144
-
145
- it 'adds aliases for defined method with :aliases option' do
146
- MyLib.function :FindWindow, 'PP', 'L', :aliases => ['my_own_find', 'my_own_find1']
147
- expect {find_window(nil, nil)}.to_not raise_error
148
- expect {my_own_find(nil, nil)}.to_not raise_error
149
- expect {my_own_find1(nil, nil)}.to_not raise_error
150
- end
151
-
152
- it 'adds Rubyesque alias to IsXxx API test function' do
153
- MyLib.function 'IsWindow', 'L', 'B'
154
- respond_to?(:window?).should be_true
155
- respond_to?(:is_window).should be_true
156
- end
157
-
158
- it 'adds Rubyesque alias to GetXxx API getter function' do
159
- MyLib.function 'GetComputerName', 'PP', 'I', :dll=> 'kernel32'
160
- respond_to?(:get_computer_name).should be_true
161
- respond_to?(:computer_name).should be_true
162
- end
163
- end
164
-
165
- context 'defining API with :boolean option converts result to boolean' do
166
- before(:each) { MyLib.function :FindWindow, 'PP', 'L', :boolean => true }
167
-
168
- it 'defines new instance method' do
169
- respond_to?(:find_window).should be_true
170
- respond_to?(:FindWindow).should be_true
171
- end
172
-
173
- it 'defined snake_case method returns false/true instead of zero/non-zero' do
174
- find_window(nil, nil).should == true
175
- find_window(nil, TEST_IMPOSSIBLE).should == false
176
- end
177
-
178
- it 'defined CamelCase method still returns zero/non-zero' do
179
- FindWindow(nil, nil).should_not == true
180
- FindWindow(nil, nil).should_not == 0
181
- FindWindow(nil, TEST_IMPOSSIBLE).should == 0
182
- end
183
-
184
- it 'defined methods enforce the argument count' do
185
- should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
186
- end
187
- end
188
-
189
- context 'defining API with :zeronil option converts zero result to nil' do
190
- before(:each) {MyLib.function :FindWindow, 'PP', 'L', :zeronil => true}
191
-
192
- it 'defines new instance method' do
193
- respond_to?(:find_window).should be_true
194
- respond_to?(:FindWindow).should be_true
195
- end
196
-
197
- it 'defined CamelCase method still returns zero/non-zero' do
198
- FindWindow(nil, nil).should_not == true
199
- FindWindow(nil, nil).should_not == 0
200
- FindWindow(nil, TEST_IMPOSSIBLE).should == 0
201
- end
202
-
203
- it 'defined method returns nil (but NOT false) instead of zero' do
204
- find_window(nil, TEST_IMPOSSIBLE).should_not == false
205
- find_window(nil, TEST_IMPOSSIBLE).should == nil
206
- end
207
-
208
- it 'defined method does not return true when result is non-zero' do
209
- find_window(nil, nil).should_not == true
210
- find_window(nil, nil).should_not == 0
211
- end
212
-
213
- it 'defined methods enforce the argument count' do
214
- should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
215
- end
216
- end
217
-
218
- context 'using DLL other than default user32 with :dll option' do
219
- before(:each) {MyLib.function 'GetComputerName', 'PP', 'I', :dll=> 'kernel32'}
220
-
221
- it 'defines new instance method with appropriate name' do
222
- respond_to?(:GetComputerName).should be_true
223
- respond_to?(:get_computer_name).should be_true
224
- respond_to?(:computer_name).should be_true
225
- end
226
-
227
- it 'returns expected result' do
228
- MyLib.function 'GetComputerName', ['P', 'P'], 'I', :dll=> 'kernel32'
229
- hostname = `hostname`.strip.upcase
230
- name = " " * 128
231
- get_computer_name(name, "128")
232
- name.unpack("A*").first.should == hostname
233
- end
234
- end
235
-
236
- context 'trying to define an invalid API function' do
237
- it 'raises error when trying to define function with a wrong function name' do
238
- expect { MyLib.function 'FindWindowImpossible', 'PP', 'L' }.
239
- to raise_error( /Function 'FindWindowImpossible' not found/ )
240
- end
241
- end
242
-
243
- context 'defining API function using definition block' do
244
- it 'defines new instance method' do
245
- MyLib.function( :FindWindow, 'PP', 'L' ){|api, *args|}
246
- respond_to?(:find_window).should be_true
247
- respond_to?(:FindWindow).should be_true
248
- end
249
-
250
- it 'does not enforce argument count outside of block' do
251
- MyLib.function( :FindWindow, 'PP', 'L' ){|api, *args|}
252
- expect { find_window }.to_not raise_error
253
- expect { find_window(nil) }.to_not raise_error
254
- expect { find_window(nil, 'Str', 1) }.to_not raise_error
255
- end
256
-
257
- it 'returns block return value when defined method is called' do
258
- MyLib.function( :FindWindow, 'PP', 'L' ){|api, *args| 'Value'}
259
- find_window(nil).should == 'Value'
260
- end
261
-
262
- it 'passes arguments and underlying Win32::API object to the block' do
263
- MyLib.function( :FindWindow, 'PP', 'L' ) do |api, *args|
264
- @api = api
265
- @args = args
266
- end
267
- expect {find_window(1, 2, 3) }.to_not raise_error
268
- @args.should == [1, 2, 3]
269
- should_be :find_window, @api
270
- end
271
-
272
- it ':rename option overrides standard name for defined method' do
273
- MyLib.function( :FindWindow, 'PP', 'L', :rename => 'my_own_find' ){|api, *args|}
274
- expect {find_window(nil, nil, nil)}.to raise_error
275
- expect {my_own_find(nil, nil)}.to_not raise_error
276
- end
277
-
278
- it 'adds alias for defined method with :alias option' do
279
- MyLib.function( :FindWindow, 'PP', 'L', :alias => 'my_own_find' ){|api, *args|}
280
- expect {find_window(nil, nil)}.to_not raise_error
281
- expect {my_own_find(nil, nil)}.to_not raise_error
282
- end
283
-
284
- it 'adds aliases for defined method with :aliases option' do
285
- MyLib.function( :FindWindow, 'PP', 'L', :aliases => ['my_own_find', 'my_own_find1'] ) {|api, *args|}
286
- expect {find_window(nil, nil)}.to_not raise_error
287
- expect {my_own_find(nil, nil)}.to_not raise_error
288
- expect {my_own_find1(nil, nil)}.to_not raise_error
289
- end
290
- end
291
-
292
- context 'calling defined methods with attached block to preprocess the API function results' do
293
- it 'defined method yields raw result to block attached to its invocation' do
294
- MyLib.function :FindWindow, 'PP', 'L', zeronil: true
295
- find_window(nil, TEST_IMPOSSIBLE) {|result| result.should == 0 }
296
- end
297
-
298
- it 'defined method returns result of block attached to its invocation' do
299
- MyLib.function :FindWindow, 'PP', 'L', zeronil: true
300
- return_value = find_window(nil, TEST_IMPOSSIBLE) {|result| 'Value'}
301
- return_value.should == 'Value'
302
- end
303
-
304
- it 'defined method transforms result of block before returning it' do
305
- MyLib.function :FindWindow, 'PP', 'L', zeronil: true
306
- return_value = find_window(nil, TEST_IMPOSSIBLE) {|result| 0 }
307
- return_value.should_not == 0
308
- return_value.should == nil
309
- end
310
- end
311
-
312
- context 'defining API function without arguments - f(VOID)' do
313
- it 'should enforce argument count to 0, NOT 1' do
314
- MyLib.function :GetForegroundWindow, [], 'L', zeronil: true
315
- should_count_args :GetForegroundWindow, :get_foreground_window, :foreground_window, [], [nil, 0, 123]
316
- end
317
- end
318
- end
319
-
320
- context '::callback defining API callback TYPES' do
321
- it '#callback macro creates a valid callback definition' do
322
- expect { MyLib.callback :MyEnumWindowsProc, [:HWND, :long], :bool}.to_not raise_error
323
- end
324
-
325
- it 'created callback definition can be used to define API function expecting callback' do
326
- expect {MyLib.function :EnumWindows, [:MyEnumWindowsProc, :long], :long}.to_not raise_error
327
- expect { enum_windows(lambda{|handle, message| true }, 0) }.to_not raise_error
328
- end
329
- end
330
-
331
- context '::try_function to define API function that are platform-specific' do
332
- if xp?
333
- it 'should silently fail to define function not present on current platform' do
334
- expect {MyLib.function :GetErrorMode, [], :UINT}.to raise_error /Function 'GetErrorMode' not found/
335
- expect {MyLib.try_function :GetErrorMode, [], :UINT}.to_not raise_error
336
- expect { GetErrorMode() }.to raise_error /undefined method `GetErrorMode'/
337
- expect { get_error_mode() }.to raise_error /undefined method `get_error_mode'/
338
- end
339
- end
340
- end
341
- end
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'win/library'
3
+
4
+ module WinLibraryTest
5
+
6
+ include WinTest
7
+
8
+ module MyLib # namespace for defined functions
9
+ include Win::Library
10
+ end
11
+ include MyLib
12
+
13
+ def should_be symbol, api
14
+ case symbol
15
+ when :find_window
16
+ #api.dll_name.should == 'user32' # The name of the DLL that exports the API function
17
+ api.effective_function_name.should == 'FindWindowA' # Actual function returned by the constructor: 'GetUserName' ->'GetUserNameA' or 'GetUserNameW'
18
+ api.function_name.should == :FindWindow # The name of the function passed to the constructor
19
+ api.prototype.should == [:pointer, :pointer] # The prototype, returned as an array of characters
20
+ api.return_type.should == :ulong # The prototype, returned as an array of characters
21
+ end
22
+ end
23
+
24
+ def should_count_args(*methods, rights, wrongs)
25
+ rights = [rights].flatten
26
+ wrongs = [wrongs].flatten
27
+ methods.each do |method|
28
+ (0..8).each do |n|
29
+ if n == rights.size
30
+ expect {send method, *rights}.to_not raise_error
31
+ else
32
+ args = (1..n).map {wrongs[rand(wrongs.size)]}
33
+ expect {send method, *args}.
34
+ to raise_error "wrong number of arguments (#{args.size} for #{rights.size})"
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def any_handle
41
+ MyLib.function :FindWindow, 'PP', 'L' unless respond_to? :find_window
42
+ find_window(nil, nil)
43
+ end
44
+
45
+ def redefined_methods
46
+ [:FindWindow, :IsWindow, :EnumWindows, :GetComputerName, :GetForegroundWindow]
47
+ end
48
+
49
+ def hide_method(*names) # hide original method(s) if it is defined
50
+ names.map(&:to_s).each do |name|
51
+ MyLib.module_eval do
52
+ # + remove_const
53
+ aliases = generate_names(name).flatten + [name]
54
+ aliases.map(&:to_s).each do |ali|
55
+ if method_defined? ali
56
+ alias_method "original_#{ali}".to_sym, ali
57
+ remove_method ali
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ def restore_method(*names) # restore original method if it was hidden
65
+ names.map(&:to_s).each do |name|
66
+ MyLib.module_eval do
67
+ aliases = generate_names(name).flatten + [name]
68
+ aliases.map(&:to_s).each do |ali|
69
+ temp = "original_#{ali}".to_sym
70
+ if method_defined? temp
71
+ alias_method ali, temp
72
+ remove_method temp
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ describe Win::Library, ' defines wrappers for Win32::API functions' do
80
+
81
+ before(:each) { hide_method *redefined_methods } # hide original methods if defined
82
+ after(:each) { restore_method *redefined_methods } # restore original methods if hidden
83
+ context '::function' do
84
+ context 'defining enhanced API function method' do
85
+ spec{ use{ MyLib.function(:FindWindow, 'PP', 'l', rename: nil, aliases: nil, boolean: nil, zeronil: nil, &any_block) }}
86
+
87
+ it 'defines new instance methods with appropriate names' do
88
+ MyLib.function :FindWindow, 'PP', 'L'
89
+ respond_to?(:FindWindow).should be_true
90
+ respond_to?(:find_window).should be_true
91
+ end
92
+
93
+ it 'constructs argument prototype from uppercase string, enforces the args count' do
94
+ expect { MyLib.function :FindWindow, 'PP', 'L' }.to_not raise_error
95
+ should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
96
+ end
97
+
98
+ it 'constructs argument prototype from (mixed) array, enforces the args count' do
99
+ expect { MyLib.function :FindWindow, [:pointer, 'P'], 'L' }.to_not raise_error
100
+ should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
101
+ end
102
+
103
+ it 'with :rename option, overrides snake_case name for defined method but leaves CamelCase intact' do
104
+ MyLib.function :FindWindow, 'PP', 'L', :rename=> 'my_own_find'
105
+ expect {find_window(nil, nil)}.to raise_error NoMethodError
106
+ expect {FindWindow(nil, nil)}.to_not raise_error
107
+ expect {my_own_find(nil, nil)}.to_not raise_error
108
+ end
109
+
110
+ it 'defined snake_case method returns expected value when called' do
111
+ MyLib.function :FindWindow, 'PP', 'L'
112
+ find_window(nil, nil).should_not == 0
113
+ find_window(nil, TEST_IMPOSSIBLE).should == 0
114
+ find_window(TEST_IMPOSSIBLE, nil).should == 0
115
+ find_window(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE).should == 0
116
+ end
117
+
118
+ it 'defined CamelCase method returns expected value when called' do
119
+ MyLib.function :FindWindow, 'PP', 'L'
120
+ FindWindow(nil, nil).should_not == 0
121
+ FindWindow(nil, TEST_IMPOSSIBLE).should == 0
122
+ FindWindow(TEST_IMPOSSIBLE, nil).should == 0
123
+ FindWindow(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE).should == 0
124
+ end
125
+
126
+ # it 'returns underlying Win32::API object if defined method is called with (:api) argument ' do
127
+ # MyLib.function :FindWindow, 'PP', 'L'
128
+ # expect {find_window(:api)}.to_not raise_error
129
+ # should_be :find_window, find_window(:api)
130
+ # end
131
+
132
+ it 'returns underlying Win32::API object' do
133
+ FWAPI = MyLib.function :FindWindow, 'PP', 'L'
134
+ should_be :find_window, FWAPI
135
+ end
136
+ end
137
+
138
+ context 'defining aliases' do
139
+ it 'adds alias for defined method with :alias option' do
140
+ MyLib.function( :FindWindow, 'PP', 'L', :alias => 'my_own_find')
141
+ expect {find_window(nil, nil)}.to_not raise_error
142
+ expect {my_own_find(nil, nil)}.to_not raise_error
143
+ end
144
+
145
+ it 'adds aliases for defined method with :aliases option' do
146
+ MyLib.function :FindWindow, 'PP', 'L', :aliases => ['my_own_find', 'my_own_find1']
147
+ expect {find_window(nil, nil)}.to_not raise_error
148
+ expect {my_own_find(nil, nil)}.to_not raise_error
149
+ expect {my_own_find1(nil, nil)}.to_not raise_error
150
+ end
151
+
152
+ it 'adds Rubyesque alias to IsXxx API test function' do
153
+ MyLib.function 'IsWindow', 'L', 'B'
154
+ respond_to?(:window?).should be_true
155
+ respond_to?(:is_window).should be_true
156
+ end
157
+
158
+ it 'adds Rubyesque alias to GetXxx API getter function' do
159
+ MyLib.function 'GetComputerName', 'PP', 'I', :dll=> 'kernel32'
160
+ respond_to?(:get_computer_name).should be_true
161
+ respond_to?(:computer_name).should be_true
162
+ end
163
+ end
164
+
165
+ context 'defining API with :boolean option converts result to boolean' do
166
+ before(:each) { MyLib.function :FindWindow, 'PP', 'L', :boolean => true }
167
+
168
+ it 'defines new instance method' do
169
+ respond_to?(:find_window).should be_true
170
+ respond_to?(:FindWindow).should be_true
171
+ end
172
+
173
+ it 'defined snake_case method returns false/true instead of zero/non-zero' do
174
+ find_window(nil, nil).should == true
175
+ find_window(nil, TEST_IMPOSSIBLE).should == false
176
+ end
177
+
178
+ it 'defined CamelCase method still returns zero/non-zero' do
179
+ FindWindow(nil, nil).should_not == true
180
+ FindWindow(nil, nil).should_not == 0
181
+ FindWindow(nil, TEST_IMPOSSIBLE).should == 0
182
+ end
183
+
184
+ it 'defined methods enforce the argument count' do
185
+ should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
186
+ end
187
+ end
188
+
189
+ context 'defining API with :zeronil option converts zero result to nil' do
190
+ before(:each) {MyLib.function :FindWindow, 'PP', 'L', :zeronil => true}
191
+
192
+ it 'defines new instance method' do
193
+ respond_to?(:find_window).should be_true
194
+ respond_to?(:FindWindow).should be_true
195
+ end
196
+
197
+ it 'defined CamelCase method still returns zero/non-zero' do
198
+ FindWindow(nil, nil).should_not == true
199
+ FindWindow(nil, nil).should_not == 0
200
+ FindWindow(nil, TEST_IMPOSSIBLE).should == 0
201
+ end
202
+
203
+ it 'defined method returns nil (but NOT false) instead of zero' do
204
+ find_window(nil, TEST_IMPOSSIBLE).should_not == false
205
+ find_window(nil, TEST_IMPOSSIBLE).should == nil
206
+ end
207
+
208
+ it 'defined method does not return true when result is non-zero' do
209
+ find_window(nil, nil).should_not == true
210
+ find_window(nil, nil).should_not == 0
211
+ end
212
+
213
+ it 'defined methods enforce the argument count' do
214
+ should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
215
+ end
216
+ end
217
+
218
+ context 'using DLL other than default user32 with :dll option' do
219
+ before(:each) {MyLib.function 'GetComputerName', 'PP', 'I', :dll=> 'kernel32'}
220
+
221
+ it 'defines new instance method with appropriate name' do
222
+ respond_to?(:GetComputerName).should be_true
223
+ respond_to?(:get_computer_name).should be_true
224
+ respond_to?(:computer_name).should be_true
225
+ end
226
+
227
+ it 'returns expected result' do
228
+ MyLib.function 'GetComputerName', ['P', 'P'], 'I', :dll=> 'kernel32'
229
+ hostname = `hostname`.strip.upcase
230
+ name = " " * 128
231
+ get_computer_name(name, "128")
232
+ name.unpack("A*").first.should == hostname
233
+ end
234
+ end
235
+
236
+ context 'trying to define an invalid API function' do
237
+ it 'raises error when trying to define function with a wrong function name' do
238
+ expect { MyLib.function 'FindWindowImpossible', 'PP', 'L' }.
239
+ to raise_error( /Function 'FindWindowImpossible' not found/ )
240
+ end
241
+ end
242
+
243
+ context 'defining API function using definition block' do
244
+ it 'defines new instance method' do
245
+ MyLib.function( :FindWindow, 'PP', 'L' ){|api, *args|}
246
+ respond_to?(:find_window).should be_true
247
+ respond_to?(:FindWindow).should be_true
248
+ end
249
+
250
+ it 'does not enforce argument count outside of block' do
251
+ MyLib.function( :FindWindow, 'PP', 'L' ){|api, *args|}
252
+ expect { find_window }.to_not raise_error
253
+ expect { find_window(nil) }.to_not raise_error
254
+ expect { find_window(nil, 'Str', 1) }.to_not raise_error
255
+ end
256
+
257
+ it 'returns block return value when defined method is called' do
258
+ MyLib.function( :FindWindow, 'PP', 'L' ){|api, *args| 'Value'}
259
+ find_window(nil).should == 'Value'
260
+ end
261
+
262
+ it 'passes arguments and underlying Win32::API object to the block' do
263
+ MyLib.function( :FindWindow, 'PP', 'L' ) do |api, *args|
264
+ @api = api
265
+ @args = args
266
+ end
267
+ expect {find_window(1, 2, 3) }.to_not raise_error
268
+ @args.should == [1, 2, 3]
269
+ should_be :find_window, @api
270
+ end
271
+
272
+ it ':rename option overrides standard name for defined method' do
273
+ MyLib.function( :FindWindow, 'PP', 'L', :rename => 'my_own_find' ){|api, *args|}
274
+ expect {find_window(nil, nil, nil)}.to raise_error
275
+ expect {my_own_find(nil, nil)}.to_not raise_error
276
+ end
277
+
278
+ it 'adds alias for defined method with :alias option' do
279
+ MyLib.function( :FindWindow, 'PP', 'L', :alias => 'my_own_find' ){|api, *args|}
280
+ expect {find_window(nil, nil)}.to_not raise_error
281
+ expect {my_own_find(nil, nil)}.to_not raise_error
282
+ end
283
+
284
+ it 'adds aliases for defined method with :aliases option' do
285
+ MyLib.function( :FindWindow, 'PP', 'L', :aliases => ['my_own_find', 'my_own_find1'] ) {|api, *args|}
286
+ expect {find_window(nil, nil)}.to_not raise_error
287
+ expect {my_own_find(nil, nil)}.to_not raise_error
288
+ expect {my_own_find1(nil, nil)}.to_not raise_error
289
+ end
290
+ end
291
+
292
+ context 'calling defined methods with attached block to preprocess the API function results' do
293
+ it 'defined method yields raw result to block attached to its invocation' do
294
+ MyLib.function :FindWindow, 'PP', 'L', zeronil: true
295
+ find_window(nil, TEST_IMPOSSIBLE) {|result| result.should == 0 }
296
+ end
297
+
298
+ it 'defined method returns result of block attached to its invocation' do
299
+ MyLib.function :FindWindow, 'PP', 'L', zeronil: true
300
+ return_value = find_window(nil, TEST_IMPOSSIBLE) {|result| 'Value'}
301
+ return_value.should == 'Value'
302
+ end
303
+
304
+ it 'defined method transforms result of block before returning it' do
305
+ MyLib.function :FindWindow, 'PP', 'L', zeronil: true
306
+ return_value = find_window(nil, TEST_IMPOSSIBLE) {|result| 0 }
307
+ return_value.should_not == 0
308
+ return_value.should == nil
309
+ end
310
+ end
311
+
312
+ context 'defining API function without arguments - f(VOID)' do
313
+ it 'should enforce argument count to 0, NOT 1' do
314
+ MyLib.function :GetForegroundWindow, [], 'L', zeronil: true
315
+ should_count_args :GetForegroundWindow, :get_foreground_window, :foreground_window, [], [nil, 0, 123]
316
+ end
317
+ end
318
+ end
319
+
320
+ context '::callback defining API callback TYPES' do
321
+ it '#callback macro creates a valid callback definition' do
322
+ expect { MyLib.callback :MyEnumWindowsProc, [:HWND, :long], :bool}.to_not raise_error
323
+ end
324
+
325
+ it 'created callback definition can be used to define API function expecting callback' do
326
+ expect {MyLib.function :EnumWindows, [:MyEnumWindowsProc, :long], :long}.to_not raise_error
327
+ expect { enum_windows(lambda{|handle, message| true }, 0) }.to_not raise_error
328
+ end
329
+ end
330
+
331
+ context '::try_function to define API function that are platform-specific' do
332
+ if xp?
333
+ it 'should silently fail to define function not present on current platform' do
334
+ expect {MyLib.function :GetErrorMode, [], :UINT}.to raise_error /Function 'GetErrorMode' not found/
335
+ expect {MyLib.try_function :GetErrorMode, [], :UINT}.to_not raise_error
336
+ expect { GetErrorMode() }.to raise_error /undefined method `GetErrorMode'/
337
+ expect { get_error_mode() }.to raise_error /undefined method `get_error_mode'/
338
+ end
339
+ end
340
+ end
341
+ end
342
342
  end