1//
2// Copyright (c) ZeroC, Inc. All rights reserved.
3//
4
5#import <objc/Ice.h>
6#import <TestCommon.h>
7#import <BindingTest.h>
8
9#import <Foundation/Foundation.h>
10
11@interface GetAdapterNameCB : NSObject
12{
13    NSCondition* cond_;
14    NSString* name_;
15}
16-(id) init;
17#if defined(__clang__) && !__has_feature(objc_arc)
18-(void) dealloc;
19#endif
20-(void) response:(NSString*)name;
21-(void) exception:(ICEException*)ex;
22-(NSString*) getResult;
23@end
24
25@implementation GetAdapterNameCB
26-(id) init
27{
28    self = [super init];
29    if(!self)
30    {
31        return nil;
32    }
33    cond_ = [[NSCondition alloc] init];
34    name_ = nil;
35    return self;
36}
37
38#if defined(__clang__) && !__has_feature(objc_arc)
39-(void) dealloc
40{
41    [cond_ release];
42    [name_ release];
43    [super dealloc];
44}
45#endif
46
47-(void) response:(NSString*)name
48{
49    [cond_ lock];
50    name_ = ICE_RETAIN(name);
51    [cond_ signal];
52    [cond_ unlock];
53}
54-(void) exception:(ICEException*)ex
55{
56    tprintf("unexpected exception: %@", ex);
57    test(NO);
58}
59-(NSString*) getResult
60{
61    [cond_ lock];
62    @try
63    {
64        while(name_ == nil)
65        {
66            [cond_ wait];
67        }
68        return ICE_AUTORELEASE(ICE_RETAIN(name_));
69    }
70    @finally
71    {
72        [cond_ unlock];
73    }
74    return nil;
75}
76@end
77
78NSString*
79getAdapterNameWithAMI(id<TestBindingTestIntfPrx> test)
80{
81    GetAdapterNameCB* cb = ICE_AUTORELEASE([[GetAdapterNameCB alloc] init]);
82    [test begin_getAdapterName:^(NSMutableString* name) { [cb response:name]; }
83                     exception:^(ICEException* ex) { [cb exception:ex]; }];
84    return [cb getResult];
85}
86
87NSArray*
88getEndpoints(id<TestBindingTestIntfPrx> proxy)
89{
90    NSMutableArray* edpts = [NSMutableArray array];
91    bool escape = NO;
92    int beg = 0;
93    int length = 0;
94    NSString* s = [proxy ice_toString];
95    int index;
96    for(index = 0; index < (int)[s length]; ++index)
97    {
98        unichar c = [s characterAtIndex:index];
99        if(c == '"')
100        {
101            escape = !escape;
102        }
103
104        if(!escape && c == ':')
105        {
106            NSRange range = { beg, length };
107            [edpts addObject:[s substringWithRange:range]];
108            beg = beg + length + 1;
109            length = 0;
110        }
111        else
112        {
113            ++length;
114        }
115    }
116    if(length > 0)
117    {
118        NSRange range = { beg, length };
119        [edpts addObject:[s substringWithRange:range]];
120    }
121    [edpts removeObjectAtIndex:0];
122    return edpts;
123}
124
125id<TestBindingTestIntfPrx>
126createTestIntfPrx(NSArray* adapters)
127{
128    NSMutableArray* endpoints = [NSMutableArray arrayWithCapacity:[adapters count]];
129    id<TestBindingTestIntfPrx> test = nil;
130    for(id<TestBindingRemoteObjectAdapterPrx> a in adapters)
131    {
132        test = [a getTestIntf];
133        [endpoints addObjectsFromArray:getEndpoints(test)];
134    }
135    NSString* proxy = [[test ice_getCommunicator] identityToString:[test ice_getIdentity]];
136    for(NSString* e in endpoints)
137    {
138        proxy = [proxy stringByAppendingString:@":"];
139        proxy = [proxy stringByAppendingString:e];
140    }
141    return [TestBindingTestIntfPrx uncheckedCast:[[test ice_getCommunicator] stringToProxy:proxy]];
142}
143
144void
145deactivate(id<TestBindingRemoteCommunicatorPrx> com, NSArray* adapters)
146{
147    for(id<TestBindingRemoteObjectAdapterPrx> a in adapters)
148    {
149        [com deactivateObjectAdapter:a];
150    }
151}
152
153void
154random_shuffle(NSMutableArray* array)
155{
156    NSUInteger count = [array count];
157    while(count--)
158    {
159        [array exchangeObjectAtIndex:count withObjectAtIndex:(random() % (count + 1))];
160    }
161}
162
163void
164bindingAllTests(id<ICECommunicator> communicator)
165{
166    NSString* ref = @"communicator:default -p 12010";
167    id<TestBindingRemoteCommunicatorPrx> com = [TestBindingRemoteCommunicatorPrx uncheckedCast:[
168            communicator stringToProxy:ref]];
169
170    tprintf("testing binding with single endpoint... ");
171    {
172        id<TestBindingRemoteObjectAdapterPrx> adapter = [com createObjectAdapter:@"Adapter" endpoints:@"default"];
173
174        id<TestBindingTestIntfPrx> test1 = [adapter getTestIntf];
175        id<TestBindingTestIntfPrx> test2 = [adapter getTestIntf];
176        test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]);
177
178        [test1 ice_ping];
179        [test2 ice_ping];
180
181        [com deactivateObjectAdapter:adapter];
182
183        id<TestBindingTestIntfPrx> test3 = [TestBindingTestIntfPrx uncheckedCast:test1];
184        test([[test3 ice_getConnection] isEqual:[test1 ice_getConnection]]);
185        test([[test3 ice_getConnection] isEqual:[test2 ice_getConnection]]);
186
187        @try
188        {
189            [test3 ice_ping];
190            test(NO);
191        }
192        @catch(ICEConnectionRefusedException*)
193        {
194        }
195    }
196    tprintf("ok\n");
197
198    tprintf("testing binding with multiple endpoints... ");
199    {
200        NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3];
201        [adapters addObject:[com createObjectAdapter:@"Adapter11" endpoints:@"default"]];
202        [adapters addObject:[com createObjectAdapter:@"Adapter12" endpoints:@"default"]];
203        [adapters addObject:[com createObjectAdapter:@"Adapter13" endpoints:@"default"]];
204
205        //
206        // Ensure that when a connection is opened it's reused for new
207        // proxies and that all endpoints are eventually tried.
208        //
209        NSMutableSet* names = [NSMutableSet setWithCapacity:3];
210        [names addObject:@"Adapter11"];
211        [names addObject:@"Adapter12"];
212        [names addObject:@"Adapter13"];
213        while([names count] != 0)
214        {
215            NSMutableArray* adpts = ICE_AUTORELEASE([adapters mutableCopy]);
216
217            id<TestBindingTestIntfPrx> test1 = createTestIntfPrx(adpts);
218            random_shuffle(adpts);
219            id<TestBindingTestIntfPrx> test2 = createTestIntfPrx(adpts);
220            random_shuffle(adpts);
221            id<TestBindingTestIntfPrx> test3 = createTestIntfPrx(adpts);
222
223            test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]);
224            test([[test2 ice_getConnection] isEqual:[test3 ice_getConnection]]);
225
226            [names removeObject:[test1 getAdapterName]];
227            [[test1 ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
228        }
229
230        //
231        // Ensure that the proxy correctly caches the connection (we
232        // always send the request over the same connection.)
233        //
234        {
235            for(id<TestBindingRemoteObjectAdapterPrx> a in adapters)
236            {
237                [[a getTestIntf] ice_ping];
238            }
239
240            id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters);
241            NSString* name = [test getAdapterName];
242            const int nRetry = 10;
243            int i;
244            for(i = 0; i < nRetry &&  [[test getAdapterName] isEqualToString:name]; i++);
245            test(i == nRetry);
246
247            for(id<TestBindingRemoteObjectAdapterPrx> a in adapters)
248            {
249                [[[a getTestIntf] ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
250            }
251        }
252
253        //
254        // Deactivate an adapter and ensure that we can still
255        // establish the connection to the remaining adapters.
256        //
257        [com deactivateObjectAdapter:[adapters objectAtIndex:0]];
258        [names addObject:@"Adapter12"];
259        [names addObject:@"Adapter13"];
260        while([names count] != 0)
261        {
262            NSMutableArray* adpts = ICE_AUTORELEASE([adapters mutableCopy]);
263
264            id<TestBindingTestIntfPrx> test1 = createTestIntfPrx(adpts);
265            random_shuffle(adpts);
266            id<TestBindingTestIntfPrx> test2 = createTestIntfPrx(adpts);
267            random_shuffle(adpts);
268            id<TestBindingTestIntfPrx> test3 = createTestIntfPrx(adpts);
269
270            test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]);
271            test([[test2 ice_getConnection] isEqual:[test3 ice_getConnection]]);
272
273            [names removeObject:[test1 getAdapterName]];
274            [[test1 ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
275        }
276
277        //
278        // Deactivate an adapter and ensure that we can still
279        // establish the connection to the remaining adapter.
280        //
281        [com deactivateObjectAdapter:[adapters objectAtIndex:2]];
282        id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters);
283        test([[test getAdapterName] isEqualToString:@"Adapter12"]);
284
285        deactivate(com, adapters);
286    }
287    tprintf("ok\n");
288
289    tprintf("testing binding with multiple endpoints and AMI... ");
290    {
291        NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3];
292        [adapters addObject:[com createObjectAdapter:@"AdapterAMI11" endpoints:@"default"]];
293        [adapters addObject:[com createObjectAdapter:@"AdapterAMI12" endpoints:@"default"]];
294        [adapters addObject:[com createObjectAdapter:@"AdapterAMI13" endpoints:@"default"]];
295
296        //
297        // Ensure that when a connection is opened it's reused for new
298        // proxies and that all endpoints are eventually tried.
299        //
300        NSMutableSet* names = [NSMutableSet setWithCapacity:3];
301        [names addObject:@"AdapterAMI11"];
302        [names addObject:@"AdapterAMI12"];
303        [names addObject:@"AdapterAMI13"];
304        while([names count] != 0)
305        {
306            NSMutableArray* adpts = ICE_AUTORELEASE([adapters mutableCopy]);
307
308            id<TestBindingTestIntfPrx> test1 = createTestIntfPrx(adpts);
309            random_shuffle(adpts);
310            id<TestBindingTestIntfPrx> test2 = createTestIntfPrx(adpts);
311            random_shuffle(adpts);
312            id<TestBindingTestIntfPrx> test3 = createTestIntfPrx(adpts);
313
314            test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]);
315            test([[test2 ice_getConnection] isEqual:[test3 ice_getConnection]]);
316
317            [names removeObject:getAdapterNameWithAMI(test1)];
318            [[test1 ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
319        }
320
321        //
322        // Ensure that the proxy correctly caches the connection (we
323        // always send the request over the same connection.)
324        //
325        {
326            for(id<TestBindingRemoteObjectAdapterPrx> a in adapters)
327            {
328                [[a getTestIntf] ice_ping];
329            }
330
331            id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters);
332            NSString* name = getAdapterNameWithAMI(test);
333            const int nRetry = 10;
334            int i;
335            for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:name]; i++);
336            test(i == nRetry);
337
338            for(id<TestBindingRemoteObjectAdapterPrx> a in adapters)
339            {
340                [[[a getTestIntf] ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
341            }
342        }
343
344        //
345        // Deactivate an adapter and ensure that we can still
346        // establish the connection to the remaining adapters.
347        //
348        [com deactivateObjectAdapter:[adapters objectAtIndex:0]];
349        [names addObject:@"AdapterAMI12"];
350        [names addObject:@"AdapterAMI13"];
351        while([names count] != 0)
352        {
353            NSMutableArray* adpts = ICE_AUTORELEASE([adapters mutableCopy]);
354
355            id<TestBindingTestIntfPrx> test1 = createTestIntfPrx(adpts);
356            random_shuffle(adpts);
357            id<TestBindingTestIntfPrx> test2 = createTestIntfPrx(adpts);
358            random_shuffle(adpts);
359            id<TestBindingTestIntfPrx> test3 = createTestIntfPrx(adpts);
360
361            test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]);
362            test([[test2 ice_getConnection] isEqual:[test3 ice_getConnection]]);
363
364            [names removeObject:[test1 getAdapterName]];
365            [[test1 ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
366        }
367
368        //
369        // Deactivate an adapter and ensure that we can still
370        // establish the connection to the remaining adapter.
371        //
372        [com deactivateObjectAdapter:[adapters objectAtIndex:2]];
373        id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters);
374        test([[test getAdapterName] isEqualToString:@"AdapterAMI12"]);
375
376        deactivate(com, adapters);
377    }
378    tprintf("ok\n");
379
380    tprintf("testing random endpoint selection... ");
381    {
382        NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3];
383        [adapters addObject:[com createObjectAdapter:@"Adapter21" endpoints:@"default"]];
384        [adapters addObject:[com createObjectAdapter:@"Adapter22" endpoints:@"default"]];
385        [adapters addObject:[com createObjectAdapter:@"Adapter23" endpoints:@"default"]];
386
387        id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters);
388        test([test ice_getEndpointSelection] == ICERandom);
389
390        NSMutableSet* names = [NSMutableSet setWithCapacity:3];
391        [names addObject:@"Adapter21"];
392        [names addObject:@"Adapter22"];
393        [names addObject:@"Adapter23"];
394        while([names count] != 0)
395        {
396            [names removeObject:[test getAdapterName]];
397            [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
398        }
399
400        test = [TestBindingTestIntfPrx uncheckedCast:[test ice_endpointSelection:ICERandom]];
401        test([test ice_getEndpointSelection] == ICERandom);
402
403        [names addObject:@"Adapter21"];
404        [names addObject:@"Adapter22"];
405        [names addObject:@"Adapter23"];
406        while([names count] != 0)
407        {
408            [names removeObject:[test getAdapterName]];
409            [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
410        }
411
412        deactivate(com, adapters);
413    }
414    tprintf("ok\n");
415
416    tprintf("testing ordered endpoint selection... ");
417    {
418        NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3];
419        [adapters addObject:[com createObjectAdapter:@"Adapter31" endpoints:@"default"]];
420        [adapters addObject:[com createObjectAdapter:@"Adapter32" endpoints:@"default"]];
421        [adapters addObject:[com createObjectAdapter:@"Adapter33" endpoints:@"default"]];
422
423        id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters);
424        test = [TestBindingTestIntfPrx uncheckedCast:[test ice_endpointSelection:ICEOrdered]];
425        test([test ice_getEndpointSelection] == ICEOrdered);
426        const int nRetry = 5;
427        int i;
428
429        //
430        // Ensure that endpoints are tried in order by deactiving the adapters
431        // one after the other.
432        //
433        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter31"]; i++);
434#if TARGET_OS_IPHONE > 0
435        if(i != nRetry)
436        {
437            [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
438            for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter31"]; i++);
439        }
440#endif
441        test(i == nRetry);
442        [com deactivateObjectAdapter:[adapters objectAtIndex:0]];
443        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter32"]; i++);
444#if TARGET_OS_IPHONE > 0
445        if(i != nRetry)
446        {
447            [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
448            for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter32"]; i++);
449        }
450#endif
451        test(i == nRetry);
452        [com deactivateObjectAdapter:[adapters objectAtIndex:1]];
453        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter33"]; i++);
454#if TARGET_OS_IPHONE > 0
455        if(i != nRetry)
456        {
457            [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
458            for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter33"]; i++);
459        }
460#endif
461        test(i == nRetry);
462        [com deactivateObjectAdapter:[adapters objectAtIndex:2]];
463
464        @try
465        {
466            [test getAdapterName];
467        }
468        @catch(ICEConnectionRefusedException*)
469        {
470        }
471
472        NSArray* endpoints = getEndpoints(test);
473
474        adapters = [NSMutableArray arrayWithCapacity:3];
475
476        //
477        // Now, re-activate the adapters with the same endpoints in the opposite
478        // order.
479        //
480        [adapters addObject:[com createObjectAdapter:@"Adapter36" endpoints:[endpoints objectAtIndex:2]]];
481        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter36"]; i++);
482#if TARGET_OS_IPHONE > 0
483        if(i != nRetry)
484        {
485            [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
486            for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter36"]; i++);
487        }
488#endif
489        test(i == nRetry);
490        [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
491        [adapters addObject:[com createObjectAdapter:@"Adapter35" endpoints:[endpoints objectAtIndex:1]]];
492        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter35"]; i++);
493#if TARGET_OS_IPHONE > 0
494        if(i != nRetry)
495        {
496            [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
497            for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter35"]; i++);
498        }
499#endif
500        test(i == nRetry);
501        [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
502        [adapters addObject:[com createObjectAdapter:@"Adapter34" endpoints:[endpoints objectAtIndex:0]]];
503        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter34"]; i++);
504#if TARGET_OS_IPHONE > 0
505        if(i != nRetry)
506        {
507            [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
508            for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter34"]; i++);
509        }
510#endif
511        test(i == nRetry);
512        deactivate(com, adapters);
513    }
514    tprintf("ok\n");
515
516    tprintf("testing per request binding with single endpoint... ");
517    {
518        id<TestBindingRemoteObjectAdapterPrx> adapter = [com createObjectAdapter:@"Adapter41" endpoints:@"default"];
519
520        id<TestBindingTestIntfPrx> test1 = [TestBindingTestIntfPrx uncheckedCast:[[adapter getTestIntf] ice_connectionCached:NO]];
521        id<TestBindingTestIntfPrx> test2 = [TestBindingTestIntfPrx uncheckedCast:[[adapter getTestIntf] ice_connectionCached:NO]];
522        test(![test1 ice_isConnectionCached]);
523        test(![test2 ice_isConnectionCached]);
524        test([test1 ice_getConnection] && [test2 ice_getConnection]);
525        test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]);
526
527        [test1 ice_ping];
528
529        [com deactivateObjectAdapter:adapter];
530
531        id<TestBindingTestIntfPrx> test3 = [TestBindingTestIntfPrx uncheckedCast:test1];
532        @try
533        {
534            test([[test3 ice_getConnection] isEqual:[test1 ice_getConnection]]);
535            test(NO);
536        }
537        @catch(ICEConnectionRefusedException*)
538        {
539        }
540    }
541    tprintf("ok\n");
542
543    tprintf("testing per request binding with multiple endpoints... ");
544    {
545        NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3];
546        [adapters addObject:[com createObjectAdapter:@"Adapter51" endpoints:@"default"]];
547        [adapters addObject:[com createObjectAdapter:@"Adapter52" endpoints:@"default"]];
548        [adapters addObject:[com createObjectAdapter:@"Adapter53" endpoints:@"default"]];
549
550        id<TestBindingTestIntfPrx> test = [createTestIntfPrx(adapters) ice_connectionCached:NO];
551        test(![test ice_isConnectionCached]);
552
553        NSMutableSet* names = [NSMutableSet setWithCapacity:3];
554        [names addObject:@"Adapter51"];
555        [names addObject:@"Adapter52"];
556        [names addObject:@"Adapter53"];
557        while([names count] != 0)
558        {
559            [names removeObject:[test getAdapterName]];
560        }
561
562        [com deactivateObjectAdapter:[adapters objectAtIndex:0]];
563
564        [names addObject:@"Adapter52"];
565        [names addObject:@"Adapter53"];
566        while([names count] != 0)
567        {
568            [names removeObject:[test getAdapterName]];
569        }
570
571        [com deactivateObjectAdapter:[adapters objectAtIndex:2]];
572
573        test([[test getAdapterName] isEqualToString:@"Adapter52"]);
574
575        deactivate(com, adapters);
576    }
577    tprintf("ok\n");
578
579    tprintf("testing per request binding with multiple endpoints and AMI... ");
580    {
581        NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3];
582        [adapters addObject:[com createObjectAdapter:@"AdapterAMI51" endpoints:@"default"]];
583        [adapters addObject:[com createObjectAdapter:@"AdapterAMI52" endpoints:@"default"]];
584        [adapters addObject:[com createObjectAdapter:@"AdapterAMI53" endpoints:@"default"]];
585
586        id<TestBindingTestIntfPrx> test = [createTestIntfPrx(adapters) ice_connectionCached:NO];
587        test(![test ice_isConnectionCached]);
588
589        NSMutableSet* names = [NSMutableSet setWithCapacity:3];
590        [names addObject:@"AdapterAMI51"];
591        [names addObject:@"AdapterAMI52"];
592        [names addObject:@"AdapterAMI53"];
593        while([names count] != 0)
594        {
595            [names removeObject:getAdapterNameWithAMI(test)];
596        }
597
598        [com deactivateObjectAdapter:[adapters objectAtIndex:0]];
599
600        [names addObject:@"AdapterAMI52"];
601        [names addObject:@"AdapterAMI53"];
602        while([names count] != 0)
603        {
604            [names removeObject:getAdapterNameWithAMI(test)];
605        }
606
607        [com deactivateObjectAdapter:[adapters objectAtIndex:2]];
608
609        test([[test getAdapterName] isEqualToString:@"AdapterAMI52"]);
610
611        deactivate(com, adapters);
612    }
613    tprintf("ok\n");
614
615    tprintf("testing per request binding and ordered endpoint selection... ");
616    {
617        NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3];
618        [adapters addObject:[com createObjectAdapter:@"Adapter61" endpoints:@"default"]];
619        [adapters addObject:[com createObjectAdapter:@"Adapter62" endpoints:@"default"]];
620        [adapters addObject:[com createObjectAdapter:@"Adapter63" endpoints:@"default"]];
621
622        id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters);
623        test = [TestBindingTestIntfPrx uncheckedCast:[test ice_endpointSelection:ICEOrdered]];
624        test([test ice_getEndpointSelection] == ICEOrdered);
625        test = [TestBindingTestIntfPrx uncheckedCast:[test ice_connectionCached:NO]];
626        test(![test ice_isConnectionCached]);
627        const int nRetry = 5;
628        int i;
629
630        //
631        // Ensure that endpoints are tried in order by deactiving the adapters
632        // one after the other.
633        //
634        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter61"]; i++);
635#if TARGET_OS_IPHONE > 0
636        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
637#else
638        test(i == nRetry);
639#endif
640        [com deactivateObjectAdapter:[adapters objectAtIndex:0]];
641        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter62"]; i++);
642#if TARGET_OS_IPHONE > 0
643        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
644#else
645        test(i == nRetry);
646#endif
647        [com deactivateObjectAdapter:[adapters objectAtIndex:1]];
648        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter63"]; i++);
649#if TARGET_OS_IPHONE > 0
650        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
651#else
652        test(i == nRetry);
653#endif
654        [com deactivateObjectAdapter:[adapters objectAtIndex:2]];
655
656        @try
657        {
658            [test getAdapterName];
659        }
660        @catch(ICEConnectionRefusedException*)
661        {
662        }
663
664        NSArray* endpoints = getEndpoints(test);
665
666        adapters = [NSMutableArray arrayWithCapacity:3];
667
668        //
669        // Now, re-activate the adapters with the same endpoints in the opposite
670        // order.
671        //
672        [adapters addObject:[com createObjectAdapter:@"Adapter66" endpoints:[endpoints objectAtIndex:2]]];
673        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter66"]; i++);
674#if TARGET_OS_IPHONE > 0
675        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
676#else
677        test(i == nRetry);
678#endif
679        [adapters addObject:[com createObjectAdapter:@"Adapter65" endpoints:[endpoints objectAtIndex:1]]];
680        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter65"]; i++);
681#if TARGET_OS_IPHONE > 0
682        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
683#else
684        test(i == nRetry);
685#endif
686        [adapters addObject:[com createObjectAdapter:@"Adapter64" endpoints:[endpoints objectAtIndex:0]]];
687        for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter64"]; i++);
688#if TARGET_OS_IPHONE > 0
689        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
690#else
691        test(i == nRetry);
692#endif
693
694        deactivate(com, adapters);
695    }
696    tprintf("ok\n");
697
698    tprintf("testing per request binding and ordered endpoint selection and AMI... ");
699    {
700        NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3];
701        [adapters addObject:[com createObjectAdapter:@"AdapterAMI61" endpoints:@"default"]];
702        [adapters addObject:[com createObjectAdapter:@"AdapterAMI62" endpoints:@"default"]];
703        [adapters addObject:[com createObjectAdapter:@"AdapterAMI63" endpoints:@"default"]];
704
705        id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters);
706        test = [TestBindingTestIntfPrx uncheckedCast:[test ice_endpointSelection:ICEOrdered]];
707        test([test ice_getEndpointSelection] == ICEOrdered);
708        test = [TestBindingTestIntfPrx uncheckedCast:[test ice_connectionCached:NO]];
709        test(![test ice_isConnectionCached]);
710        const int nRetry = 5;
711        int i;
712
713        //
714        // Ensure that endpoints are tried in order by deactiving the adapters
715        // one after the other.
716        //
717        for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI61"]; i++);
718#if TARGET_OS_IPHONE > 0
719        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
720#else
721        test(i == nRetry);
722#endif
723        [com deactivateObjectAdapter:[adapters objectAtIndex:0]];
724        for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI62"]; i++);
725#if TARGET_OS_IPHONE > 0
726        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
727#else
728        test(i == nRetry);
729#endif
730        [com deactivateObjectAdapter:[adapters objectAtIndex:1]];
731        for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI63"]; i++);
732#if TARGET_OS_IPHONE > 0
733        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
734#else
735        test(i == nRetry);
736#endif
737        [com deactivateObjectAdapter:[adapters objectAtIndex:2]];
738
739        @try
740        {
741            [test getAdapterName];
742        }
743        @catch(ICEConnectionRefusedException*)
744        {
745        }
746
747        NSArray* endpoints = getEndpoints(test);
748
749        adapters = [NSMutableArray arrayWithCapacity:3];
750
751        //
752        // Now, re-activate the adapters with the same endpoints in the opposite
753        // order.
754        //
755        [adapters addObject:[com createObjectAdapter:@"AdapterAMI66" endpoints:[endpoints objectAtIndex:2]]];
756        for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI66"]; i++);
757#if TARGET_OS_IPHONE > 0
758        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
759#else
760        test(i == nRetry);
761#endif
762        [adapters addObject:[com createObjectAdapter:@"AdapterAMI65" endpoints:[endpoints objectAtIndex:1]]];
763        for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI65"]; i++);
764#if TARGET_OS_IPHONE > 0
765        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
766#else
767        test(i == nRetry);
768#endif
769        [adapters addObject:[com createObjectAdapter:@"AdapterAMI64" endpoints:[endpoints objectAtIndex:0]]];
770        for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI64"]; i++);
771#if TARGET_OS_IPHONE > 0
772        test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang.
773#else
774        test(i == nRetry);
775#endif
776
777        deactivate(com, adapters);
778    }
779    tprintf("ok\n");
780
781    tprintf("testing endpoint mode filtering... ");
782    {
783        NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3];
784        [adapters addObject:[com createObjectAdapter:@"Adapter71" endpoints:@"default"]];
785        [adapters addObject:[com createObjectAdapter:@"Adapter72" endpoints:@"udp"]];
786
787        id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters);
788        test([[test getAdapterName] isEqualToString:@"Adapter71"]);
789
790        id<TestBindingTestIntfPrx> testUDP = [TestBindingTestIntfPrx uncheckedCast:[test ice_datagram]];
791        test([test ice_getConnection] != [testUDP ice_getConnection]);
792        @try
793        {
794            [testUDP getAdapterName];
795        }
796        @catch(ICETwowayOnlyException*)
797        {
798        }
799    }
800    tprintf("ok\n");
801
802    if([[[communicator getProperties] getProperty:@"Ice.Default.Protocol"] isEqual:@"ssl"])
803    {
804        tprintf("testing unsecure vs. secure endpoints... ");
805        {
806            NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3];
807            [adapters addObject:[com createObjectAdapter:@"Adapter81" endpoints:@"ssl"]];
808            [adapters addObject:[com createObjectAdapter:@"Adapter82" endpoints:@"tcp"]];
809
810            id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters);
811            int i;
812            for(i = 0; i < 5; i++)
813            {
814                test([[test getAdapterName] isEqualToString:@"Adapter82"]);
815                [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
816            }
817
818            id<TestBindingTestIntfPrx> testSecure = [TestBindingTestIntfPrx uncheckedCast:[test ice_secure:YES]];
819            test([testSecure ice_isSecure]);
820            testSecure = [TestBindingTestIntfPrx uncheckedCast:[test ice_secure:NO]];
821            test(![testSecure ice_isSecure]);
822            testSecure = [TestBindingTestIntfPrx uncheckedCast:[test ice_secure:YES]];
823            test([testSecure ice_isSecure]);
824            test([test ice_getConnection] != [testSecure ice_getConnection]);
825
826            [com deactivateObjectAdapter:[adapters objectAtIndex:1]];
827
828            for(i = 0; i < 5; i++)
829            {
830                test([[test getAdapterName] isEqualToString:@"Adapter81"]);
831                [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
832            }
833
834            [com createObjectAdapter:@"Adapter83" endpoints:[getEndpoints(test) objectAtIndex:1]]; // Reactive tcp OA.
835
836            for(i = 0; i < 5; i++)
837            {
838                test([[test getAdapterName] isEqualToString:@"Adapter83"]);
839                [[test ice_getConnection] close:ICEConnectionCloseGracefullyWithWait];
840            }
841
842            [com deactivateObjectAdapter:[adapters objectAtIndex:0]];
843            @try
844            {
845                [testSecure ice_ping];
846                test(NO);
847            }
848            @catch(ICEConnectionRefusedException*)
849            {
850            }
851
852            deactivate(com, adapters);
853        }
854        tprintf("ok\n");
855    }
856
857    [com shutdown];
858}
859