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.
Files changed (45) hide show
  1. data/.gitignore +27 -0
  2. data/HISTORY +7 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +24 -0
  5. data/Rakefile +42 -0
  6. data/VERSION +1 -0
  7. data/bin/olegen.rb +368 -0
  8. data/features/p2ruby.feature +9 -0
  9. data/features/step_definitions/p2ruby_steps.rb +0 -0
  10. data/features/support/env.rb +10 -0
  11. data/features/support/world.rb +12 -0
  12. data/lib/extension.rb +19 -0
  13. data/lib/ole20110223-013209.rb +1677 -0
  14. data/lib/p2ruby/application.rb +111 -0
  15. data/lib/p2ruby/base.rb +59 -0
  16. data/lib/p2ruby/connection.rb +250 -0
  17. data/lib/p2ruby/data_stream.rb +215 -0
  18. data/lib/p2ruby/library.rb +24 -0
  19. data/lib/p2ruby/message.rb +150 -0
  20. data/lib/p2ruby/message_factory.rb +70 -0
  21. data/lib/p2ruby/record.rb +104 -0
  22. data/lib/p2ruby/router.rb +45 -0
  23. data/lib/p2ruby/table_set.rb +166 -0
  24. data/lib/p2ruby.rb +156 -0
  25. data/lib/version.rb +8 -0
  26. data/lib/win32ole-pr.rb +5540 -0
  27. data/spec/encoding_spec.rb +15 -0
  28. data/spec/p2ruby/application_spec.rb +35 -0
  29. data/spec/p2ruby/connection_spec.rb +293 -0
  30. data/spec/p2ruby/data_stream_spec.rb +218 -0
  31. data/spec/p2ruby/library_spec.rb +42 -0
  32. data/spec/p2ruby/message_factory_spec.rb +69 -0
  33. data/spec/p2ruby/message_spec.rb +159 -0
  34. data/spec/p2ruby/record_spec.rb +85 -0
  35. data/spec/p2ruby/router_spec.rb +54 -0
  36. data/spec/p2ruby/table_set_spec.rb +132 -0
  37. data/spec/p2ruby_spec.rb +46 -0
  38. data/spec/spec_helper.rb +78 -0
  39. data/tasks/common.rake +18 -0
  40. data/tasks/doc.rake +14 -0
  41. data/tasks/gem.rake +40 -0
  42. data/tasks/git.rake +34 -0
  43. data/tasks/spec.rake +16 -0
  44. data/tasks/version.rake +71 -0
  45. 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
+