p2ruby 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +27 -0
- data/HISTORY +7 -0
- data/LICENSE +20 -0
- data/README.rdoc +24 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/bin/olegen.rb +368 -0
- data/features/p2ruby.feature +9 -0
- data/features/step_definitions/p2ruby_steps.rb +0 -0
- data/features/support/env.rb +10 -0
- data/features/support/world.rb +12 -0
- data/lib/extension.rb +19 -0
- data/lib/ole20110223-013209.rb +1677 -0
- data/lib/p2ruby/application.rb +111 -0
- data/lib/p2ruby/base.rb +59 -0
- data/lib/p2ruby/connection.rb +250 -0
- data/lib/p2ruby/data_stream.rb +215 -0
- data/lib/p2ruby/library.rb +24 -0
- data/lib/p2ruby/message.rb +150 -0
- data/lib/p2ruby/message_factory.rb +70 -0
- data/lib/p2ruby/record.rb +104 -0
- data/lib/p2ruby/router.rb +45 -0
- data/lib/p2ruby/table_set.rb +166 -0
- data/lib/p2ruby.rb +156 -0
- data/lib/version.rb +8 -0
- data/lib/win32ole-pr.rb +5540 -0
- data/spec/encoding_spec.rb +15 -0
- data/spec/p2ruby/application_spec.rb +35 -0
- data/spec/p2ruby/connection_spec.rb +293 -0
- data/spec/p2ruby/data_stream_spec.rb +218 -0
- data/spec/p2ruby/library_spec.rb +42 -0
- data/spec/p2ruby/message_factory_spec.rb +69 -0
- data/spec/p2ruby/message_spec.rb +159 -0
- data/spec/p2ruby/record_spec.rb +85 -0
- data/spec/p2ruby/router_spec.rb +54 -0
- data/spec/p2ruby/table_set_spec.rb +132 -0
- data/spec/p2ruby_spec.rb +46 -0
- data/spec/spec_helper.rb +78 -0
- data/tasks/common.rake +18 -0
- data/tasks/doc.rake +14 -0
- data/tasks/gem.rake +40 -0
- data/tasks/git.rake +34 -0
- data/tasks/spec.rake +16 -0
- data/tasks/version.rake +71 -0
- metadata +149 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: CP1251
|
2
|
+
require 'rspec'
|
3
|
+
|
4
|
+
describe 'RSpec' do
|
5
|
+
it 'correctly outputs Windows Cyrillics' do
|
6
|
+
pending 'RSpec does NOT output Windows Cyrillics, unless `chcp 1251` is run in console'
|
7
|
+
Encoding.default_internal, Encoding.default_external = ['cp1251'] * 2
|
8
|
+
lit = "������� �������������� ����� �������� ���� ������ ������ ������� �����"
|
9
|
+
puts "Source encoding: #{__ENCODING__}"
|
10
|
+
puts "Def ext/int encoding: #{Encoding.default_external}/#{Encoding.default_internal}"
|
11
|
+
puts "String literal: #{lit} - encoding: #{lit.encoding}"
|
12
|
+
|
13
|
+
lit.should == :miserable_failure
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe P2::Application, "singleton app object" do
|
5
|
+
after(:all) { P2::Application.reset CLIENT_INI }
|
6
|
+
subject { P2::Application.instance CLIENT_INI }
|
7
|
+
|
8
|
+
it 'wraps P2ClientGate.P2Application OLE class' do
|
9
|
+
subject.ole_type.name.should == 'IP2Application'
|
10
|
+
show_ole
|
11
|
+
end
|
12
|
+
|
13
|
+
its(:clsid) { should == '{08A95064-05C2-4EF4-8B5D-D6211C2C9880}' }
|
14
|
+
its(:progid) { should == 'P2ClientGate.P2Application.1' }
|
15
|
+
its(:opts) { should have_key :ini }
|
16
|
+
its(:ini) { should == CLIENT_INI }
|
17
|
+
its(:ole) { should be_a WIN32OLE }
|
18
|
+
its(:ParserType) { should == 2 } # � 1 � Plaza; � 2 � Plaza-II (default)
|
19
|
+
|
20
|
+
it 'is a Singleton' do
|
21
|
+
a1 = P2::Application.instance
|
22
|
+
a2 = P2::Application.instance
|
23
|
+
a1.object_id.should == a2.object_id
|
24
|
+
end
|
25
|
+
|
26
|
+
context '.reset' do
|
27
|
+
|
28
|
+
it 'resets Application singleton' do
|
29
|
+
a1 = P2::Application.instance
|
30
|
+
P2::Application.reset CLIENT_INI1
|
31
|
+
a2 = P2::Application.instance
|
32
|
+
a1.object_id.should_not == a2.object_id
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,293 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
def random_name
|
5
|
+
"APP-#{rand 10000}"
|
6
|
+
end
|
7
|
+
|
8
|
+
shared_examples_for 'new connection' do
|
9
|
+
|
10
|
+
its(:clsid) { should == '{CCD42082-33E0-49EA-AED3-9FE39978EB56}' }
|
11
|
+
its(:progid) { should == 'P2ClientGate.P2Connection.1' }
|
12
|
+
its(:opts) { should be_a Hash }
|
13
|
+
its(:ole) { should be_a WIN32OLE }
|
14
|
+
its(:Status) { should == P2::CS_CONNECTION_DISCONNECTED }
|
15
|
+
its(:status_text) { should == 'Connection Disconnected' }
|
16
|
+
|
17
|
+
it 'raises on NodeName access' do
|
18
|
+
expect { subject.NodeName }.to raise_error /Couldn't get MQ node name/
|
19
|
+
# its(:NodeName) { should == "??" }
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'is possible to set settable properties' do
|
23
|
+
# Notes: �������� AppName, NodeName, Host, Port, Password � Timeout ������ ����
|
24
|
+
# ������ �� ������� ������ ������ Connect. � ������ ��������� ������ ������� ���
|
25
|
+
# ����, ����� ��������� �������� � ���� ���������� �������� ���������������� �����
|
26
|
+
# ������� Disconnect � Connect. ��������� �������������� ������� (LoginStr) ������
|
27
|
+
# ���� ������ �� ������� ������ ������ Login.
|
28
|
+
subject.AppName ='REASSIGNED'
|
29
|
+
subject.Host ='REASSIGNED_HOST'
|
30
|
+
subject.Port =1313
|
31
|
+
subject.LoginStr ='REASSIGNED_STRING'
|
32
|
+
subject.Timeout =13
|
33
|
+
subject.Password ='REASSIGNED_PASS'
|
34
|
+
|
35
|
+
subject.AppName.should == 'REASSIGNED'
|
36
|
+
subject.Name.should == 'REASSIGNED'
|
37
|
+
subject.name.should == 'REASSIGNED'
|
38
|
+
subject.Host.should == 'REASSIGNED_HOST'
|
39
|
+
subject.Port.should == 1313
|
40
|
+
subject.LoginStr.should =='REASSIGNED_STRING'
|
41
|
+
subject.Timeout.should == 13
|
42
|
+
# subject.Password.should == 'REASSIGNED_PASS' # - No accessor for Password!
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'is possible to set/access AppName property through aliases' do
|
46
|
+
subject.Name ='Set through Name'
|
47
|
+
subject.AppName.should == 'Set through Name'
|
48
|
+
subject.Name.should == 'Set through Name'
|
49
|
+
subject.name.should == 'Set through Name'
|
50
|
+
|
51
|
+
subject.name ='Now set through name'
|
52
|
+
subject.AppName.should == 'Now set through name'
|
53
|
+
subject.Name.should == 'Now set through name'
|
54
|
+
subject.name.should == 'Now set through name'
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'is not connected right away' do
|
58
|
+
subject.should_not be_connected
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe P2::Connection do
|
63
|
+
before(:all) do
|
64
|
+
start_router
|
65
|
+
P2::Application.reset CLIENT_INI
|
66
|
+
end
|
67
|
+
after(:all) { stop_router }
|
68
|
+
|
69
|
+
describe '.new' do
|
70
|
+
context 'with options' do
|
71
|
+
subject { P2::Connection.new :ini => CLIENT_INI,
|
72
|
+
:app_name => random_name,
|
73
|
+
:host => "localhost",
|
74
|
+
:port => 3333,
|
75
|
+
:timeout => 500,
|
76
|
+
:login_str => "Blah" }
|
77
|
+
|
78
|
+
it 'wraps P2ClientGate.P2Connection OLE class' do
|
79
|
+
subject.ole_type.name.should == 'IP2Connection'
|
80
|
+
show_ole
|
81
|
+
end
|
82
|
+
|
83
|
+
its(:AppName) { should =~ /APP-./ }
|
84
|
+
its(:Host) { should == "localhost" }
|
85
|
+
its(:Port) { should == 3333 }
|
86
|
+
its(:Timeout) { should == 500 }
|
87
|
+
its(:LoginStr) { should == "Blah" }
|
88
|
+
|
89
|
+
# Alias properties
|
90
|
+
its(:Name) { should =~ /APP-./ }
|
91
|
+
its(:name) { should =~ /APP-./ }
|
92
|
+
|
93
|
+
it_behaves_like 'new connection'
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'by default' do
|
97
|
+
# Ini file is still necessary if Application instance does not exist yet. Otherwise
|
98
|
+
# Connection#new will SEGFAULT looking for default "P2ClientGate.ini" in current dir
|
99
|
+
subject { P2::Connection.new }
|
100
|
+
|
101
|
+
its(:AppName) { should == '' }
|
102
|
+
its(:Host) { should == '' }
|
103
|
+
its(:Port) { should == 3000 }
|
104
|
+
its(:Timeout) { should == 1000 }
|
105
|
+
its(:LoginStr) { should == '' }
|
106
|
+
it_behaves_like 'new connection'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#Connect()', 'creates local connection to Router' do
|
111
|
+
context 'with correct connection parameters' do
|
112
|
+
it 'connects successfully' do
|
113
|
+
@conn = P2::Connection.new :app_name => random_name,
|
114
|
+
:host => "127.0.0.1", :port => 4001
|
115
|
+
@conn.Connect().should == P2::P2ERR_OK
|
116
|
+
@conn.NodeName.should =~ Regexp.new(ROUTER_LOGIN)
|
117
|
+
@conn.should be_connected
|
118
|
+
@conn.status_text.should == "Connection Connected, Router Connected"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'with wrong connection parameters' do
|
123
|
+
it 'fails to connect' do
|
124
|
+
@conn = P2::Connection.new :app_name => random_name, :timeout => 200,
|
125
|
+
:host => "127.0.0.1", :port => 1313
|
126
|
+
expect { @conn.Connect() }.to raise_error /Couldn't connect to MQ/
|
127
|
+
@conn.should_not be_connected
|
128
|
+
@conn.status_text.should == "Connection Disconnected"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe '#Disconnect()', 'drops local connection to Router' do
|
134
|
+
context 'when connected to Router' do
|
135
|
+
before do
|
136
|
+
@conn = P2::Connection.new :app_name => random_name,
|
137
|
+
:host => "127.0.0.1", :port => 4001
|
138
|
+
@conn.Connect()
|
139
|
+
@conn.should be_connected
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'disconnects from Router successfully' do
|
143
|
+
@conn.Disconnect()
|
144
|
+
expect { @conn.NodeName }.to raise_error /Couldn't get MQ node name/
|
145
|
+
@conn.should_not be_connected
|
146
|
+
@conn.status_text.should == "Connection Disconnected"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'when NOT connected to Router' do
|
151
|
+
it 'it`s noop' do
|
152
|
+
@conn = P2::Connection.new :app_name => random_name,
|
153
|
+
:host => "127.0.0.1", :port => 1313
|
154
|
+
@conn.Disconnect()
|
155
|
+
@conn.should_not be_connected
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe '#Connect2 '
|
161
|
+
# Connect2 ( [in] BSTR connStr, [out, retval] ULONG* errClass);
|
162
|
+
# �������� ���������� ���������� ���������� � ��������. ���������� � ������ Connect.
|
163
|
+
|
164
|
+
describe '#ProcessMessage'
|
165
|
+
# ProcessMessage ( [out] ULONG* cookie, [in] ULONG pollTimeout);
|
166
|
+
# ����� � ��������� ���������, � ��� ����� � ��������������.
|
167
|
+
# ���������
|
168
|
+
# � pollTimeout � ������� � �������������, � ������� �������� ��������� ��������� ���������;
|
169
|
+
# � cookie � ���������� ������������� ����������.
|
170
|
+
|
171
|
+
describe '#ProcessMessage2'
|
172
|
+
# ProcessMessage2 ( [in] ULONG pollTimeout, [out, retval] ULONG* cookie);
|
173
|
+
# ����� � ��������� ���������. ������� � ���������� � ������ Connection.ProcessMessage,
|
174
|
+
# ��� ��� ��� �� �������� � ������������������ ������ (JScript) �������� ���������
|
175
|
+
# ������ ������� (cookie).
|
176
|
+
|
177
|
+
describe '#RegisterReceiver'
|
178
|
+
# RegisterReceiver ( [in] IP2MessageReceiver* newReceiver, [out,retval] ULONG* cookie);
|
179
|
+
# ����������� ����������.
|
180
|
+
# ���������
|
181
|
+
# � newReceiver � ��������� �� ��������� ��������� ������;
|
182
|
+
# � cookie � ���������� ������������� ����������. ������������ ��� ����, ����� �����
|
183
|
+
# ���� �������� ��������, � ����� ������ �� ���� � ������ Connection.ProcessMessage
|
184
|
+
# ������������ ���������� ���������.
|
185
|
+
|
186
|
+
describe '#UnRegisterReceiver'
|
187
|
+
# UnRegisterReceiver ([in] ULONG cookie);
|
188
|
+
# ������ ����������� ����������.
|
189
|
+
|
190
|
+
describe '#ResolveService' do
|
191
|
+
# ResolveService ( [in] BSTR service, [out,retval] BSTR* address);
|
192
|
+
# ��������� ������� ������ ���������� �� ����� �������, ������� ��� �������������.
|
193
|
+
# ���������
|
194
|
+
# � service � ��� �������;
|
195
|
+
# � address � ������ ����� ����������.
|
196
|
+
|
197
|
+
before(:all) do
|
198
|
+
@conn = P2::Connection.new :app_name => random_name,
|
199
|
+
:host => "127.0.0.1", :port => 4001
|
200
|
+
@conn.Connect()
|
201
|
+
@conn.should be_connected
|
202
|
+
@conn.should be_logged
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'returns full server address, given a service name' do
|
206
|
+
@conn.ResolveService('FORTS_OPTINFO_REPL').should == "FINTER_FORTS3.inter_info"
|
207
|
+
@conn.ResolveService('FORTS_FUTINFO_REPL').should == "FINTER_FORTS3.inter_info"
|
208
|
+
@conn.ResolveService('FORTS_POS_REPL').should == "FINTER_FORTS3.inter_pos"
|
209
|
+
@conn.ResolveService('FORTS_FUTCOMMON_REPL').should== "FINTER_FORTS3.inter_futcommon"
|
210
|
+
@conn.ResolveService('FORTS_OPTCOMMON_REPL').should== "FINTER_FORTS3.inter_optcommon"
|
211
|
+
@conn.ResolveService('FORTS_VOLAT_REPL').should == "FINTER_FORTS3.inter_vmv"
|
212
|
+
@conn.ResolveService('FORTS_VM_REPL').should == "FINTER_FORTS3.inter_vmv"
|
213
|
+
# Order placement:
|
214
|
+
@conn.ResolveService("FORTS_SRV").should == "FINTER_FORTS3.Dispatcher"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# �������������� ����������� ����������. �������� ������� �� ������ Login ��������,
|
219
|
+
# ��� ������������������ ���������� ���� ������� �� ������. ��� ����, ����� ������,
|
220
|
+
# ������� �� ����������� ��������������, ������� �������� � ������������ �����������
|
221
|
+
# � ��������� ����������.
|
222
|
+
context 'When router is authenticated via ini file' do
|
223
|
+
end
|
224
|
+
context 'When router is authenticated explicitely - via Login()' do
|
225
|
+
end
|
226
|
+
|
227
|
+
describe '#Logout(void)', 'drops Router connection to uplink (RTS)' do
|
228
|
+
context 'when Router is connected' do
|
229
|
+
before(:all) do
|
230
|
+
@conn = P2::Connection.new :app_name => random_name,
|
231
|
+
:host => "127.0.0.1", :port => 4001
|
232
|
+
@conn.Connect()
|
233
|
+
@conn.should be_connected
|
234
|
+
@conn.Logout()
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'keeps local connection to Router' do
|
238
|
+
@conn.should be_connected
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'only sends an ASYNC request to disconnect Router from uplink' do
|
242
|
+
@conn.should be_logged # Need to wait for Server to react to logout
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end #Logout()
|
246
|
+
|
247
|
+
describe '#events' do
|
248
|
+
before(:each) do
|
249
|
+
@conn = P2::Connection.new :app_name => random_name,
|
250
|
+
:host => "127.0.0.1", :port => 4001
|
251
|
+
@conn.Connect()
|
252
|
+
@events = @conn.events
|
253
|
+
@event_fired = false
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'provides access to (IP2ConnectionEvent interface) events' do
|
257
|
+
@events.should be_kind_of WIN32OLE_EVENT
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'allows setting callbacks for IP2ConnectionEvent interface events' do
|
261
|
+
@events.on_event do |event_name, ole, status|
|
262
|
+
@event_fired = true
|
263
|
+
p "EVENT: #{event_name}, #{ole}, #{status}"
|
264
|
+
event_name.should == "ConnectionStatusChanged"
|
265
|
+
ole.ole_type.name.should == "IP2Connection"
|
266
|
+
status.should be_kind_of Fixnum
|
267
|
+
end
|
268
|
+
|
269
|
+
@conn.ProcessMessage2(100) # Grabs messages/events from queue
|
270
|
+
@event_fired.should == true
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'allows setting explicit handler for IP2ConnectionEvent events' do
|
274
|
+
class TestHandler
|
275
|
+
attr_accessor :event_fired
|
276
|
+
|
277
|
+
def onConnectionStatusChanged(ole, status)
|
278
|
+
puts "StatusTextChanged"
|
279
|
+
@event_fired = true
|
280
|
+
p "HANDLER EVENT (ConnectionStatusChanged): #{ole}, #{status}"
|
281
|
+
ole.ole_type.name.should == "IP2Connection"
|
282
|
+
status.is_a?(Fixnum).should == true # We are inside Handler class, no #be_kind_of
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
@events.handler = TestHandler.new
|
287
|
+
@conn.ProcessMessage2(100) # Grabs messages/events from queue
|
288
|
+
|
289
|
+
@events.handler.should be_a TestHandler
|
290
|
+
@events.handler.event_fired.should == true
|
291
|
+
end
|
292
|
+
end #events
|
293
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
def baseless_opts
|
5
|
+
{:stream_name => 'RTS_INDEX_REPL',
|
6
|
+
:type => P2::RT_COMBINED_DYNAMIC}
|
7
|
+
end
|
8
|
+
|
9
|
+
describe P2::DataStream do
|
10
|
+
before(:all) do
|
11
|
+
start_router
|
12
|
+
P2::Application.reset CLIENT_INI
|
13
|
+
@conn = P2::Connection.new :app_name => 'DSTest',
|
14
|
+
:host => "127.0.0.1", :port => 4001
|
15
|
+
@conn.Connect
|
16
|
+
@conn.should be_connected
|
17
|
+
@conn.should be_logged
|
18
|
+
# Disconnected connection, for comparison
|
19
|
+
@disconn = P2::Connection.new :app_name => 'DSTestDisconnected',
|
20
|
+
:host => "127.0.0.1", :port => 4001
|
21
|
+
end
|
22
|
+
|
23
|
+
after(:all) { stop_router }
|
24
|
+
|
25
|
+
context 'initializing Baseless' do
|
26
|
+
subject { P2::DataStream.new baseless_opts }
|
27
|
+
describe '.new' do
|
28
|
+
it 'wraps P2ClientGate.P2DataStream OLE class' do
|
29
|
+
subject.ole_type.name.should == 'IP2DataStream'
|
30
|
+
show_ole
|
31
|
+
end
|
32
|
+
|
33
|
+
its(:clsid) { should == '{914893CB-0864-4FBB-856A-92C3A1D970F8}' }
|
34
|
+
its(:progid) { should == 'P2ClientGate.P2DataStream.1' }
|
35
|
+
its(:opts) { should be_a Hash }
|
36
|
+
its(:ole) { should be_a WIN32OLE }
|
37
|
+
its(:StreamName) { should == 'RTS_INDEX_REPL' }
|
38
|
+
its(:Type) { should == P2::RT_COMBINED_DYNAMIC }
|
39
|
+
its(:State) { should == P2::DS_STATE_CLOSE }
|
40
|
+
its(:TableSet) { should == nil }
|
41
|
+
its(:DBConnString) { should == '' }
|
42
|
+
its(:state_text) { should == 'Data Stream Closed' }
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'is possible to set settable properties' do
|
47
|
+
subject.Type = P2::RT_LOCAL
|
48
|
+
subject.DBConnString = 'Blah'
|
49
|
+
subject.StreamName = 'BLAH_REPL'
|
50
|
+
|
51
|
+
subject.Type.should == P2::RT_LOCAL
|
52
|
+
subject.DBConnString.should == 'Blah'
|
53
|
+
subject.StreamName.should == 'BLAH_REPL'
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'is possible to set either wrapped or unwrapped TableSet' do
|
57
|
+
subject.TableSet = P2::TableSet.new :ini => TABLESET_INI, :life_num => 1313
|
58
|
+
subject.TableSet.LifeNum.should == 1313
|
59
|
+
|
60
|
+
subject.TableSet = (P2::TableSet.new :ini => TABLESET_INI, :life_num => 131313).ole
|
61
|
+
subject.TableSet.LifeNum.should == 131313
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'is possible to set/access StreamName property through aliases' do
|
65
|
+
subject.Name ='Set through Name'
|
66
|
+
subject.StreamName.should == 'Set through Name'
|
67
|
+
subject.Name.should == 'Set through Name'
|
68
|
+
subject.name.should == 'Set through Name'
|
69
|
+
|
70
|
+
subject.name ='Now set through name'
|
71
|
+
subject.StreamName.should == 'Now set through name'
|
72
|
+
subject.Name.should == 'Now set through name'
|
73
|
+
subject.name.should == 'Now set through name'
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should not be open initially' do
|
77
|
+
subject.should_not be_open
|
78
|
+
subject.should_not be_opened
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when initialized Baseless' do
|
83
|
+
subject { P2::DataStream.new baseless_opts }
|
84
|
+
describe '#Open()' do
|
85
|
+
it 'opens replication data stream via connection' do
|
86
|
+
subject.Open(@conn)
|
87
|
+
subject.should be_open
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'opens replication data stream via raw connection ole' do
|
91
|
+
subject.Open(@conn.ole)
|
92
|
+
subject.should be_open
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'fails to open data stream via disconnected connection?!' do
|
96
|
+
@disconn.should_not be_connected
|
97
|
+
expect { subject.Open(@disconn) }.to raise_error /Couldn't open baseless repl datastream/
|
98
|
+
subject.should_not be_open
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'fails to open data stream if arg is not a connection' do
|
102
|
+
expect { subject.Open(subject) }.to raise_error /Type mismatch/
|
103
|
+
expect { subject.Open(1313) }.to raise_error /not valid value/
|
104
|
+
subject.should_not be_open
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#Close()' do
|
109
|
+
it 'closes opened replication data stream' do
|
110
|
+
# --- before
|
111
|
+
subject.Open(@conn)
|
112
|
+
subject.should be_open
|
113
|
+
|
114
|
+
# --- example
|
115
|
+
subject.Close()
|
116
|
+
subject.should_not be_open
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'does not raise errors closing unopened stream' do
|
120
|
+
# --- before
|
121
|
+
subject.should_not be_open
|
122
|
+
|
123
|
+
# --- example
|
124
|
+
subject.Close()
|
125
|
+
subject.should_not be_open
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'testing stream state' do
|
130
|
+
describe 'unopened data stream' do
|
131
|
+
|
132
|
+
it 'is not open' do
|
133
|
+
subject.open?.should == false
|
134
|
+
subject.opened?.should == false
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'is closed' do
|
138
|
+
subject.closed?.should == true
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'is not error' do
|
142
|
+
subject.error?.should == false
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe 'opened data stream' do
|
147
|
+
before { subject.Open(@conn) }
|
148
|
+
it 'is open' do
|
149
|
+
subject.open?.should == true
|
150
|
+
subject.opened?.should == true
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'is not closed' do
|
154
|
+
subject.closed?.should == false
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'is not error' do
|
158
|
+
subject.error?.should == false
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe 'data stream in error' # how?
|
163
|
+
end
|
164
|
+
end # when initialized Baseless
|
165
|
+
|
166
|
+
describe '#events' do
|
167
|
+
before do
|
168
|
+
@ds = P2::DataStream.new baseless_opts
|
169
|
+
@events = @ds.events
|
170
|
+
@events_fired = 0
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'provides access to (IP2ConnectionEvent interface) events' do
|
174
|
+
@events.should be_kind_of WIN32OLE_EVENT
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'allows setting callbacks for IP2ConnectionEvent interface events' do
|
178
|
+
@events.on_event do |event_name, ole, state|
|
179
|
+
@events_fired += 1
|
180
|
+
p "EVENT: #{event_name}, #{ole}, #{state}"
|
181
|
+
event_name.should == "StreamStateChanged"
|
182
|
+
ole.ole_type.name.should == "IP2DataStream"
|
183
|
+
state.should be_kind_of Fixnum
|
184
|
+
end
|
185
|
+
|
186
|
+
@ds.Open(@conn)
|
187
|
+
@ds.Close()
|
188
|
+
# @conn.ProcessMessage2(100) # Grabs messages/events from queue
|
189
|
+
@events_fired.should == 2
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'allows setting explicit handler for IP2ConnectionEvent events' do
|
193
|
+
class TestHandler
|
194
|
+
attr_accessor :events_fired
|
195
|
+
|
196
|
+
def onStreamStateChanged(ole, status)
|
197
|
+
@events_fired = (@events_fired || 0) + 1
|
198
|
+
p "HANDLER EVENT (StreamStateChanged): #{ole}, #{status}"
|
199
|
+
ole.ole_type.name.should == "IP2DataStream"
|
200
|
+
status.is_a?(Fixnum).should == true # We are inside Handler class, no #be_kind_of
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
@events.handler = TestHandler.new
|
205
|
+
@events.handler.should be_a TestHandler
|
206
|
+
|
207
|
+
@ds.Open(@conn)
|
208
|
+
@ds.Close()
|
209
|
+
# @conn.ProcessMessage2(100) # Grabs messages/events from queue
|
210
|
+
@events.handler.events_fired.should == 2
|
211
|
+
end
|
212
|
+
end #events
|
213
|
+
|
214
|
+
context 'when baseless data stream is open' do
|
215
|
+
subject { P2::DataStream.new(baseless_opts).tap { |ds| ds.Open @conn } }
|
216
|
+
|
217
|
+
end # when baseless data stream is open
|
218
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe P2::Library do
|
5
|
+
|
6
|
+
context 'at initialization' do
|
7
|
+
it 'works only with pre-registered STA P2ClientGate typelib' do
|
8
|
+
libs = WIN32OLE_TYPELIB.typelibs
|
9
|
+
p2libs = libs.select { |t| t.name=~/P2ClientGate/ }
|
10
|
+
print 'Registered P2ClientGate libs: '
|
11
|
+
p p2libs.map &:guid
|
12
|
+
p2sta = p2libs.find { |t| t.name !~ /MTA/ }
|
13
|
+
p2sta.should_not be_nil
|
14
|
+
print 'P2ClientGate (STA) OLE types: '
|
15
|
+
p2sta.ole_types.map { |k| p [k.name, k.progid, k.guid, k.implemented_ole_types] }
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'wraps STA P2ClientGate typelib' do
|
19
|
+
lib = P2::Library.new
|
20
|
+
lib.name.should =~ /P2ClientGate/
|
21
|
+
lib.name.should_not =~ /MTA/
|
22
|
+
end
|
23
|
+
end # initialization
|
24
|
+
|
25
|
+
describe '.default' do
|
26
|
+
it 'points to (initialized) STA P2ClientGate OLE typelib singleton' do
|
27
|
+
P2::Library.default.should be_an_instance_of P2::Library
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when initialized' do
|
32
|
+
let(:lib) { P2::Library.default }
|
33
|
+
|
34
|
+
describe '#find' do
|
35
|
+
it 'returns progid needed to create OLE type with a given name' do
|
36
|
+
lib.find("P2Application").should == "P2ClientGate.P2Application.1"
|
37
|
+
lib.find("App").should == "P2ClientGate.P2Application.1"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end # when initialized
|
42
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe P2::MessageFactory do
|
5
|
+
before(:all) { P2::Application.reset CLIENT_INI }
|
6
|
+
subject { P2::MessageFactory.new :ini => MESSAGE_INI }
|
7
|
+
|
8
|
+
it 'wraps P2ClientGate.P2BLMessageFactory OLE class' do
|
9
|
+
subject.ole_type.name.should == 'IP2BLMessageFactory'
|
10
|
+
show_ole
|
11
|
+
end
|
12
|
+
|
13
|
+
its(:clsid) { should == '{501786DA-CA02-45C1-B815-1C58C383265D}' }
|
14
|
+
its(:progid) { should == 'P2ClientGate.P2BLMessageFactory.1' }
|
15
|
+
its(:opts) { should have_key :ini }
|
16
|
+
its(:ole) { should be_a WIN32OLE }
|
17
|
+
|
18
|
+
describe '#Init()', 'is implicitly called by #new'
|
19
|
+
# Init ( BSTR structFile, BSTR signFile); - ������������� �������.
|
20
|
+
# ���������
|
21
|
+
# � structFile � ini-����, ���������� ����� ���������.
|
22
|
+
# � signFile � �� ������������.
|
23
|
+
|
24
|
+
describe '#CreateMessageByName()', 'creates raw (unwrapped) OLE message objects' do
|
25
|
+
# CreateMessageByName ( [in] BSTR msgName, [out,retval] IP2BLMessage** newMsg);
|
26
|
+
# �������� ��������� �� �����.
|
27
|
+
# ���������
|
28
|
+
# � msgName � ��� ��������� (��� ������� ��).
|
29
|
+
it 'creates raw OLE message objects according to scheme' do
|
30
|
+
msg = subject.CreateMessageByName("FutAddOrder")
|
31
|
+
msg.should be_a WIN32OLE # raw (unwrapped) OLE object!
|
32
|
+
msg.ole_type.name.should == 'IP2BLMessage'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#message', 'creates P2::Message according to scheme' do
|
37
|
+
# This is a P2 object wrapper for CreateMessageByName
|
38
|
+
|
39
|
+
it 'creates P2::Message wrapper given message opts' do
|
40
|
+
msg = subject.message :name => "FutAddOrder", :dest_addr => 'Blah'
|
41
|
+
msg.should be_a P2::Message
|
42
|
+
msg.DestAddr.should == "Blah"
|
43
|
+
p msg.Id
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'creates P2::Message wrapper given a name and opts' do
|
47
|
+
msg = subject.message "FutAddOrder", :dest_addr => 'Blah'
|
48
|
+
msg.should be_a P2::Message
|
49
|
+
msg.DestAddr.should == "Blah"
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'creates P2::Message wrapper given a name WITHOUT opts' do
|
53
|
+
msg = subject.message "FutAddOrder"
|
54
|
+
msg.should be_a P2::Message
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'fails to create P2::Message wrapper given wrong number of args' do
|
58
|
+
[[], ["One", "two", {}], ['one', 'two', 'three']].each do |args|
|
59
|
+
expect { msg = subject.message *args }.to raise_error ArgumentError
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'fails to create P2::Message wrapper given wrong message name' do
|
64
|
+
expect { msg = subject.message 'Impossible' }.
|
65
|
+
to raise_error /Couldn't create BL message by name/
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|