win 0.3.24 → 0.3.25
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +4 -0
- data/README.rdoc +4 -5
- data/VERSION +1 -1
- data/lib/win.rb +1 -1
- data/lib/win/gui/menu.rb +34 -3
- data/lib/win/gui/message.rb +1 -3
- data/lib/win/gui/window.rb +1 -1
- data/lib/win/library.rb +10 -5
- data/lib/win/national.rb +585 -0
- data/lib/win/time.rb +140 -0
- data/spec/extension_spec.rb +2 -38
- data/spec/spec_helper.rb +60 -71
- data/spec/win/dde_spec.rb +435 -437
- data/spec/win/error_spec.rb +86 -88
- data/spec/win/gui/dialog_spec.rb +43 -46
- data/spec/win/gui/input_spec.rb +81 -85
- data/spec/win/gui/menu_spec.rb +260 -247
- data/spec/win/gui/message_spec.rb +218 -219
- data/spec/win/gui/window_spec.rb +558 -557
- data/spec/win/library_spec.rb +180 -199
- data/spec/win/system/info_spec.rb +42 -45
- data/spec/win/system/version_spec.rb +143 -146
- data/spec/win/time_spec.rb +48 -0
- data/tasks/spec.rake +5 -9
- metadata +16 -36
data/spec/win/library_spec.rb
CHANGED
@@ -1,290 +1,259 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
require 'win/library'
|
3
3
|
require 'win/gui/message'
|
4
4
|
|
5
|
-
module
|
5
|
+
module LibraryTest
|
6
|
+
# include my_lib
|
7
|
+
# include WinTest
|
6
8
|
|
7
|
-
include WinTest
|
8
|
-
|
9
|
-
module MyLib # namespace for defined functions
|
10
|
-
extend Win::Library
|
11
|
-
end
|
12
|
-
include MyLib
|
13
|
-
|
14
|
-
def should_be symbol, api
|
15
|
-
case symbol
|
16
|
-
when :find_window
|
17
|
-
api.dll.should include "user32" # The name of the DLL that exports the API function
|
18
|
-
api.effective_function_name.should == :FindWindowA # Actual function: 'GetUserName' ->'GetUserNameA' or 'GetUserNameW'
|
19
|
-
api.function_name.should == :FindWindow # The name of the function passed to the constructor
|
20
|
-
api.prototype.should == [:pointer, :pointer] # The prototype, returned as an array of characters
|
21
|
-
api.return_type.should == :ulong # The prototype, returned as an array of characters
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def should_count_args(*methods, rights, wrongs)
|
26
|
-
rights = [rights].flatten
|
27
|
-
wrongs = [wrongs].flatten
|
28
|
-
methods.each do |method|
|
29
|
-
(0..8).each do |n|
|
30
|
-
if n == rights.size
|
31
|
-
expect {send method, *rights}.to_not raise_error
|
32
|
-
else
|
33
|
-
args = (1..n).map {wrongs[rand(wrongs.size)]}
|
34
|
-
expect {send method, *args}.
|
35
|
-
to raise_error "wrong number of arguments (#{args.size} for #{rights.size})"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def any_handle
|
42
|
-
MyLib.function :FindWindow, 'PP', 'L' unless respond_to? :find_window
|
43
|
-
find_window(nil, nil)
|
44
|
-
end
|
45
|
-
|
46
|
-
def redefined_methods
|
47
|
-
[:FindWindow, :IsWindow, :EnumWindows, :GetUserName, :GetForegroundWindow, :keybd_event, :SendMessage]
|
48
|
-
end
|
49
|
-
|
50
|
-
def hide_method(*names) # hide original method(s) if it is defined
|
51
|
-
names.map(&:to_s).each do |name|
|
52
|
-
MyLib.module_eval do
|
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
9
|
|
79
10
|
shared_examples_for 'defining macro with options' do
|
11
|
+
|
80
12
|
context 'basic behavior' do
|
81
13
|
it 'defines new instance methods with appropriate names' do
|
82
|
-
|
83
|
-
|
84
|
-
respond_to?(:
|
85
|
-
MyLib.respond_to?(:find_window).should be_true
|
86
|
-
respond_to?(:find_window).should be_true
|
14
|
+
@my_lib.function :FindWindow, 'PP', 'L', &@def_block
|
15
|
+
@my_lib.respond_to?(:FindWindow).should be_true
|
16
|
+
@my_lib.respond_to?(:find_window).should be_true
|
87
17
|
end
|
88
18
|
|
89
19
|
it 'returns underlying Win32::API object' do
|
90
|
-
FWAPI =
|
20
|
+
FWAPI = @my_lib.function :FindWindow, 'PP', 'L', &@def_block
|
91
21
|
should_be :find_window, FWAPI
|
92
22
|
end
|
93
23
|
end
|
94
24
|
|
95
25
|
context 'renaming and aliasing' do
|
96
26
|
it ':camel_name option overrides default CamelCase name for attached function but leaves snake_case intact' do
|
97
|
-
|
98
|
-
expect {find_window(nil, nil)}.to_not raise_error
|
99
|
-
expect {FindWindow(nil, nil)}.to raise_error NoMethodError
|
100
|
-
expect {MyOwnName(nil, nil)}.to_not raise_error
|
27
|
+
@my_lib.function :FindWindow, 'PP', 'L', camel_name: 'MyOwnName', &@def_block
|
28
|
+
expect { @my_lib.find_window(nil, nil) }.to_not raise_error
|
29
|
+
expect { @my_lib.FindWindow(nil, nil) }.to raise_error NoMethodError
|
30
|
+
expect { @my_lib.MyOwnName(nil, nil) }.to_not raise_error
|
101
31
|
end
|
102
32
|
|
103
33
|
it ':snake_name option overrides default snake_case name for defined method but leaves CamelCase intact' do
|
104
|
-
|
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
|
34
|
+
@my_lib.function :FindWindow, 'PP', 'L', snake_name: 'my_own_find', &@def_block
|
35
|
+
expect { @my_lib.find_window(nil, nil) }.to raise_error NoMethodError
|
36
|
+
expect { @my_lib.FindWindow(nil, nil) }.to_not raise_error
|
37
|
+
expect { @my_lib.my_own_find(nil, nil) }.to_not raise_error
|
108
38
|
end
|
109
39
|
|
110
40
|
it 'both :snake_name and :camel_name option can be used in one declaration' do
|
111
|
-
|
112
|
-
expect {find_window(nil, nil)}.to raise_error NoMethodError
|
113
|
-
expect {my_own_find(nil, nil)}.to_not raise_error
|
114
|
-
expect {FindWindow(nil, nil)}.to raise_error NoMethodError
|
115
|
-
expect {MyOwnName(nil, nil)}.to_not raise_error
|
41
|
+
@my_lib.function :FindWindow, 'PP', 'L', camel_name: 'MyOwnName', snake_name: 'my_own_find', &@def_block
|
42
|
+
expect { @my_lib.find_window(nil, nil) }.to raise_error NoMethodError
|
43
|
+
expect { @my_lib.my_own_find(nil, nil) }.to_not raise_error
|
44
|
+
expect { @my_lib.FindWindow(nil, nil) }.to raise_error NoMethodError
|
45
|
+
expect { @my_lib.MyOwnName(nil, nil) }.to_not raise_error
|
116
46
|
end
|
117
47
|
|
118
48
|
it ':camel_only option means no snake_case method will be defined' do
|
119
|
-
|
120
|
-
expect {find_window(nil, nil)}.to raise_error NoMethodError
|
121
|
-
expect {FindWindow(nil, nil)}.to_not raise_error
|
49
|
+
@my_lib.function :FindWindow, 'PP', 'L', camel_only: true, &@def_block
|
50
|
+
expect { @my_lib.find_window(nil, nil) }.to raise_error NoMethodError
|
51
|
+
expect { @my_lib.FindWindow(nil, nil) }.to_not raise_error
|
122
52
|
end
|
123
53
|
|
124
54
|
it 'automatically adds Rubyesque alias to IsXxx API test function' do
|
125
|
-
|
126
|
-
respond_to?(:window?).should be_true
|
127
|
-
respond_to?(:is_window).should be_true
|
55
|
+
@my_lib.function 'IsWindow', 'L', 'B', &@def_block
|
56
|
+
@my_lib.respond_to?(:window?).should be_true
|
57
|
+
@my_lib.respond_to?(:is_window).should be_true
|
128
58
|
end
|
129
59
|
|
130
60
|
it 'automatically adds Rubyesque alias to GetXxx API getter function' do
|
131
|
-
|
132
|
-
respond_to?(:get_foreground_window).should be_true
|
133
|
-
respond_to?(:foreground_window).should be_true
|
61
|
+
@my_lib.function 'GetForegroundWindow', [], 'L', &@def_block
|
62
|
+
@my_lib.respond_to?(:get_foreground_window).should be_true
|
63
|
+
@my_lib.respond_to?(:foreground_window).should be_true
|
134
64
|
end
|
135
65
|
|
136
66
|
it ':alias option adds alias for defined snake_case method' do
|
137
|
-
|
138
|
-
expect {find_window(nil, nil)}.to_not raise_error
|
139
|
-
expect {my_own_find(nil, nil)}.to_not raise_error
|
67
|
+
@my_lib.function(:FindWindow, 'PP', 'L', :alias => 'my_own_find', &@def_block)
|
68
|
+
expect { @my_lib.find_window(nil, nil) }.to_not raise_error
|
69
|
+
expect { @my_lib.my_own_find(nil, nil) }.to_not raise_error
|
140
70
|
end
|
141
71
|
|
142
72
|
it ':aliases option adds aliases for defined snake_case method' do
|
143
|
-
|
144
|
-
expect {find_window(nil, nil)}.to_not raise_error
|
145
|
-
expect {my_own_find(nil, nil)}.to_not raise_error
|
146
|
-
expect {my_own_find1(nil, nil)}.to_not raise_error
|
73
|
+
@my_lib.function :FindWindow, 'PP', 'L', :aliases => ['my_own_find', 'my_own_find1'], &@def_block
|
74
|
+
expect { @my_lib.find_window(nil, nil) }.to_not raise_error
|
75
|
+
expect { @my_lib.my_own_find(nil, nil) }.to_not raise_error
|
76
|
+
expect { @my_lib.my_own_find1(nil, nil) }.to_not raise_error
|
147
77
|
end
|
148
78
|
end
|
149
79
|
|
150
80
|
context ':boolean option converts result to boolean' do
|
151
|
-
before(:each) {
|
81
|
+
before(:each) { @my_lib.function :FindWindow, 'PP', 'L', :boolean => true, &@def_block }
|
152
82
|
|
153
|
-
it 'defines new
|
154
|
-
respond_to?(:find_window).should be_true
|
155
|
-
respond_to?(:FindWindow).should be_true
|
83
|
+
it 'defines new method on @my_lib' do
|
84
|
+
@my_lib.respond_to?(:find_window).should be_true
|
85
|
+
@my_lib.respond_to?(:FindWindow).should be_true
|
156
86
|
end
|
157
87
|
|
158
88
|
it 'defined snake_case method returns false/true instead of zero/non-zero' do
|
159
|
-
find_window(nil, nil).should == true
|
160
|
-
find_window(nil, IMPOSSIBLE).should == false
|
89
|
+
@my_lib.find_window(nil, nil).should == true
|
90
|
+
@my_lib.find_window(nil, IMPOSSIBLE).should == false
|
161
91
|
end
|
162
92
|
|
163
93
|
it 'defined CamelCase method still returns zero/non-zero' do
|
164
|
-
FindWindow(nil, nil).should_not == true
|
165
|
-
FindWindow(nil, nil).should_not == 0
|
166
|
-
FindWindow(nil, IMPOSSIBLE).should == 0
|
94
|
+
@my_lib.FindWindow(nil, nil).should_not == true
|
95
|
+
@my_lib.FindWindow(nil, nil).should_not == 0
|
96
|
+
@my_lib.FindWindow(nil, IMPOSSIBLE).should == 0
|
167
97
|
end
|
168
98
|
end
|
169
99
|
|
170
100
|
context 'defining API with :fails option converts zero result to nil' do
|
171
|
-
before(:each) {
|
101
|
+
before(:each) { @my_lib.function :FindWindow, 'PP', 'L', fails: 0, &@def_block }
|
172
102
|
|
173
103
|
it 'defines new instance method' do
|
174
|
-
respond_to?(:find_window).should be_true
|
175
|
-
respond_to?(:FindWindow).should be_true
|
104
|
+
@my_lib.respond_to?(:find_window).should be_true
|
105
|
+
@my_lib.respond_to?(:FindWindow).should be_true
|
176
106
|
end
|
177
107
|
|
178
108
|
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, IMPOSSIBLE).should == 0
|
109
|
+
@my_lib.FindWindow(nil, nil).should_not == true
|
110
|
+
@my_lib.FindWindow(nil, nil).should_not == 0
|
111
|
+
@my_lib.FindWindow(nil, IMPOSSIBLE).should == 0
|
182
112
|
end
|
183
113
|
|
184
114
|
it 'defined method returns nil (but NOT false) instead of zero' do
|
185
|
-
find_window(nil, IMPOSSIBLE).should_not == false
|
186
|
-
find_window(nil, IMPOSSIBLE).should == nil
|
115
|
+
@my_lib.find_window(nil, IMPOSSIBLE).should_not == false
|
116
|
+
@my_lib.find_window(nil, IMPOSSIBLE).should == nil
|
187
117
|
end
|
188
118
|
|
189
119
|
it 'defined method does not return true when result is non-zero' do
|
190
|
-
find_window(nil, nil).should_not == true
|
191
|
-
find_window(nil, nil).should_not == 0
|
120
|
+
@my_lib.find_window(nil, nil).should_not == true
|
121
|
+
@my_lib.find_window(nil, nil).should_not == 0
|
192
122
|
end
|
193
123
|
end
|
194
124
|
|
195
125
|
context 'using DLL other than default user32, kernel32 with :dll option' do
|
196
|
-
before(:each){
|
126
|
+
before(:each) { @my_lib.function 'GetUserName', 'PP', 'I', :dll=> 'advapi32', &@def_block }
|
197
127
|
|
198
128
|
it 'defines new instance method with appropriate name' do
|
199
|
-
respond_to?(:GetUserName).should be_true
|
200
|
-
respond_to?(:get_user_name).should be_true
|
201
|
-
respond_to?(:user_name).should be_true
|
129
|
+
@my_lib.respond_to?(:GetUserName).should be_true
|
130
|
+
@my_lib.respond_to?(:get_user_name).should be_true
|
131
|
+
@my_obj.respond_to?(:user_name).should be_true
|
132
|
+
@my_lib.respond_to?(:user_name).should be_true
|
202
133
|
end
|
203
134
|
|
204
135
|
it 'returns expected result' do
|
205
|
-
username =
|
136
|
+
username = ENV['USERNAME'].strip
|
206
137
|
name_ptr = FFI::MemoryPointer.from_string(" " * 128)
|
207
138
|
size_ptr = FFI::MemoryPointer.new(:long).write_int(name_ptr.size)
|
208
|
-
get_user_name(name_ptr, size_ptr)
|
139
|
+
@my_lib.get_user_name(name_ptr, size_ptr)
|
209
140
|
name_ptr.read_string.strip.should == username
|
210
141
|
end
|
211
142
|
end
|
212
143
|
end
|
213
144
|
|
214
145
|
describe Win::Library, ' defines wrappers for Win32::API functions' do
|
146
|
+
def should_be symbol, api
|
147
|
+
case symbol
|
148
|
+
when :find_window
|
149
|
+
api.dll.should include "user32" # The name of the DLL that exports the API function
|
150
|
+
api.effective_function_name.should == :FindWindowA # Actual function: 'GetUserName' ->'GetUserNameA' or 'GetUserNameW'
|
151
|
+
api.function_name.should == :FindWindow # The name of the function passed to the constructor
|
152
|
+
api.prototype.should == [:pointer, :pointer] # The prototype, returned as an array of characters
|
153
|
+
api.return_type.should == :ulong # The prototype, returned as an array of characters
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def should_count_args(*methods, rights, wrongs)
|
158
|
+
rights = [rights].flatten
|
159
|
+
wrongs = [wrongs].flatten
|
160
|
+
methods.each do |method|
|
161
|
+
(0..8).each do |n|
|
162
|
+
if n == rights.size
|
163
|
+
expect { @my_lib.send method, *rights }.to_not raise_error
|
164
|
+
else
|
165
|
+
args = (1..n).map { wrongs[rand(wrongs.size)] }
|
166
|
+
expect { @my_lib.send method, *args }.
|
167
|
+
to raise_error "wrong number of arguments (#{args.size} for #{rights.size})"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def any_handle
|
174
|
+
@my_lib.function :FindWindow, 'PP', 'L' unless respond_to? :find_window
|
175
|
+
@my_lib.find_window(nil, nil)
|
176
|
+
end
|
177
|
+
|
178
|
+
def recreate_library
|
179
|
+
@my_lib = Module.new
|
180
|
+
@my_lib.extend Win::Library
|
181
|
+
@my_class = Class.new
|
182
|
+
@my_class.send :include, @my_lib
|
183
|
+
@my_obj = @my_class.new
|
184
|
+
end
|
215
185
|
|
216
|
-
before(:each) {
|
217
|
-
after(:each) { restore_method *redefined_methods } # restore original methods if hidden
|
186
|
+
before(:each) { recreate_library }
|
218
187
|
|
219
188
|
describe '::attach_function - delegates to FFI::Library::attach_function' do
|
220
189
|
it 'can be used to attach same function with different signatures' do
|
221
|
-
|
222
|
-
|
223
|
-
respond_to?(:send_one).should be_true
|
224
|
-
respond_to?(:send_two).should be_true
|
225
|
-
|
226
|
-
|
190
|
+
@my_lib.attach_function :send_one, :SendMessageA, [:ulong, :uint, :uint, :long], :int
|
191
|
+
@my_lib.attach_function :send_two, :SendMessageA, [:ulong, :uint, :uint, :pointer], :int
|
192
|
+
@my_lib.respond_to?(:send_one).should be_true
|
193
|
+
@my_lib.respond_to?(:send_two).should be_true
|
194
|
+
@my_obj.respond_to?(:send_one).should be_true
|
195
|
+
@my_obj.respond_to?(:send_two).should be_true
|
227
196
|
end
|
228
197
|
end
|
229
198
|
|
230
199
|
describe '::function - attaches external API function and defines enhanced snake_case method on top of it' do
|
231
|
-
spec{ use{
|
200
|
+
spec { use { @my_lib.function(:FindWindow, 'PP', 'l', aliases: nil, boolean: nil, fails: 0, &any_block) } }
|
232
201
|
|
233
|
-
context 'defining enhanced API function without
|
202
|
+
context 'defining enhanced API function without definition block (using defaults)' do
|
234
203
|
it_should_behave_like 'defining macro with options'
|
235
204
|
|
236
205
|
it 'constructs argument prototype from uppercase string, enforces the args count' do
|
237
|
-
expect {
|
206
|
+
expect { @my_lib.function :FindWindow, 'PP', 'L' }.to_not raise_error
|
238
207
|
should_count_args :find_window, :FindWindow, [nil, nil], [nil, IMPOSSIBLE, 'cmd']
|
239
208
|
end
|
240
209
|
|
241
210
|
it 'constructs argument prototype from (mixed) array, enforces the args count' do
|
242
|
-
expect {
|
211
|
+
expect { @my_lib.function :FindWindow, [:pointer, 'P'], 'L' }.to_not raise_error
|
243
212
|
should_count_args :find_window, :FindWindow, [nil, nil], [nil, IMPOSSIBLE, 'cmd']
|
244
213
|
end
|
245
214
|
|
246
215
|
it 'defined snake_case method returns expected value when called' do
|
247
|
-
|
248
|
-
find_window(nil, nil).should_not == 0
|
249
|
-
find_window(nil, IMPOSSIBLE).should == 0
|
250
|
-
find_window(IMPOSSIBLE, nil).should == 0
|
251
|
-
find_window(IMPOSSIBLE, IMPOSSIBLE).should == 0
|
216
|
+
@my_lib.function :FindWindow, 'PP', 'L'
|
217
|
+
@my_lib.find_window(nil, nil).should_not == 0
|
218
|
+
@my_lib.find_window(nil, IMPOSSIBLE).should == 0
|
219
|
+
@my_lib.find_window(IMPOSSIBLE, nil).should == 0
|
220
|
+
@my_lib.find_window(IMPOSSIBLE, IMPOSSIBLE).should == 0
|
252
221
|
end
|
253
222
|
|
254
223
|
it 'defined CamelCase method returns expected value when called' do
|
255
|
-
|
256
|
-
FindWindow(nil, nil).should_not == 0
|
257
|
-
FindWindow(nil, IMPOSSIBLE).should == 0
|
258
|
-
FindWindow(IMPOSSIBLE, nil).should == 0
|
259
|
-
FindWindow(IMPOSSIBLE, IMPOSSIBLE).should == 0
|
224
|
+
@my_lib.function :FindWindow, 'PP', 'L'
|
225
|
+
@my_lib.FindWindow(nil, nil).should_not == 0
|
226
|
+
@my_lib.FindWindow(nil, IMPOSSIBLE).should == 0
|
227
|
+
@my_lib.FindWindow(IMPOSSIBLE, nil).should == 0
|
228
|
+
@my_lib.FindWindow(IMPOSSIBLE, IMPOSSIBLE).should == 0
|
260
229
|
end
|
261
230
|
end
|
262
231
|
|
263
232
|
context 'defining API function using explicit definition block' do
|
264
233
|
before(:each) do
|
265
|
-
@def_block = lambda{|api, *args| api.call(*args)}
|
234
|
+
@def_block = lambda { |api, *args| api.call(*args) } # Trivial define_block for shared examples
|
266
235
|
end
|
267
236
|
|
268
237
|
it_should_behave_like 'defining macro with options'
|
269
238
|
|
270
239
|
it 'does not enforce argument count outside of block' do
|
271
|
-
|
272
|
-
expect { find_window }.to_not raise_error
|
273
|
-
expect { find_window(nil) }.to_not raise_error
|
274
|
-
expect { find_window(nil, 'Str', 1) }.to_not raise_error
|
240
|
+
@my_lib.function(:FindWindow, 'PP', 'L') { |api, *args|}
|
241
|
+
expect { @my_lib.find_window }.to_not raise_error
|
242
|
+
expect { @my_lib.find_window(nil) }.to_not raise_error
|
243
|
+
expect { @my_lib.find_window(nil, 'Str', 1) }.to_not raise_error
|
275
244
|
end
|
276
245
|
|
277
246
|
it 'returns block return value when defined method is called' do
|
278
|
-
|
279
|
-
find_window(nil).should == 'Value'
|
247
|
+
@my_lib.function(:FindWindow, 'PP', 'L') { |api, *args| 'Value' }
|
248
|
+
@my_lib.find_window(nil).should == 'Value'
|
280
249
|
end
|
281
250
|
|
282
251
|
it 'passes arguments and underlying Win32::API object to the block' do
|
283
|
-
|
284
|
-
@api
|
252
|
+
@my_lib.function(:FindWindow, 'PP', 'L') do |api, *args|
|
253
|
+
@api = api
|
285
254
|
@args = args
|
286
255
|
end
|
287
|
-
expect {find_window(1, 2, 3) }.to_not raise_error
|
256
|
+
expect { @my_lib.find_window(1, 2, 3) }.to_not raise_error
|
288
257
|
@args.should == [1, 2, 3]
|
289
258
|
should_be :find_window, @api
|
290
259
|
end
|
@@ -293,49 +262,53 @@ module WinLibraryTest
|
|
293
262
|
context 'defining API function with alternative signature' do
|
294
263
|
before(:each) do
|
295
264
|
@def_block = nil
|
296
|
-
|
297
|
-
alternative: [[:ulong, :uint, :uint, :long], :int,
|
265
|
+
@my_lib.function :SendMessage, [:ulong, :uint, :uint, :pointer], :int,
|
266
|
+
alternative: [[:ulong, :uint, :uint, :long], :int,
|
267
|
+
->(*args){ Integer === args.last }]
|
298
268
|
end
|
299
269
|
|
300
270
|
it 'defines camel and snake methods (as well as hidden Original/Alternative methods)' do
|
301
|
-
|
302
|
-
|
271
|
+
expect { @my_lib.send_message(any_handle, Win::Gui::Message::WM_GETTEXT,
|
272
|
+
buffer.size, buffer) }.to_not raise_error
|
273
|
+
expect {
|
274
|
+
@my_lib.send_message(any_handle, Win::Gui::Message::WM_GETTEXT, buffer.size, buffer.address)
|
275
|
+
}.to_not raise_error
|
303
276
|
end
|
304
277
|
|
305
278
|
it 'defines camel and snake methods that work with both signatures' do
|
306
|
-
respond_to?(:SendMessage).should be_true
|
307
|
-
respond_to?(:send_message).should be_true
|
308
|
-
respond_to?(:SendMessageOriginal).should be_true
|
309
|
-
respond_to?(:SendMessageAlternative).should be_true
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
279
|
+
@my_obj.respond_to?(:SendMessage).should be_true
|
280
|
+
@my_obj.respond_to?(:send_message).should be_true
|
281
|
+
@my_obj.respond_to?(:SendMessageOriginal).should be_true
|
282
|
+
@my_obj.respond_to?(:SendMessageAlternative).should be_true
|
283
|
+
@my_lib.respond_to?(:SendMessage).should be_true
|
284
|
+
@my_lib.respond_to?(:send_message).should be_true
|
285
|
+
@my_lib.respond_to?(:SendMessageOriginal).should be_true
|
286
|
+
@my_lib.respond_to?(:SendMessageAlternative).should be_true
|
314
287
|
end
|
315
288
|
end
|
316
289
|
|
317
290
|
context 'trying to define an invalid API function' do
|
318
291
|
it 'raises error when trying to define function with a wrong function name' do
|
319
|
-
expect {
|
320
|
-
|
292
|
+
expect { @my_lib.function 'FindWindowImpossible', 'PP', 'L' }.
|
293
|
+
to raise_error(/Function 'FindWindowImpossible' not found/)
|
321
294
|
end
|
322
295
|
end
|
323
296
|
|
324
297
|
context 'calling defined methods with attached block to preprocess the API function results' do
|
325
298
|
it 'defined method yields raw result to block attached to its invocation' do
|
326
|
-
|
327
|
-
find_window(nil, IMPOSSIBLE) {|result| result.should == 0 }
|
299
|
+
@my_lib.function :FindWindow, 'PP', 'L', fails: 0
|
300
|
+
@my_obj.find_window(nil, IMPOSSIBLE) { |result| result.should == 0 }
|
328
301
|
end
|
329
302
|
|
330
303
|
it 'defined method returns result of block attached to its invocation' do
|
331
|
-
|
332
|
-
return_value = find_window(nil, IMPOSSIBLE) {|result| 'Value'}
|
304
|
+
@my_lib.function :FindWindow, 'PP', 'L', fails: 0
|
305
|
+
return_value = @my_obj.find_window(nil, IMPOSSIBLE) { |result| 'Value' }
|
333
306
|
return_value.should == 'Value'
|
334
307
|
end
|
335
308
|
|
336
309
|
it 'defined method transforms result of block before returning it' do
|
337
|
-
|
338
|
-
return_value = find_window(nil, IMPOSSIBLE) {|result| 0 }
|
310
|
+
@my_lib.function :FindWindow, 'PP', 'L', fails: 0
|
311
|
+
return_value = @my_obj.find_window(nil, IMPOSSIBLE) { |result| 0 }
|
339
312
|
return_value.should_not == 0
|
340
313
|
return_value.should == nil
|
341
314
|
end
|
@@ -343,43 +316,51 @@ module WinLibraryTest
|
|
343
316
|
|
344
317
|
context 'defining API function without arguments - f(VOID)' do
|
345
318
|
it 'should enforce argument count to 0, NOT 1' do
|
346
|
-
|
319
|
+
@my_lib.function :GetForegroundWindow, [], 'L', fails: 0
|
320
|
+
p (@my_lib.methods-Win::Library.methods).sort
|
321
|
+
p (@my_obj.methods-Win::Library.methods).sort
|
347
322
|
should_count_args :GetForegroundWindow, :get_foreground_window, :foreground_window, [], [nil, 0, 123]
|
348
323
|
end
|
349
324
|
end
|
350
325
|
|
351
326
|
context 'defining API function that has original snake_case name' do
|
352
327
|
it 'should define original function in (generated) CamelCase' do
|
353
|
-
|
354
|
-
expect {
|
355
|
-
|
328
|
+
@my_lib.function :keybd_event, [:char, :char, :ulong, :ulong], :void
|
329
|
+
expect {
|
330
|
+
@my_obj.KeybdEvent(Win::Gui::Input::VK_CONTROL, 0, Win::Gui::Input::KEYEVENTF_KEYDOWN, 0)
|
331
|
+
}.to_not raise_error
|
332
|
+
expect {
|
333
|
+
@my_obj.keybd_event(Win::Gui::Input::VK_CONTROL, 0, Win::Gui::Input::KEYEVENTF_KEYUP, 0)
|
334
|
+
}.to_not raise_error
|
356
335
|
end
|
357
336
|
end
|
358
337
|
end
|
359
338
|
|
360
339
|
context '::callback defining API callback TYPES' do
|
361
340
|
it '#callback macro defines a valid callback TYPE' do
|
362
|
-
expect {
|
341
|
+
expect { @my_lib.callback :MyEnumWindowsProc, [:HWND, :long], :bool }.to_not raise_error
|
363
342
|
end
|
364
343
|
|
365
|
-
it 'pre-
|
366
|
-
|
367
|
-
expect {
|
344
|
+
it 'pre-defined callback type can be used to define API functions (expecting callback)' do
|
345
|
+
@my_lib.callback :MyEnumWindowsProc, [:HWND, :long], :bool
|
346
|
+
expect { @my_lib.function :EnumWindows, [:MyEnumWindowsProc, :long], :long }.to_not raise_error
|
347
|
+
expect { @my_lib.function :EnumWindows, [:UndefinedProc, :long], :long }.to raise_error TypeError
|
368
348
|
end
|
369
349
|
|
370
350
|
it 'API function expecting callback accept lambdas representing callback' do
|
371
|
-
|
372
|
-
|
351
|
+
@my_lib.callback :MyEnumWindowsProc, [:HWND, :long], :bool
|
352
|
+
@my_lib.function :EnumWindows, [:MyEnumWindowsProc, :long], :long
|
353
|
+
expect { @my_obj.enum_windows(lambda { |handle, message| true }, 0) }.to_not raise_error
|
373
354
|
end
|
374
355
|
end
|
375
356
|
|
376
357
|
context '::try_function - possibly defines API functions that are platform-specific' do
|
377
358
|
if os_xp?
|
378
359
|
it 'silently fails to define function not present on current platform' do
|
379
|
-
expect {
|
380
|
-
expect {
|
381
|
-
expect { GetErrorMode() }.to raise_error /undefined method `GetErrorMode'/
|
382
|
-
expect { get_error_mode() }.to raise_error /undefined method `get_error_mode'/
|
360
|
+
expect { @my_lib.function :GetErrorMode, [], :UINT }.to raise_error /Function 'GetErrorMode' not found/
|
361
|
+
expect { @my_lib.try_function :GetErrorMode, [], :UINT }.to_not raise_error
|
362
|
+
expect { @my_obj.GetErrorMode() }.to raise_error /undefined method `GetErrorMode'/
|
363
|
+
expect { @my_obj.get_error_mode() }.to raise_error /undefined method `get_error_mode'/
|
383
364
|
end
|
384
365
|
end
|
385
366
|
end
|