-
Notifications
You must be signed in to change notification settings - Fork 2
/
enterprise_ole_example.rb
238 lines (187 loc) · 7.82 KB
/
enterprise_ole_example.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
require 'example_helper'
module Examples
module EnterpriseOle
fail 'OLE in UNIX??? :)' if PLATFORM::LINUX
module HRESULT
RPC_SERVER_UNAVALIBLE = '0x800706ba'
end
# 1C:Enterprise provides three OLE servers:
# v8x.Application - thick client local OLE server
# v8xC.Application - thin client local OLE server
# v8x.ComConnector - in-process OLE server for connect to:
# - 1C:Enterprise application aka infobases
# - 1C:Enterprise server agent
# - 1C:Enterprise server working process
describe 'AssLauncher provides wrappers for 1C:Enterprise Ole servers' do
extend AssLauncher::Api
# Wrappers returned AssLauncher::Api#ole method
thick_app = ole(:thick, PLATFORM_VER)
it 'Wrapper for "Thick application ole server" (aka v83.Application)' do
thick_app.must_be_instance_of AssLauncher::Enterprise::Ole::ThickApplication
end
thin_app = ole(:thin, PLATFORM_VER)
it 'Wrapper for "Thin application ole server" (aka v83c.Application)' do
thin_app.must_be_instance_of AssLauncher::Enterprise::Ole::ThinApplication
end
external = ole(:external, PLATFORM_VER)
it 'Wrapper for "External connection with infobase" (childe v83.ComConnector)' do
external.must_be_instance_of AssLauncher::Enterprise::Ole::IbConnection
end
wpconn = ole(:wprocess, PLATFORM_VER)
it 'Wrapper for "1C:Enterprise server working process connection" (childe v83.ComConnector)' do
wpconn.must_be_instance_of AssLauncher::Enterprise::Ole::WpConnection
end
saconn = ole(:sagent, PLATFORM_VER)
it 'Wrapper for "1C:Enterprise server agent connection" (childe v83.ComConnector)' do
saconn.must_be_instance_of AssLauncher::Enterprise::Ole::AgentConnection
end
end
describe 'Example for basic to use' do
extend AssLauncher::Api
# Get ole wrapper
external = ole(:external, PLATFORM_VER)
it 'Example' do
# Open connection with connection string
# For WpConnection and AgentConnection __connect__
# expects URI string
external.__open__ TMP::EMPTY_IB_CS
# Call 1C:Enterprise method #InfoBaseConnectionString
external.InfoBaseConnectionString.must_equal\
TMP::EMPTY_IB_CS.to_ole_string
# Close connection
external.__close__
end
after do
external.__close__
end
end
describe 'Closing connection' do
describe 'For local server it working perfect' do
extend AssLauncher::Api
thick_app = ole(:thick, PLATFORM_VER)
it 'Connection realy closed of thick_app' do
thick_app.__open__ TMP::EMPTY_IB_CS
ole_array = thick_app.newObject('Array')
ole_array.Count.must_equal 0
thick_app.__close__
# Fails because OLE server is down
e = proc {
ole_array.Count
}.must_raise NoMethodError
e.message.must_match %r{error code:#{HRESULT::RPC_SERVER_UNAVALIBLE}}
end
after do
thick_app.__close__
end
end
describe 'For in-process server close connection working with restrictions' do
# 1C in-process OLE servers haven't method for closing connection!
# Connection keep alive while live ruby process.
#
# If in one ruby script we want to use in-process connection for some work
# do in the infobase and after them we want run other connection
# or application or designer with flag of exclusive mode, in this case
# opened in-process connection doesn't give us to do it
#
# AssLauncher provide feature for closing in-process connection but
# it working with restrictions.
#
# AssLauncher patching WIN32OLE and collect all ole objects which
# generated and try kill refs calling #ole_free method for them when
# #__close__ method call.
#
# But it works not always. Connection keep alive while have any alive
# WIN32OLE refs generated this connection
describe 'Case when in-process server connection realy closed' do
extend AssLauncher::Api
# Get local ole server wrapper
# It is service connector
thick_app = ole(:thick, PLATFORM_VER)
# Get in-process ole server wrapper
# It object under test
external = ole(:external, PLATFORM_VER)
it 'External connection realy closed' do
thick_app.__open__ TMP::EMPTY_IB_CS
external.__open__ TMP::EMPTY_IB_CS
# We have two working sessions
thick_app.GetInfoBaseSessions.Count.must_equal 2
ole_array = external.newObject('Array')
ole_array.Count.must_equal 0
external.__close__
# External connection was closed
# and only one working session is alive
thick_app.GetInfoBaseSessions.Count.must_equal 1
# Fails 'failed to get Dispatch Interface'
# because #ole_free was called while external.__close__
e = proc {
ole_array.Count
}.must_raise RuntimeError
e.message.must_match %r{failed to get Dispatch Interface}i
end
after do
thick_app.__close__
external.__close__
end
end
end
end
describe 'We can chose version of 1C:Enterprise ole server' do
# We can choosing 1C ole server's version.
# AssLauncher automatically register needed server version
# and returns suitable wrapper.
#
# Registration version of ole server working correct only for local
# servers such as Thin and Thick applications.
#
# We don't get new version of in-process ole server until old version
# is loaded in memory
it "Fail if 1C:Enterprise version doesn't instaled" do
extend AssLauncher::Api
external = ole(:external, '~> 999')
e = proc {
external.__open__ ''
}.must_raise RuntimeError
e.message.must_match %r{Platform version `~> 999' not instaled}
end
describe 'Choosing version of local ole server working perfect' do
extend AssLauncher::Api
thick_app = ole(:thick, PLATFORM_VER)
it 'Ole server have suitable version' do
thick_app.__open__ TMP::EMPTY_IB_CS
system_info = thick_app.newObject('SystemInfo')
real_ole_app_version = Gem::Version.new(system_info.AppVersion)
real_ole_app_version.must_equal\
thick_app.instance_variable_get(:@__ole_binary__).version
thick_app.__close__
end
after do
thick_app.__close__
end
end
end
describe 'AssLauncher patching WIN32OLE for some reason' do
describe 'Getting real Ruby objects from WIN32OLE wrapper' do
# Ruby WIN32OLE automatically convert Ruby objects into IDispatch
# when they passed as parameter in to OLE server's side.
# When such objects returns on the Ruby's side they will keep as WIN32OLE
# AssLauncher provides feature for getting real Ruby object
it 'Example' do
ole_server = WIN32OLE.new('Scripting.Dictionary')
ruby_obj = Object.new
skip "It usually Segmentation fault in ruby:\n"\
" 2.0.0p645 (2015-04-13 revision 50299) [i386-cygwin]\n"\
" 2.3.6p384 (2017-12-14 revision 9808) [i386-cygwin]"
# Call OLE server
ole_server.add(1, ruby_obj)
wrapped_obj = ole_server.items[0]
# Ruby object wrapped into WIN32OLE
wrapped_obj.must_be_instance_of WIN32OLE
# Ask: Is it Ryuby object?
wrapped_obj.__ruby__?.must_equal true
# Get Ruby object
wrapped_obj.__real_obj__.must_equal ruby_obj
end
end
end
end
end