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