win 0.3.24 → 0.3.25
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/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
|