1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4
5 #include <Ice/Ice.h>
6 #include <IceUtil/Random.h>
7 #include <TestHelper.h>
8 #include <Test.h>
9
10 using namespace std;
11 using namespace Test;
12
13 namespace
14 {
15
16 class Condition : public IceUtil::Mutex, public IceUtil::Shared
17 {
18 public:
19
Condition(bool value)20 Condition(bool value) : _value(value)
21 {
22 }
23
24 void
set(bool value)25 set(bool value)
26 {
27 Lock sync(*this);
28 _value = value;
29 }
30
31 bool
value() const32 value() const
33 {
34 Lock sync(*this);
35 return _value;
36 }
37
38 private:
39
40 bool _value;
41 };
42 typedef IceUtil::Handle<Condition> ConditionPtr;
43
44 class SetCB : public IceUtil::Shared, public IceUtil::Monitor<IceUtil::Mutex>
45 {
46 public:
47
SetCB(const ConditionPtr & condition,Ice::Int expected)48 SetCB(const ConditionPtr& condition, Ice::Int expected) : _condition(condition), _expected(expected)
49 {
50 }
51
52 void
response(Ice::Int value)53 response(Ice::Int value)
54 {
55 if(value != _expected)
56 {
57 _condition->set(false);
58 }
59 }
60
61 void
exception(const Ice::Exception &)62 exception(const Ice::Exception&)
63 {
64 }
65
66 private:
67
68 const ConditionPtr _condition;
69 Ice::Int _expected;
70 };
71 typedef IceUtil::Handle<SetCB> SetCBPtr;
72
73 }
74
75 void
allTests(Test::TestHelper * helper)76 allTests(Test::TestHelper* helper)
77 {
78 Ice::CommunicatorPtr communicator = helper->communicator();
79 cout << "testing stringToProxy... " << flush;
80 string ref = "hold:" + helper->getTestEndpoint();
81 Ice::ObjectPrxPtr base = communicator->stringToProxy(ref);
82 test(base);
83 string refSerialized = "hold:" + helper->getTestEndpoint(1);
84 Ice::ObjectPrxPtr baseSerialized = communicator->stringToProxy(refSerialized);
85 test(base);
86 cout << "ok" << endl;
87
88 cout << "testing checked cast... " << flush;
89 HoldPrxPtr hold = ICE_CHECKED_CAST(HoldPrx, base);
90 test(hold);
91 #ifdef ICE_CPP11_MAPPING
92 test(Ice::targetEqualTo(hold, base));
93 #else
94 test(hold == base);
95 #endif
96 HoldPrxPtr holdSerialized = ICE_CHECKED_CAST(HoldPrx, baseSerialized);
97 test(holdSerialized);
98
99 #ifdef ICE_CPP11_MAPPING
100 test(Ice::targetEqualTo(holdSerialized, baseSerialized));
101 #else
102 test(holdSerialized == baseSerialized);
103 #endif
104 cout << "ok" << endl;
105
106 cout << "changing state between active and hold rapidly... " << flush;
107 for(int i = 0; i < 100; ++i)
108 {
109 hold->putOnHold(0);
110 }
111 for(int i = 0; i < 100; ++i)
112 {
113 hold->ice_oneway()->putOnHold(0);
114 }
115 for(int i = 0; i < 100; ++i)
116 {
117 holdSerialized->putOnHold(0);
118 }
119 for(int i = 0; i < 100; ++i)
120 {
121 holdSerialized->ice_oneway()->putOnHold(0);
122 }
123 cout << "ok" << endl;
124
125 cout << "testing without serialize mode... " << flush;
126 {
127 ConditionPtr cond = new Condition(true);
128 int value = 0;
129 #ifdef ICE_CPP11_MAPPING
130 shared_ptr<promise<void>> completed;
131 while(cond->value())
132 {
133 completed = make_shared<promise<void>>();
134 auto sent = make_shared<promise<bool>>();
135 auto expected = value;
136 hold->setAsync(value + 1, IceUtilInternal::random(5),
137 [cond, expected, completed](int val)
138 {
139 if(val != expected)
140 {
141 cond->set(false);
142 }
143 completed->set_value();
144 },
145 [completed](exception_ptr)
146 {
147 completed->set_value();
148 },
149 [sent](bool sentSynchronously)
150 {
151 sent->set_value(sentSynchronously);
152 });
153
154 ++value;
155 if(value % 100 == 0)
156 {
157 sent->get_future().get();
158 }
159
160 if(value > 1000000)
161 {
162 // Don't continue, it's possible that out-of-order dispatch doesn't occur
163 // after 100000 iterations and we don't want the test to last for too long
164 // when this occurs.
165 break;
166 }
167 }
168 test(value > 100000 || !cond->value());
169 completed->get_future().get();
170 #else
171
172 Ice::AsyncResultPtr result;
173 while(cond->value())
174 {
175 result = hold->begin_set(value + 1,
176 IceUtilInternal::random(5),
177 newCallback_Hold_set(new SetCB(cond, value), &SetCB::response, &SetCB::exception));
178 ++value;
179 if(value % 100 == 0)
180 {
181 result->waitForSent();
182 }
183
184 if(value > 1000000)
185 {
186 // Don't continue, it's possible that out-of-order dispatch doesn't occur
187 // after 100000 iterations and we don't want the test to last for too long
188 // when this occurs.
189 break;
190 }
191 }
192 test(value > 100000 || !cond->value());
193 result->waitForCompleted();
194 #endif
195 }
196 cout << "ok" << endl;
197
198 cout << "testing with serialize mode... " << flush;
199 {
200 ConditionPtr cond = new Condition(true);
201 int value = 0;
202 #ifdef ICE_CPP11_MAPPING
203 shared_ptr<promise<void>> completed;
204 while(value < 3000 && cond->value())
205 {
206 completed = make_shared<promise<void>>();
207 auto sent = make_shared<promise<bool>>();
208 auto expected = value;
209 holdSerialized->setAsync(
210 value + 1,
211 IceUtilInternal::random(1),
212 [cond, expected, completed](int val)
213 {
214 if(val != expected)
215 {
216 cond->set(false);
217 }
218 completed->set_value();
219 },
220 [completed](exception_ptr)
221 {
222 completed->set_value();
223 },
224 [sent](bool sentSynchronously)
225 {
226 sent->set_value(sentSynchronously);
227 });
228 ++value;
229 if(value % 100 == 0)
230 {
231 sent->get_future().get();
232 }
233 }
234 #else
235 Ice::AsyncResultPtr result;
236 while(value < 3000 && cond->value())
237 {
238 result = holdSerialized->begin_set(value + 1,
239 IceUtilInternal::random(1),
240 newCallback_Hold_set(new SetCB(cond, value),
241 &SetCB::response,
242 &SetCB::exception));
243 ++value;
244 if(value % 100 == 0)
245 {
246 result->waitForSent();
247 }
248 }
249 result->waitForCompleted();
250 #endif
251 test(cond->value());
252 for(int i = 0; i < 10000; ++i)
253 {
254 holdSerialized->ice_oneway()->setOneway(value + 1, value);
255 ++value;
256 if((i % 100) == 0)
257 {
258 holdSerialized->ice_oneway()->putOnHold(1);
259 }
260 }
261 }
262 cout << "ok" << endl;
263
264 cout << "testing serialization... " << flush;
265 {
266 int value = 0;
267 holdSerialized->set(value, 0);
268 #ifdef ICE_CPP11_MAPPING
269 shared_ptr<promise<void>> completed;
270 for(int i = 0; i < 10000; ++i)
271 {
272 completed = make_shared<promise<void>>();
273 // Create a new proxy for each request
274 holdSerialized->ice_oneway()->setOnewayAsync(value + 1, value,
275 nullptr,
276 [](exception_ptr)
277 {
278 },
279 [completed](bool /*sentSynchronously*/)
280 {
281 completed->set_value();
282 });
283 ++value;
284 if((i % 100) == 0)
285 {
286 completed->get_future().get();
287 holdSerialized->ice_ping(); // Ensure everything's dispatched
288 holdSerialized->ice_getConnection()->close(Ice::ICE_SCOPED_ENUM(ConnectionClose, GracefullyWithWait));
289 }
290 }
291 completed->get_future().get();
292 #else
293 Ice::AsyncResultPtr result;
294 for(int i = 0; i < 10000; ++i)
295 {
296 // Create a new proxy for each request
297 result = holdSerialized->ice_oneway()->begin_setOneway(value + 1, value);
298 ++value;
299 if((i % 100) == 0)
300 {
301 result->waitForSent();
302 holdSerialized->ice_ping(); // Ensure everything's dispatched
303 holdSerialized->ice_getConnection()->close(Ice::ICE_SCOPED_ENUM(ConnectionClose, GracefullyWithWait));
304 }
305 }
306 result->waitForCompleted();
307 #endif
308 }
309 cout << "ok" << endl;
310
311 cout << "testing waitForHold... " << flush;
312 {
313 hold->waitForHold();
314 hold->waitForHold();
315 for(int i = 0; i < 1000; ++i)
316 {
317 hold->ice_oneway()->ice_ping();
318 if((i % 20) == 0)
319 {
320 hold->putOnHold(0);
321 }
322 }
323 hold->putOnHold(-1);
324 hold->ice_ping();
325 hold->putOnHold(-1);
326 hold->ice_ping();
327 }
328 cout << "ok" << endl;
329
330 cout << "changing state to hold and shutting down server... " << flush;
331 hold->shutdown();
332 cout << "ok" << endl;
333 }
334