1//
2// Copyright (c) ZeroC, Inc. All rights reserved.
3//
4
5#import <objc/Ice.h>
6#import <TestCommon.h>
7#import <OptionalTest.h>
8
9#import <Foundation/Foundation.h>
10
11@interface TestObjectReader : ICEObject
12{
13}
14@end
15
16@implementation TestObjectReader
17-(void) iceRead:(id<ICEInputStream>)is
18{
19    [is startValue];
20    [is startSlice];
21    [is endSlice];
22    [is endValue:NO];
23}
24@end
25
26@interface BObjectReader : ICEObject
27{
28}
29@end
30
31@implementation BObjectReader
32-(void) iceRead:(id<ICEInputStream>)is
33{
34    [is startValue];
35    // ::Test::B
36    [is startSlice];
37    [is readInt];
38    [is endSlice];
39    // ::Test::A
40    [is startSlice];
41    [is readInt];
42    [is endSlice];
43    [is endValue:NO];
44};
45@end
46
47@interface CObjectReader : ICEObject
48{
49}
50@end
51
52@implementation CObjectReader
53-(void) iceRead:(id<ICEInputStream>)is
54{
55    [is startValue];
56    // ::Test::C
57    [is startSlice];
58    [is skipSlice];
59    // ::Test::B
60    [is startSlice];
61    [is readInt];
62    [is endSlice];
63    // ::Test::A
64    [is startSlice];
65    [is readInt];
66    [is endSlice];
67    [is endValue:NO];
68};
69@end
70
71@interface DObjectWriter : ICEObject
72{
73}
74@end
75
76@implementation DObjectWriter
77-(void) iceWrite:(id<ICEOutputStream>)os
78{
79    [os startValue:0];
80    // ::Test::D
81    [os startSlice:@"::Test::D" compactId:-1 lastSlice:NO];
82    [os writeString:@"test"];
83    if([os writeOptional:1 format:ICEOptionalFormatVSize])
84    {
85        ICEMutableStringSeq* o = [ICEMutableStringSeq array];
86        [o addObject:@"test1"];
87        [o addObject:@"test2"];
88        [o addObject:@"test3"];
89        [o addObject:@"test4"];
90        [ICEStringSeqHelper write:o stream:os];
91    }
92    if([os writeOptional:1000 format:ICEOptionalFormatClass])
93    {
94        TestOptionalA* a = [TestOptionalA a];
95        a.mc = 18;
96        [os writeValue:a];
97    }
98    [os endSlice];
99    // ::Test::B
100    [os startSlice:@"::Test::B" compactId:-1 lastSlice:NO];
101    [os writeInt:14];
102    [os endSlice];
103    // ::Test::A
104    [os startSlice:@"::Test::A" compactId:-1 lastSlice:YES];
105    [os writeInt:14];
106    [os endSlice];
107    [os endValue];
108}
109@end
110
111@interface DObjectReader : ICEObject
112{
113    TestOptionalA* a_;
114}
115@end
116
117@implementation DObjectReader
118#if defined(__clang__) && !__has_feature(objc_arc)
119-(void) dealloc
120{
121    [a_ release];
122    [super dealloc];
123}
124#endif
125-(void) iceRead:(id<ICEInputStream>)is
126{
127    [is startValue];
128    // ::Test::D
129    [is startSlice];
130    NSString* s = [is readString];
131    test([s isEqualToString:@"test"]);
132    test([is readOptional:1 format:ICEOptionalFormatVSize]);
133    NSMutableArray* o = [ICEStringSeqHelper read:is];
134    test(o != nil && [o count] == 4 &&
135         [[o objectAtIndex:0] isEqualToString:@"test1"] &&
136         [[o objectAtIndex:1] isEqualToString:@"test2"] &&
137         [[o objectAtIndex:2] isEqualToString:@"test3"] &&
138         [[o objectAtIndex:3] isEqualToString:@"test4"]);
139    test([is readOptional:1000 format:ICEOptionalFormatClass]);
140    [is newValue:(ICEObject**)&a_ expectedType:[TestOptionalA class]];
141    [is endSlice];
142
143    // ::Test::B
144    [is startSlice];
145    [is readInt];
146    [is endSlice];
147    // ::Test::A
148    [is startSlice];
149    [is readInt];
150    [is endSlice];
151    [is endValue:NO];
152}
153-(void) check
154{
155    test(a_.mc == 18);
156}
157@end
158
159@interface FObjectReader : ICEObject
160{
161    TestOptionalF* f_;
162}
163@end
164
165@implementation FObjectReader
166-(id) init
167{
168    self = [super init];
169    if(self)
170    {
171        f_ = nil;
172    }
173    return self;
174}
175
176-(void) iceRead:(id<ICEInputStream>)is
177{
178    if(f_ != nil)
179    {
180        ICE_RELEASE(f_);
181    }
182    f_ = [TestOptionalF new];
183    [is startValue];
184    [is startSlice];
185    // Don't read optional af on purpose
186    //[is_ readValue:(ICEObject**)&self->af expectedType:[TestOptionalA class]];
187    [is endSlice];
188    [is startSlice];
189    TestOptionalA* ICE_AUTORELEASING_QUALIFIER ae;
190    [is readValue:(ICEObject**)&ae expectedType:[TestOptionalA class]];
191    [is endSlice];
192    [is endValue:NO];
193    f_.ae = ae;
194}
195
196#if defined(__clang__) && !__has_feature(objc_arc)
197-(void) dealloc
198{
199    [f_ release];
200    [super dealloc];
201}
202#endif
203
204-(TestOptionalF*) getF
205{
206    return f_;
207}
208@end
209
210@interface FactoryI : ICEObject
211{
212    BOOL enabled_;
213}
214+(FactoryI*) factoryI;
215-(void) setEnabled:(BOOL)enabled;
216@end
217
218@implementation FactoryI
219+(FactoryI*) factoryI
220{
221    return ICE_AUTORELEASE([[FactoryI alloc] init]);
222}
223-(id) init
224{
225    self = [super init];
226    if(self)
227    {
228        self->enabled_ = NO;
229    }
230    return self;
231}
232-(ICEObject*) create:(NSString*)typeId
233{
234    if(!enabled_)
235    {
236        return nil;
237    }
238    if([typeId isEqualToString:@"::Test::OneOptional"])
239    {
240        return [TestObjectReader new];
241    }
242    else if([typeId isEqualToString:@"::Test::MultiOptional"])
243    {
244        return [TestObjectReader new];
245    }
246    else if([typeId isEqualToString:@"::Test::B"])
247    {
248        return [BObjectReader new];
249    }
250    else if([typeId isEqualToString:@"::Test::C"])
251    {
252        return [CObjectReader new];
253    }
254    else if([typeId isEqualToString:@"::Test::D"])
255    {
256        return [DObjectReader new];
257    }
258    else if([typeId isEqualToString:@"::Test::F"])
259    {
260        return [FObjectReader new];
261    }
262
263    return nil;
264}
265-(void) setEnabled:(BOOL)enabled
266{
267    self->enabled_ = enabled;
268}
269@end
270
271id<TestOptionalInitialPrx>
272optionalAllTests(id<ICECommunicator> communicator)
273{
274    FactoryI* factory = [FactoryI factoryI];
275#if defined(__clang__) && __has_feature(objc_arc)
276    [[communicator getValueFactoryManager] add:^(id s) NS_RETURNS_RETAINED { return [factory create:s]; } sliceId:@""];
277#else
278    [[communicator getValueFactoryManager] add:^(id s) { return [factory create:s]; } sliceId:@""];
279#endif
280    tprintf("testing stringToProxy... ");
281    NSString* sref = @"initial:default -p 12010";
282    id<ICEObjectPrx> base = [communicator stringToProxy:sref];
283    test(base);
284    tprintf("ok\n");
285
286    tprintf("testing checked cast... ");
287    id<TestOptionalInitialPrx> initial = [TestOptionalInitialPrx checkedCast:base];
288    test(initial != nil);
289    test([initial isEqual:base]);
290    tprintf("ok\n");
291
292    tprintf("testing constructor, copy constructor, and assignment operator... ");
293
294    TestOptionalOneOptional* oo1 = [TestOptionalOneOptional oneOptional];
295    test(![oo1 hasA]);
296    oo1.a = 15;
297    test([oo1 hasA] && oo1.a == 15);
298
299    TestOptionalOneOptional* oo2 = [TestOptionalOneOptional oneOptional:@16];
300    test([oo2 hasA] && oo2.a == 16);
301
302    TestOptionalOneOptional* oon = [TestOptionalOneOptional oneOptional:ICENone];
303    test(![oon hasA]);
304
305    TestOptionalMultiOptional* mo1 = [TestOptionalMultiOptional multiOptional];
306    mo1.a = 15;
307    mo1.b = true;
308    mo1.c = 19;
309    mo1.d = 78;
310    mo1.e = 99;
311    mo1.f = 5.5f;
312    mo1.g = 1.0;
313    mo1.h = @"test";
314    mo1.i = TestOptionalMyEnumMember;
315    mo1.j = [TestOptionalMultiOptionalPrx uncheckedCast:[communicator stringToProxy:@"test"]];
316    //mo1.k = mo1;
317    ICEByte bsa[] = { 0x05 };
318    mo1.bs = [TestOptionalByteSeq dataWithBytes:bsa length:1];
319    mo1.ss = [TestOptionalStringSeq arrayWithObjects:@"test", @"test2", nil];
320    mo1.iid = [TestOptionalIntIntDict dictionaryWithObjectsAndKeys:@3, @4, nil];
321    mo1.sid = [TestOptionalStringIntDict dictionaryWithObjectsAndKeys:@10, @"test", nil];
322    TestOptionalFixedStruct* fs = [TestOptionalFixedStruct fixedStruct];
323    fs.m = 78;
324    mo1.fs = fs;
325    TestOptionalVarStruct* vs = [TestOptionalVarStruct varStruct];
326    vs.m = @"hello";
327    mo1.vs = vs;
328
329    ICEShort shs[] = { 1 };
330    mo1.shs = [TestOptionalShortSeq dataWithBytes:shs length:sizeof(shs)];
331
332    TestOptionalMyEnum es[] = { TestOptionalMyEnumMember, TestOptionalMyEnumMember };
333    mo1.es = [TestOptionalMyEnumSeq dataWithBytes:es length:sizeof(es)];
334    mo1.fss = [TestOptionalFixedStructSeq arrayWithObject:fs];
335    mo1.vss = [TestOptionalVarStructSeq arrayWithObject:vs];
336    mo1.oos = [TestOptionalOneOptionalSeq arrayWithObject:oo1];
337    id<TestOptionalOneOptionalPrx> oneOptionalProxy =
338        [TestOptionalOneOptionalPrx uncheckedCast:[communicator stringToProxy:@"test"]];
339    mo1.oops = [TestOptionalOneOptionalPrxSeq arrayWithObject:oneOptionalProxy];
340    mo1.ied = [TestOptionalIntEnumDict dictionaryWithObjectsAndKeys:@(TestOptionalMyEnumMember), @4, nil];
341    mo1.ifsd = [TestOptionalIntFixedStructDict dictionaryWithObjectsAndKeys:fs, @4, nil];
342    mo1.ivsd = [TestOptionalIntVarStructDict dictionaryWithObjectsAndKeys:vs, @4, nil];
343    mo1.iood = [TestOptionalIntOneOptionalDict dictionaryWithObjectsAndKeys:[TestOptionalOneOptional oneOptional:@15],
344                                               @5, nil];
345    mo1.ioopd = [TestOptionalIntOneOptionalPrxDict dictionaryWithObjectsAndKeys:oneOptionalProxy, @5, nil];
346    BOOL bos[] = { NO, YES, NO };
347    mo1.bos = [TestOptionalBoolSeq dataWithBytes:bos length:sizeof(bos)];
348
349    TestOptionalMultiOptional* mo3 = ICE_AUTORELEASE([mo1 copy]);
350    test(mo3.a == 15);
351    test(mo3.b == YES);
352    test(mo3.c == 19);
353    test(mo3.d == 78);
354    test(mo3.e == 99);
355    test(mo3.f == 5.5f);
356    test(mo3.g == 1.0);
357    test([mo3.h isEqualToString:@"test"]);
358    test(mo3.i == TestOptionalMyEnumMember);
359    test([mo3.j isEqual:[TestOptionalMultiOptionalPrx uncheckedCast:[communicator stringToProxy:@"test"]]]);
360    //test(mo3.k == mo1);
361    test(mo3.bs == mo1.bs);
362    test(mo3.ss == mo1.ss);
363    test(mo3.iid == mo1.iid);
364    test(mo3.sid == mo1.sid);
365    test(mo3.fs == mo1.fs);
366    test(mo3.vs == mo1.vs);
367
368    test(mo3.shs == mo1.shs);
369    test(mo3.es == mo1.es);
370    test(mo3.fss == mo1.fss);
371    test(mo3.vss == mo1.vss);
372    test(mo3.oos == mo1.oos);
373    test(mo3.oops == mo1.oops);
374
375    test(mo3.ied == mo1.ied);
376    test(mo3.ifsd == mo1.ifsd);
377    test(mo3.ivsd == mo1.ivsd);
378    test(mo3.iood == mo1.iood);
379    test(mo3.ioopd == mo1.ioopd);
380
381    test(mo3.bos == mo1.bos);
382
383    tprintf("ok\n");
384
385//     tprintf("testing comparison operators... ");
386
387//     test(mo1->a == 15 && 15 == mo1->a && mo1->a != 16 && 16 != mo1->a);
388//     test(mo1->a < 16 && mo1->a > 14 && mo1->a <= 15 && mo1->a >= 15 && mo1->a <= 16 && mo1->a >= 14);
389//     test(mo1->a > IceUtil::Optional<int>() && IceUtil::Optional<int>() < mo1->a);
390//     test(14 > IceUtil::Optional<int>() && IceUtil::Optional<int>() < 14);
391
392//     test(mo1->h == "test" && "test" == mo1->h && mo1->h != "testa" && "testa" != mo1->h);
393//     test(mo1->h < "test1" && mo1->h > "tesa" && mo1->h <= "test");
394//     test(mo1->h >= "test" && mo1->h <= "test1" && mo1->h >= "tesa");
395//     test(mo1->h > IceUtil::Optional<string>() && IceUtil::Optional<string>() < mo1->h);
396//     test("test1" > IceUtil::Optional<string>() && IceUtil::Optional<string>() < "test1");
397
398//     tprintf("ok\n");
399
400    tprintf("testing marshalling... ");
401    TestOptionalOneOptional* oo4 = (TestOptionalOneOptional*)[initial pingPong:[TestOptionalOneOptional oneOptional]];
402    test(![oo4 hasA]);
403
404    TestOptionalOneOptional* oo5 = (TestOptionalOneOptional*)[initial pingPong:oo1];
405    test(oo1.a == oo5.a);
406
407    TestOptionalMultiOptional* mo4 = (TestOptionalMultiOptional*)
408        [initial pingPong:[TestOptionalMultiOptional multiOptional]];
409    test(![mo4 hasA]);
410    test(![mo4 hasB]);
411    test(![mo4 hasC]);
412    test(![mo4 hasD]);
413    test(![mo4 hasE]);
414    test(![mo4 hasF]);
415    test(![mo4 hasG]);
416    test(![mo4 hasH]);
417    test(![mo4 hasI]);
418    test(![mo4 hasJ]);
419    test(![mo4 hasK]);
420    test(![mo4 hasBs]);
421    test(![mo4 hasSs]);
422    test(![mo4 hasIid]);
423    test(![mo4 hasSid]);
424    test(![mo4 hasFs]);
425    test(![mo4 hasVs]);
426
427    test(![mo4 hasShs]);
428    test(![mo4 hasEs]);
429    test(![mo4 hasFss]);
430    test(![mo4 hasVss]);
431    test(![mo4 hasOos]);
432    test(![mo4 hasOops]);
433
434    test(![mo4 hasIed]);
435    test(![mo4 hasIfsd]);
436    test(![mo4 hasIvsd]);
437    test(![mo4 hasIood]);
438    test(![mo4 hasIoopd]);
439
440    test(![mo4 hasBos]);
441
442    //mo1.k = mo1;
443    TestOptionalMultiOptional* mo5 = (TestOptionalMultiOptional*)[initial pingPong:mo1];
444    test(mo5.a == mo1.a);
445    test(mo5.b == mo1.b);
446    test(mo5.c == mo1.c);
447    test(mo5.d == mo1.d);
448    test(mo5.e == mo1.e);
449    test(mo5.f == mo1.f);
450    test(mo5.g == mo1.g);
451    test([mo5.h isEqualToString:mo1.h]);
452    test(mo5.i == mo1.i);
453    test([mo5.j isEqual:mo1.j]);
454    //test(mo5.k == mo5);
455    test([mo5.bs isEqual:mo1.bs]);
456    test([mo5.ss isEqual:mo1.ss]);
457    test([mo5.iid isEqual: mo1.iid]);
458    test([mo5.sid isEqual:mo1.sid]);
459    test([mo5.fs isEqual:mo1.fs]);
460    test([mo5.vs isEqual:mo1.vs]);
461
462    test([mo5.shs isEqual:mo1.shs]);
463    test([mo5.es isEqual:mo1.es]);
464    test([mo5.fss isEqual:mo1.fss]);
465    test([mo5.vss isEqual:mo1.vss]);
466    test([mo5.oos count] > 0 && ((TestOptionalOneOptional*)[mo5.oos objectAtIndex:0]).a == oo1.a);
467    test([mo5.oops isEqual:mo1.oops]);
468
469    test([mo5.ied isEqual:mo1.ied]);
470    test([mo5.ifsd isEqual:mo1.ifsd]);
471    test([mo5.ivsd isEqual:mo1.ivsd]);
472    test([mo5.iood count] > 0 && ((TestOptionalOneOptional*)[mo5.iood objectForKey:@5]).a == 15);
473    test([mo5.ioopd isEqual:mo1.ioopd]);
474
475    test([mo5.bos isEqual:mo1.bos]);
476
477    // Clear the first half of the optional parameters
478    TestOptionalMultiOptional* mo6 = ICE_AUTORELEASE([mo5 copy]);
479    [mo6 clearA];
480    [mo6 clearC];
481    [mo6 clearE];
482    [mo6 clearG];
483    [mo6 clearI];
484    [mo6 clearK];
485    [mo6 clearSs];
486    [mo6 clearSid];
487    [mo6 clearVs];
488
489    [mo6 clearEs];
490    [mo6 clearVss];
491    [mo6 clearOops];
492
493    [mo6 clearIed];
494    [mo6 clearIvsd];
495    [mo6 clearIoopd];
496
497    TestOptionalMultiOptional* mo7 = (TestOptionalMultiOptional*)[initial pingPong:mo6];
498    test(![mo7 hasA]);
499    test(mo7.b == mo1.b);
500    test(![mo7 hasC]);
501    test(mo7.d == mo1.d);
502    test(![mo7 hasE]);
503    test(mo7.f == mo1.f);
504    test(![mo7 hasG]);
505    test([mo7.h isEqual:mo1.h]);
506    test(![mo7 hasI]);
507    test([mo7.j isEqual:mo1.j]);
508    test(![mo7 hasK]);
509    test([mo7.bs isEqual:mo1.bs]);
510    test(![mo7 hasSs]);
511    test([mo7.iid isEqual:mo1.iid]);
512    test(![mo7 hasSid]);
513    test([mo7.fs isEqual:mo1.fs]);
514    test(![mo7 hasVs]);
515
516    test([mo7.shs isEqual:mo1.shs]);
517    test(![mo7 hasEs]);
518    test([mo7.fss isEqual:mo1.fss]);
519    test(![mo7 hasVss]);
520    test([mo7.oos count] > 0 && ((TestOptionalOneOptional*)[mo7.oos objectAtIndex:0]).a == oo1.a);
521    test(![mo7 hasOops]);
522
523    test(![mo7 hasIed]);
524    test([mo7.ifsd isEqual:mo1.ifsd]);
525    test(![mo7 hasIvsd]);
526    test([mo7.iood count] > 0 && ((TestOptionalOneOptional*)[mo7.iood objectForKey:@5]).a == 15);
527    test(![mo7 hasIoopd]);
528
529    // Clear the second half of the optional parameters
530    TestOptionalMultiOptional* mo8 = ICE_AUTORELEASE([mo5 copy]);
531    [mo8 clearB];
532    [mo8 clearD];
533    [mo8 clearF];
534    [mo8 clearH];
535    [mo8 clearJ];
536    [mo8 clearBs];
537    [mo8 clearIid];
538    [mo8 clearFs];
539
540    [mo8 clearShs];
541    [mo8 clearFss];
542    [mo8 clearOos];
543
544    [mo8 clearIfsd];
545    [mo8 clearIood];
546
547    TestOptionalMultiOptional* mo9 = (TestOptionalMultiOptional*)[initial pingPong:mo8];
548    test(mo9.a == mo1.a);
549    test(![mo9 hasB]);
550    test(mo9.c == mo1.c);
551    test(![mo9 hasD]);
552    test(mo9.e == mo1.e);
553    test(![mo9 hasF]);
554    test(mo9.g == mo1.g);
555    test(![mo9 hasH]);
556    test(mo9.i == mo1.i);
557    test(![mo9 hasJ]);
558    //test(mo9.k == mo9.k);
559    test(![mo9 hasBs]);
560    test([mo9.ss isEqual:mo1.ss]);
561    test(![mo9 hasIid]);
562    test([mo9.sid isEqual:mo1.sid]);
563    test(![mo9 hasFs]);
564    test([mo9.vs isEqual:mo1.vs]);
565
566    test(![mo8 hasShs]);
567    test([mo8.es isEqual:mo1.es]);
568    test(![mo8 hasFss]);
569    test([mo8.vss isEqual:mo1.vss]);
570    test(![mo8 hasOos]);
571    test([mo8.oops isEqual:mo1.oops]);
572
573    test([mo8.ied isEqual:mo1.ied]);
574    test(![mo8 hasIfsd]);
575    test([mo8.ivsd isEqual:mo1.ivsd]);
576    test(![mo8 hasIood]);
577
578    //
579    // Send a request using blobjects. Upon receival, we don't read
580    // any of the optional members. This ensures the optional members
581    // are skipped even if the receiver knows nothing about them.
582    //
583    [factory setEnabled:YES];
584    id<ICEOutputStream> os = [ICEUtil createOutputStream:communicator];
585    [os startEncapsulation];
586    [os writeValue:oo1];
587    [os endEncapsulation];
588    ICEByteSeq* inEncaps = [os finished];
589    ICEMutableByteSeq* outEncaps;
590    test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]);
591    id<ICEInputStream> is = [ICEUtil createInputStream:communicator data:outEncaps];
592    [is startEncapsulation];
593    ICEObject* obj;
594    [is readValue:&obj];
595    [is endEncapsulation];
596    test(obj != nil && [obj isKindOfClass:[TestObjectReader class]]);
597
598    os = [ICEUtil createOutputStream:communicator];
599    [os startEncapsulation];
600    [os writeValue:mo1];
601    [os endEncapsulation];
602    inEncaps = [os finished];
603    test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]);
604    is = [ICEUtil createInputStream:communicator data:outEncaps];
605    [is startEncapsulation];
606    [is readValue:&obj];
607    [is endEncapsulation];
608    test(obj != nil && [obj isKindOfClass:[TestObjectReader class]]);
609    [factory setEnabled:false];
610
611    //
612    // Use the 1.0 encoding with operations whose only class parameters are optional.
613    //
614    id oo = [TestOptionalOneOptional oneOptional:@53];
615    [initial sendOptionalClass:YES o:oo];
616    [[initial ice_encodingVersion:ICEEncoding_1_0] sendOptionalClass:YES o:oo];
617
618    [initial returnOptionalClass:YES o:&oo];
619    test(oo != nil && oo != ICENone);
620    [[initial ice_encodingVersion:ICEEncoding_1_0] returnOptionalClass:YES o:&oo];
621    test(oo == ICENone);
622
623    TestOptionalG* g = [TestOptionalG g];
624    g.gg1 = [TestOptionalG1 g1:@"g1"];
625    g.gg1Opt = [TestOptionalG1 g1:@"g1opt"];
626    g.gg2 = [TestOptionalG2 g2:10];
627    g.gg2Opt = [TestOptionalG2 g2:20];
628    TestOptionalG* r = [initial opG:g];
629
630    test([r.gg1.a isEqualToString:@"g1"]);
631    test([r.gg1Opt.a isEqualToString:@"g1opt"]);
632    test(r.gg2.a == 10);
633    test(r.gg2Opt.a == 20);
634
635    os = [ICEUtil createOutputStream:communicator];
636    [os startEncapsulation];
637    [ICEIntHelper writeOptional:@15 stream:os tag:1];
638    [ICEStringHelper writeOptional:@"test" stream:os tag:2];
639    [os endEncapsulation];
640    inEncaps = [os finished];
641    test([initial ice_invoke:@"opVoid" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]);
642
643    tprintf("ok\n");
644
645    tprintf("testing marshalling of large containers with fixed size elements...");
646    TestOptionalMultiOptional* mc = [TestOptionalMultiOptional multiOptional];
647
648    mc.bs = [TestOptionalMutableByteSeq dataWithLength:1000];
649    mc.shs = [TestOptionalMutableShortSeq dataWithLength:300 * sizeof(ICEShort)];
650    mc.fss = [TestOptionalMutableFixedStructSeq array];
651    for(int i = 0; i < 300; ++i)
652    {
653        [(TestOptionalMutableFixedStructSeq*)mc.fss addObject:[TestOptionalFixedStruct fixedStruct]];
654    }
655
656    mc.ifsd = [TestOptionalMutableIntFixedStructDict dictionary];
657    for(int i = 0; i < 300; ++i)
658    {
659        [(TestOptionalMutableIntFixedStructDict*)mc.ifsd setObject:[TestOptionalFixedStruct fixedStruct] forKey:@(i)];
660    }
661
662    mc = (TestOptionalMultiOptional*)[initial pingPong:mc];
663    test([mc.bs length] == 1000);
664    test([mc.shs length] == 300 * sizeof(ICEShort));
665    test([mc.fss count] == 300);
666    test([mc.ifsd count] == 300);
667
668    [factory setEnabled:YES];
669    os = [ICEUtil createOutputStream:communicator];
670    [os startEncapsulation];
671    [os writeValue:mc];
672    [os endEncapsulation];
673    inEncaps = [os finished];
674
675    test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]);
676    is = [ICEUtil createInputStream:communicator data:outEncaps];
677    [is startEncapsulation];
678    [is readValue:&obj];
679    [is endEncapsulation];
680    test(obj != nil && [obj isKindOfClass:[TestObjectReader class]]);
681    [factory setEnabled:NO];
682
683    tprintf("ok\n");
684
685    tprintf("testing tag marshalling... ");
686    TestOptionalB* b1 = [TestOptionalB b];
687    TestOptionalB* b2 = (TestOptionalB*)[initial pingPong:b1];
688    test(![b2 hasMa]);
689    test(![b2 hasMb]);
690    test(![b2 hasMc]);
691
692    b1.ma = 10;
693    b1.mb = 11;
694    b1.mc = 12;
695    b1.md = 13;
696
697    b2 = (TestOptionalB*)[initial pingPong:b1];
698    test(b2.ma == 10);
699    test(b2.mb == 11);
700    test(b2.mc == 12);
701    test(b2.md == 13);
702
703    [factory setEnabled:YES];
704    os = [ICEUtil createOutputStream:communicator];
705    [os startEncapsulation];
706    [os writeValue:b1];
707    [os endEncapsulation];
708    inEncaps = [os finished];
709    test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]);
710    is = [ICEUtil createInputStream:communicator data:outEncaps];
711    [is startEncapsulation];
712    [is readValue:&obj];
713    [is endEncapsulation];
714    test(obj != nil);
715    [factory setEnabled:NO];
716
717    tprintf("ok\n");
718
719    tprintf("testing marshalling of objects with optional objects...");
720    {
721        TestOptionalF* f = [TestOptionalF f];
722
723        f.af = [TestOptionalA a];
724        f.ae = f.af;
725
726        TestOptionalF* rf = (TestOptionalF*)[initial pingPong:f];
727        test(rf.ae == rf.af);
728
729        [factory setEnabled:YES];
730        os = [ICEUtil createOutputStream:communicator];
731        [os startEncapsulation];
732        [os writeValue:f];
733        [os endEncapsulation];
734        inEncaps = [os finished];
735        is = [ICEUtil createInputStream:communicator data:inEncaps];
736        [is startEncapsulation];
737        [is readValue:&obj];
738        [is endEncapsulation];
739        [factory setEnabled:NO];
740
741        test(obj != nil && [obj isKindOfClass:[FObjectReader class]]);
742        rf = [(FObjectReader*)obj getF];
743        test(rf.ae != nil && ![rf hasAf]);
744    }
745    tprintf("ok\n");
746
747    tprintf("testing optional with default values... ");
748    TestOptionalWD* wd = (TestOptionalWD*)[initial pingPong:[TestOptionalWD wd]];
749    test(wd.a == 5);
750    test([wd.s isEqualToString:@"test"]);
751    [wd clearA];
752    [wd clearS];
753    wd = (TestOptionalWD*)[initial pingPong:wd];
754    test(![wd hasA]);
755    test(![wd hasS]);
756    tprintf("ok\n");
757
758    if([[communicator getProperties] getPropertyAsInt:@"Ice.Default.SlicedFormat"] > 0)
759    {
760        tprintf("testing marshalling with unknown class slices... ");
761        {
762            TestOptionalC* c = [TestOptionalC c];
763            c.ss = @"test";
764            c.ms = @"testms";
765            os = [ICEUtil createOutputStream:communicator];
766            [os startEncapsulation];
767            [os writeValue:c];
768            [os endEncapsulation];
769            inEncaps = [os finished];
770            [factory setEnabled:YES];
771            test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]);
772            is = [ICEUtil createInputStream:communicator data:outEncaps];
773            [is startEncapsulation];
774            [is readValue:&obj];
775            [is endEncapsulation];
776            test(obj != nil && [obj isKindOfClass:[CObjectReader class]]);
777            [factory setEnabled:NO];
778
779            [factory setEnabled:YES];
780            os = [ICEUtil createOutputStream:communicator];
781            [os startEncapsulation];
782            ICEObject* d = [DObjectWriter new];
783            [os writeValue:d];
784            ICE_RELEASE(d);
785            [os endEncapsulation];
786            inEncaps = [os finished];
787            test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]);
788            is = [ICEUtil createInputStream:communicator data:outEncaps];
789            [is startEncapsulation];
790            [is readValue:&obj];
791            [is endEncapsulation];
792            test(obj != nil && [obj isKindOfClass:[DObjectReader class]]);
793            [(DObjectReader*)obj check];
794            [factory setEnabled:NO];
795        }
796        tprintf("ok\n");
797
798        tprintf("testing optionals with unknown classes...");
799        {
800            TestOptionalA* a = [TestOptionalA a];
801
802            os = [ICEUtil createOutputStream:communicator];
803            [os startEncapsulation];
804            [os writeValue:a];
805            DObjectWriter* writer = [DObjectWriter new];
806            [ICEObjectHelper writeOptional:writer stream:os tag:1];
807            ICE_RELEASE(writer);
808            [os endEncapsulation];
809            inEncaps = [os finished];
810            test([initial ice_invoke:@"opClassAndUnknownOptional" mode:ICENormal inEncaps:inEncaps
811                           outEncaps:&outEncaps]);
812            is = [ICEUtil createInputStream:communicator data:outEncaps];
813            [is startEncapsulation];
814            [is endEncapsulation];
815        }
816        tprintf("ok\n");
817    }
818
819    tprintf("testing optional parameters... ");
820    {
821        id p1 = ICENone;
822        id p3 = ICENone;
823        id p2 = [initial opByte:p1 p3:&p3];
824        test(p2 == ICENone && p3 == ICENone);
825
826        p1 = @0x56;
827        p2 = [initial opByte:p1 p3:&p3];
828        test([p2 isEqual:@0x56] && [p3 isEqual:@0x56]);
829
830        os = [ICEUtil createOutputStream:communicator];
831        [os startEncapsulation];
832        [ICEByteHelper writeOptional:p1 stream:os tag:2];
833        [os endEncapsulation];
834        inEncaps = [os finished];
835        [initial ice_invoke:@"opByte" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
836        is = [ICEUtil createInputStream:communicator data:outEncaps];
837        [is startEncapsulation];
838        p2 = [ICEByteHelper readOptional:is tag:1];
839        p3 = [ICEByteHelper readOptional:is tag:3];
840
841        id p4 = @0x08;
842        p4 = [ICEByteHelper readOptional:is tag:89];
843
844        [is endEncapsulation];
845        test([p2 isEqual:@0x56] && [p3 isEqual:@0x56] && [p4 isEqual:ICENone]);
846
847        is = [ICEUtil createInputStream:communicator data:outEncaps];
848        [is startEncapsulation];
849        [is endEncapsulation];
850    }
851
852    {
853        id p1 = ICENone;
854        id p3 = ICENone;
855        id p2 = [initial opBool:p1 p3:&p3];
856        test(p2 == ICENone && p3 == ICENone);
857
858        p1 = @YES;
859        p2 = [initial opBool:p1 p3:&p3];
860        test([p2 isEqual:@YES] && [p3 isEqual:@YES]);
861
862        os = [ICEUtil createOutputStream:communicator];
863        [os startEncapsulation];
864        [ICEBoolHelper writeOptional:p1 stream:os tag:2];
865        [os endEncapsulation];
866        inEncaps = [os finished];
867        [initial ice_invoke:@"opBool" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
868        is = [ICEUtil createInputStream:communicator data:outEncaps];
869        [is startEncapsulation];
870        p2 = [ICEBoolHelper readOptional:is tag:1];
871        p3 = [ICEBoolHelper readOptional:is tag:3];
872        [is endEncapsulation];
873        test([p2 isEqual:@YES] && [p3 isEqual:@YES]);
874
875        is = [ICEUtil createInputStream:communicator data:outEncaps];
876        [is startEncapsulation];
877        [is endEncapsulation];
878    }
879
880    {
881        id p1 = ICENone;
882        id p3 = ICENone;
883        id p2 = [initial opShort:p1 p3:&p3];
884        test(p2 == ICENone && p3 == ICENone);
885
886        p1 = @56;
887        p2 = [initial opShort:p1 p3:&p3];
888        test([p2 isEqual:@56] && [p3 isEqual:@56]);
889
890        os = [ICEUtil createOutputStream:communicator];
891        [os startEncapsulation];
892        [ICEShortHelper writeOptional:p1 stream:os tag:2];
893        [os endEncapsulation];
894        inEncaps = [os finished];
895        [initial ice_invoke:@"opShort" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
896        is = [ICEUtil createInputStream:communicator data:outEncaps];
897        [is startEncapsulation];
898        p2 = [ICEShortHelper readOptional:is tag:1];
899        p3 = [ICEShortHelper readOptional:is tag:3];
900        [is endEncapsulation];
901        test([p2 isEqual:@56] && [p3 isEqual:@56]);
902
903        is = [ICEUtil createInputStream:communicator data:outEncaps];
904        [is startEncapsulation];
905        [is endEncapsulation];
906    }
907
908    {
909        id p1 = ICENone;
910        id p3 = ICENone;
911        id p2 = [initial opInt:p1 p3:&p3];
912        test(p2 == ICENone && p3 == ICENone);
913
914        p1 = @56;
915        p2 = [initial opInt:p1 p3:&p3];
916        test([p2 isEqual:@56] && [p3 isEqual:@56]);
917
918        os = [ICEUtil createOutputStream:communicator];
919        [os startEncapsulation];
920        [ICEIntHelper writeOptional:p1 stream:os tag:2];
921        [os endEncapsulation];
922        inEncaps = [os finished];
923        [initial ice_invoke:@"opInt" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
924        is = [ICEUtil createInputStream:communicator data:outEncaps];
925        [is startEncapsulation];
926        p2 = [ICEIntHelper readOptional:is tag:1];
927        p3 = [ICEIntHelper readOptional:is tag:3];
928        [is endEncapsulation];
929        test([p2 isEqual:@56] && [p3 isEqual:@56]);
930
931        is = [ICEUtil createInputStream:communicator data:outEncaps];
932        [is startEncapsulation];
933        [is endEncapsulation];
934    }
935
936    {
937        id p1 = ICENone;
938        id p3 = ICENone;
939        id p2 = [initial opLong:p1 p3:&p3];
940        test(p2 == ICENone && p3 == ICENone);
941
942        p1 = @56;
943        p2 = [initial opLong:p1 p3:&p3];
944        test([p2 isEqual:@56] && [p3 isEqual:@56]);
945
946        os = [ICEUtil createOutputStream:communicator];
947        [os startEncapsulation];
948        [ICELongHelper writeOptional:p1 stream:os tag:1];
949        [os endEncapsulation];
950        inEncaps = [os finished];
951        [initial ice_invoke:@"opLong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
952        is = [ICEUtil createInputStream:communicator data:outEncaps];
953        [is startEncapsulation];
954        p3 = [ICELongHelper readOptional:is tag:2];
955        p2 = [ICELongHelper readOptional:is tag:3];
956        [is endEncapsulation];
957        test([p2 isEqual:@56] && [p3 isEqual:@56]);
958
959        is = [ICEUtil createInputStream:communicator data:outEncaps];
960        [is startEncapsulation];
961        [is endEncapsulation];
962    }
963
964    {
965        id p1 = ICENone;
966        id p3 = ICENone;
967        id p2 = [initial opFloat:p1 p3:&p3];
968        test(p2 == ICENone && p3 == ICENone);
969
970        p1 = @1.0f;
971        p2 = [initial opFloat:p1 p3:&p3];
972        test([p2 isEqual:@1.0f] && [p3 isEqual:@1.0f]);
973
974        os = [ICEUtil createOutputStream:communicator];
975        [os startEncapsulation];
976        [ICEFloatHelper writeOptional:p1 stream:os tag:2];
977        [os endEncapsulation];
978        inEncaps = [os finished];
979        [initial ice_invoke:@"opFloat" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
980        is = [ICEUtil createInputStream:communicator data:outEncaps];
981        [is startEncapsulation];
982        p3 = [ICEFloatHelper readOptional:is tag:1];
983        p2 = [ICEFloatHelper readOptional:is tag:3];
984        [is endEncapsulation];
985        test([p2 isEqual:@1.0f] && [p3 isEqual:@1.0f]);
986
987        is = [ICEUtil createInputStream:communicator data:outEncaps];
988        [is startEncapsulation];
989        [is endEncapsulation];
990    }
991
992    {
993        id p1 = ICENone;
994        id p3 = ICENone;
995        id p2 = [initial opDouble:p1 p3:&p3];
996        test(p2 == ICENone && p3 == ICENone);
997
998        p1 = @1.0;
999        p2 = [initial opDouble:p1 p3:&p3];
1000        test([p2 isEqual:@1.0] && [p3 isEqual:@1.0]);
1001
1002        os = [ICEUtil createOutputStream:communicator];
1003        [os startEncapsulation];
1004        [ICEDoubleHelper writeOptional:p1 stream:os tag:2];
1005        [os endEncapsulation];
1006        inEncaps = [os finished];
1007        [initial ice_invoke:@"opDouble" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1008        is = [ICEUtil createInputStream:communicator data:outEncaps];
1009        [is startEncapsulation];
1010        p3 = [ICEDoubleHelper readOptional:is tag:1];
1011        p2 = [ICEDoubleHelper readOptional:is tag:3];
1012        [is endEncapsulation];
1013        test([p2 isEqual:@1.0] && [p3 isEqual:@1.0]);
1014
1015        is = [ICEUtil createInputStream:communicator data:outEncaps];
1016        [is startEncapsulation];
1017        [is endEncapsulation];
1018    }
1019
1020    {
1021        id p1 = ICENone;
1022        id p3 = ICENone;
1023        id p2 = [initial opString:p1 p3:&p3];
1024        test(p2 == ICENone && p3 == ICENone);
1025
1026        p1 = @"test";
1027        p2 = [initial opString:p1 p3:&p3];
1028        test([p2 isEqualToString:@"test"] && [p3 isEqualToString:@"test"]);
1029
1030        os = [ICEUtil createOutputStream:communicator];
1031        [os startEncapsulation];
1032        [ICEStringHelper writeOptional:p1 stream:os tag:2];
1033        [os endEncapsulation];
1034        inEncaps = [os finished];
1035        [initial ice_invoke:@"opString" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1036        is = [ICEUtil createInputStream:communicator data:outEncaps];
1037        [is startEncapsulation];
1038        p2 = [ICEStringHelper readOptional:is tag:1];
1039        p3 = [ICEStringHelper readOptional:is tag:3];
1040        [is endEncapsulation];
1041        test([p2 isEqualToString:@"test"] && [p3 isEqualToString:@"test"]);
1042
1043        is = [ICEUtil createInputStream:communicator data:outEncaps];
1044        [is startEncapsulation];
1045        [is endEncapsulation];
1046    }
1047
1048   {
1049        id p1 = ICENone;
1050        id p3 = ICENone;
1051        id p2 = [initial opMyEnum:p1 p3:&p3];
1052        test(p2 == ICENone && p3 == ICENone);
1053
1054        p1 = @(TestOptionalMyEnumMember);
1055        p2 = [initial opMyEnum:p1 p3:&p3];
1056        test([p2 isEqual:@(TestOptionalMyEnumMember)] && [p3 isEqual:@(TestOptionalMyEnumMember)]);
1057
1058        os = [ICEUtil createOutputStream:communicator];
1059        [os startEncapsulation];
1060        [TestOptionalMyEnumHelper writeOptional:p1 stream:os tag:2];
1061        [os endEncapsulation];
1062        inEncaps = [os finished];
1063        [initial ice_invoke:@"opMyEnum" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1064        is = [ICEUtil createInputStream:communicator data:outEncaps];
1065        [is startEncapsulation];
1066        p2 = [TestOptionalMyEnumHelper readOptional:is tag:1];
1067        p3 = [TestOptionalMyEnumHelper readOptional:is tag:3];
1068        [is endEncapsulation];
1069        test([p2 isEqual:@(TestOptionalMyEnumMember)] && [p3 isEqual:@(TestOptionalMyEnumMember)]);
1070
1071        is = [ICEUtil createInputStream:communicator data:outEncaps];
1072        [is startEncapsulation];
1073        [is endEncapsulation];
1074    }
1075
1076    {
1077        id p1 = ICENone;
1078        id p3 = ICENone;
1079        id p2 = [initial opSmallStruct:p1 p3:&p3];
1080        test(p2 == ICENone && p3 == ICENone);
1081
1082        p1 = [TestOptionalSmallStruct smallStruct:56];
1083        p2 = [initial opSmallStruct:p1 p3:&p3];
1084        test(((TestOptionalSmallStruct*)p2).m == 56 && ((TestOptionalSmallStruct*)p3).m== 56);
1085
1086        os = [ICEUtil createOutputStream:communicator];
1087        [os startEncapsulation];
1088        [TestOptionalSmallStructHelper writeOptional:p1 stream:os tag:2];
1089        [os endEncapsulation];
1090        inEncaps = [os finished];
1091        [initial ice_invoke:@"opSmallStruct" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1092        is = [ICEUtil createInputStream:communicator data:outEncaps];
1093        [is startEncapsulation];
1094        p2 = [TestOptionalSmallStructHelper readOptional:is tag:1];
1095        p3 = [TestOptionalSmallStructHelper readOptional:is tag:3];
1096        [is endEncapsulation];
1097        test(((TestOptionalSmallStruct*)p2).m == 56 && ((TestOptionalSmallStruct*)p3).m== 56);
1098
1099        is = [ICEUtil createInputStream:communicator data:outEncaps];
1100        [is startEncapsulation];
1101        [is endEncapsulation];
1102    }
1103
1104    {
1105        id p1 = ICENone;
1106        id p3 = ICENone;
1107        id p2 = [initial opFixedStruct:p1 p3:&p3];
1108        test(p2 == ICENone && p3 == ICENone);
1109
1110        p1 = [TestOptionalFixedStruct fixedStruct:56];
1111        p2 = [initial opFixedStruct:p1 p3:&p3];
1112        test(((TestOptionalFixedStruct*)p2).m == 56 && ((TestOptionalFixedStruct*)p3).m== 56);
1113
1114        os = [ICEUtil createOutputStream:communicator];
1115        [os startEncapsulation];
1116        [TestOptionalFixedStructHelper writeOptional:p1 stream:os tag:2];
1117        [os endEncapsulation];
1118        inEncaps = [os finished];
1119        [initial ice_invoke:@"opFixedStruct" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1120        is = [ICEUtil createInputStream:communicator data:outEncaps];
1121        [is startEncapsulation];
1122        p2 = [TestOptionalFixedStructHelper readOptional:is tag:1];
1123        p3 = [TestOptionalFixedStructHelper readOptional:is tag:3];
1124        [is endEncapsulation];
1125        test(((TestOptionalFixedStruct*)p2).m == 56 && ((TestOptionalFixedStruct*)p3).m== 56);
1126
1127        is = [ICEUtil createInputStream:communicator data:outEncaps];
1128        [is startEncapsulation];
1129        [is endEncapsulation];
1130    }
1131
1132    {
1133        id p1 = ICENone;
1134        id p3 = ICENone;
1135        id p2 = [initial opVarStruct:p1 p3:&p3];
1136        test(p2 == ICENone && p3 == ICENone);
1137
1138        p1 = [TestOptionalVarStruct varStruct:@"test"];
1139        p2 = [initial opVarStruct:p1 p3:&p3];
1140        test([((TestOptionalVarStruct*)p2).m isEqual:@"test"] && [((TestOptionalVarStruct*)p3).m isEqual:@"test"]);
1141
1142        os = [ICEUtil createOutputStream:communicator];
1143        [os startEncapsulation];
1144        [TestOptionalVarStructHelper writeOptional:p1 stream:os tag:2];
1145        [os endEncapsulation];
1146        inEncaps = [os finished];
1147        [initial ice_invoke:@"opVarStruct" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1148        is = [ICEUtil createInputStream:communicator data:outEncaps];
1149        [is startEncapsulation];
1150        p2 = [TestOptionalVarStructHelper readOptional:is tag:1];
1151        p3 = [TestOptionalVarStructHelper readOptional:is tag:3];
1152        [is endEncapsulation];
1153        test([((TestOptionalVarStruct*)p2).m isEqual:@"test"] && [((TestOptionalVarStruct*)p3).m isEqual:@"test"]);
1154
1155        is = [ICEUtil createInputStream:communicator data:outEncaps];
1156        [is startEncapsulation];
1157        [is endEncapsulation];
1158    }
1159
1160    {
1161        id p1 = ICENone;
1162        id p3 = ICENone;
1163        id p2 = [initial opOneOptional:p1 p3:&p3];
1164        test(p2 == ICENone && p3 == ICENone);
1165
1166        p1 = [TestOptionalOneOptional oneOptional:@58];
1167        p2 = [initial opOneOptional:p1 p3:&p3];
1168        test([p2 isKindOfClass:[TestOptionalOneOptional class]] && [p3 isKindOfClass:[TestOptionalOneOptional class]]);
1169        test(((TestOptionalOneOptional*)p2).a == 58 && ((TestOptionalOneOptional*)p3).a == 58);
1170
1171        os = [ICEUtil createOutputStream:communicator];
1172        [os startEncapsulation];
1173        [ICEObjectHelper writeOptional:p1 stream:os tag:2];
1174        [os endEncapsulation];
1175        inEncaps = [os finished];
1176        [initial ice_invoke:@"opOneOptional" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1177        is = [ICEUtil createInputStream:communicator data:outEncaps];
1178        [is startEncapsulation];
1179        [ICEObjectHelper readOptional:&p2 stream:is tag:1];
1180        [ICEObjectHelper readOptional:&p3 stream:is tag:3];
1181        [is endEncapsulation];
1182        test([p2 isKindOfClass:[TestOptionalOneOptional class]] && [p3 isKindOfClass:[TestOptionalOneOptional class]]);
1183        test(((TestOptionalOneOptional*)p2).a == 58 && ((TestOptionalOneOptional*)p3).a == 58);
1184
1185        is = [ICEUtil createInputStream:communicator data:outEncaps];
1186        [is startEncapsulation];
1187        [is endEncapsulation];
1188    }
1189
1190    {
1191        id p1 = ICENone;
1192        id p3 = ICENone;
1193        id p2 = [initial opOneOptionalProxy:p1 p3:&p3];
1194        test(p2 == ICENone && p3 == ICENone);
1195
1196        p1 = [TestOptionalOneOptionalPrx uncheckedCast:[communicator stringToProxy:@"test"]];
1197        p2 = [initial opOneOptionalProxy:p1 p3:&p3];
1198        test([p2 isKindOfClass:[TestOptionalOneOptionalPrx class]] &&
1199             [p3 isKindOfClass:[TestOptionalOneOptionalPrx class]]);
1200        test([p2 isEqual:p1] && [p3 isEqual:p1]);
1201
1202        os = [ICEUtil createOutputStream:communicator];
1203        [os startEncapsulation];
1204        [ICEProxyHelper writeOptional:p1 stream:os tag:2];
1205        [os endEncapsulation];
1206        inEncaps = [os finished];
1207        [initial ice_invoke:@"opOneOptionalProxy" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1208        is = [ICEUtil createInputStream:communicator data:outEncaps];
1209        [is startEncapsulation];
1210        p2 = [TestOptionalOneOptionalPrxHelper readOptional:is tag:1];
1211        p3 = [TestOptionalOneOptionalPrxHelper readOptional:is tag:3];
1212        [is endEncapsulation];
1213        test([p2 isKindOfClass:[TestOptionalOneOptionalPrx class]] &&
1214             [p3 isKindOfClass:[TestOptionalOneOptionalPrx class]]);
1215        test([p2 isEqual:p1] && [p3 isEqual:p1]);
1216
1217        is = [ICEUtil createInputStream:communicator data:outEncaps];
1218        [is startEncapsulation];
1219        [is endEncapsulation];
1220    }
1221
1222    {
1223        TestOptionalF* f = [TestOptionalF f];
1224        f.af = [TestOptionalA a];
1225        f.af.requiredA = 56;
1226        f.ae = f.af;
1227
1228        os = [ICEUtil createOutputStream:communicator];
1229        [os startEncapsulation];
1230        [TestOptionalFHelper writeOptional:f stream:os tag:1];
1231        [TestOptionalFHelper writeOptional:f.ae stream:os tag:2];
1232        [os endEncapsulation];
1233        inEncaps = [os finished];
1234
1235        is = [ICEUtil createInputStream:communicator data:inEncaps];
1236        [is startEncapsulation];
1237        id a;
1238        [TestOptionalAHelper readOptional:&a stream:is tag:2];
1239        [is endEncapsulation];
1240        test(a != nil && [a isKindOfClass:[TestOptionalA class]] && ((TestOptionalA*)a).requiredA == 56);
1241    }
1242    tprintf("ok\n");
1243
1244    tprintf("testing optional parameters and sequences... ");
1245    {
1246        id p1 = ICENone;
1247        id p3 = ICENone;
1248        id p2 = [initial opByteSeq:p1 p3:&p3];
1249        test(p2 == ICENone && p3 == ICENone);
1250
1251        TestOptionalByteSeq* bs = [TestOptionalMutableByteSeq dataWithLength:100];
1252        p1 = bs;
1253        p2 = [initial opByteSeq:p1 p3:&p3];
1254        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1255
1256        os = [ICEUtil createOutputStream:communicator];
1257        [os startEncapsulation];
1258        [TestOptionalByteSeqHelper writeOptional:p1 stream:os tag:2];
1259        [os endEncapsulation];
1260        inEncaps = [os finished];
1261        [initial ice_invoke:@"opByteSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1262        is = [ICEUtil createInputStream:communicator data:outEncaps];
1263        [is startEncapsulation];
1264        p2 = [TestOptionalByteSeqHelper readOptional:is tag:1];
1265        p3 = [TestOptionalByteSeqHelper readOptional:is tag:3];
1266        [is endEncapsulation];
1267        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1268
1269        is = [ICEUtil createInputStream:communicator data:outEncaps];
1270        [is startEncapsulation];
1271        [is endEncapsulation];
1272    }
1273
1274    {
1275        id p1 = ICENone;
1276        id p3 = ICENone;
1277        id p2 = [initial opBoolSeq:p1 p3:&p3];
1278        test(p2 == ICENone && p3 == ICENone);
1279
1280        TestOptionalBoolSeq* bs = [TestOptionalMutableBoolSeq dataWithLength:100];
1281        p1 = bs;
1282        p2 = [initial opBoolSeq:p1 p3:&p3];
1283        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1284
1285        os = [ICEUtil createOutputStream:communicator];
1286        [os startEncapsulation];
1287        [TestOptionalBoolSeqHelper writeOptional:p1 stream:os tag:2];
1288        [os endEncapsulation];
1289        inEncaps = [os finished];
1290        [initial ice_invoke:@"opBoolSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1291        is = [ICEUtil createInputStream:communicator data:outEncaps];
1292        [is startEncapsulation];
1293        p2 = [TestOptionalBoolSeqHelper readOptional:is tag:1];
1294        p3 = [TestOptionalBoolSeqHelper readOptional:is tag:3];
1295        [is endEncapsulation];
1296        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1297
1298        is = [ICEUtil createInputStream:communicator data:outEncaps];
1299        [is startEncapsulation];
1300        [is endEncapsulation];
1301    }
1302
1303    {
1304        id p1 = ICENone;
1305        id p3 = ICENone;
1306        id p2 = [initial opShortSeq:p1 p3:&p3];
1307        test(p2 == ICENone && p3 == ICENone);
1308
1309        TestOptionalShortSeq* bs = [TestOptionalMutableShortSeq dataWithLength:100 * sizeof(ICEShort)];
1310        p1 = bs;
1311        p2 = [initial opShortSeq:p1 p3:&p3];
1312        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1313
1314        os = [ICEUtil createOutputStream:communicator];
1315        [os startEncapsulation];
1316        [TestOptionalShortSeqHelper writeOptional:p1 stream:os tag:2];
1317        [os endEncapsulation];
1318        inEncaps = [os finished];
1319        [initial ice_invoke:@"opShortSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1320        is = [ICEUtil createInputStream:communicator data:outEncaps];
1321        [is startEncapsulation];
1322        p2 = [TestOptionalShortSeqHelper readOptional:is tag:1];
1323        p3 = [TestOptionalShortSeqHelper readOptional:is tag:3];
1324        [is endEncapsulation];
1325        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1326
1327        is = [ICEUtil createInputStream:communicator data:outEncaps];
1328        [is startEncapsulation];
1329        [is endEncapsulation];
1330    }
1331
1332    {
1333        id p1 = ICENone;
1334        id p3 = ICENone;
1335        id p2 = [initial opIntSeq:p1 p3:&p3];
1336        test(p2 == ICENone && p3 == ICENone);
1337
1338        TestOptionalIntSeq* bs = [TestOptionalMutableIntSeq dataWithLength:100 * sizeof(ICEInt)];
1339        p1 = bs;
1340        p2 = [initial opIntSeq:p1 p3:&p3];
1341        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1342
1343        os = [ICEUtil createOutputStream:communicator];
1344        [os startEncapsulation];
1345        [TestOptionalIntSeqHelper writeOptional:p1 stream:os tag:2];
1346        [os endEncapsulation];
1347        inEncaps = [os finished];
1348        [initial ice_invoke:@"opIntSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1349        is = [ICEUtil createInputStream:communicator data:outEncaps];
1350        [is startEncapsulation];
1351        p2 = [TestOptionalIntSeqHelper readOptional:is tag:1];
1352        p3 = [TestOptionalIntSeqHelper readOptional:is tag:3];
1353        [is endEncapsulation];
1354        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1355
1356        is = [ICEUtil createInputStream:communicator data:outEncaps];
1357        [is startEncapsulation];
1358        [is endEncapsulation];
1359    }
1360
1361    {
1362        id p1 = ICENone;
1363        id p3 = ICENone;
1364        id p2 = [initial opLongSeq:p1 p3:&p3];
1365        test(p2 == ICENone && p3 == ICENone);
1366
1367        TestOptionalLongSeq* bs = [TestOptionalMutableLongSeq dataWithLength:100 * sizeof(ICELong)];
1368        p1 = bs;
1369        p2 = [initial opLongSeq:p1 p3:&p3];
1370        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1371
1372        os = [ICEUtil createOutputStream:communicator];
1373        [os startEncapsulation];
1374        [TestOptionalLongSeqHelper writeOptional:p1 stream:os tag:2];
1375        [os endEncapsulation];
1376        inEncaps = [os finished];
1377        [initial ice_invoke:@"opLongSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1378        is = [ICEUtil createInputStream:communicator data:outEncaps];
1379        [is startEncapsulation];
1380        p2 = [TestOptionalLongSeqHelper readOptional:is tag:1];
1381        p3 = [TestOptionalLongSeqHelper readOptional:is tag:3];
1382        [is endEncapsulation];
1383        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1384
1385        is = [ICEUtil createInputStream:communicator data:outEncaps];
1386        [is startEncapsulation];
1387        [is endEncapsulation];
1388    }
1389
1390    {
1391        id p1 = ICENone;
1392        id p3 = ICENone;
1393        id p2 = [initial opFloatSeq:p1 p3:&p3];
1394        test(p2 == ICENone && p3 == ICENone);
1395
1396        TestOptionalFloatSeq* bs = [TestOptionalMutableFloatSeq dataWithLength:100 * sizeof(ICEFloat)];
1397        p1 = bs;
1398        p2 = [initial opFloatSeq:p1 p3:&p3];
1399        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1400
1401        os = [ICEUtil createOutputStream:communicator];
1402        [os startEncapsulation];
1403        [TestOptionalFloatSeqHelper writeOptional:p1 stream:os tag:2];
1404        [os endEncapsulation];
1405        inEncaps = [os finished];
1406        [initial ice_invoke:@"opFloatSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1407        is = [ICEUtil createInputStream:communicator data:outEncaps];
1408        [is startEncapsulation];
1409        p2 = [TestOptionalFloatSeqHelper readOptional:is tag:1];
1410        p3 = [TestOptionalFloatSeqHelper readOptional:is tag:3];
1411        [is endEncapsulation];
1412        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1413
1414        is = [ICEUtil createInputStream:communicator data:outEncaps];
1415        [is startEncapsulation];
1416        [is endEncapsulation];
1417    }
1418
1419    {
1420        id p1 = ICENone;
1421        id p3 = ICENone;
1422        id p2 = [initial opDoubleSeq:p1 p3:&p3];
1423        test(p2 == ICENone && p3 == ICENone);
1424
1425        TestOptionalDoubleSeq* bs = [TestOptionalMutableDoubleSeq dataWithLength:100 * sizeof(ICEDouble)];
1426        p1 = bs;
1427        p2 = [initial opDoubleSeq:p1 p3:&p3];
1428        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1429
1430        os = [ICEUtil createOutputStream:communicator];
1431        [os startEncapsulation];
1432        [TestOptionalDoubleSeqHelper writeOptional:p1 stream:os tag:2];
1433        [os endEncapsulation];
1434        inEncaps = [os finished];
1435        [initial ice_invoke:@"opDoubleSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1436        is = [ICEUtil createInputStream:communicator data:outEncaps];
1437        [is startEncapsulation];
1438        p2 = [TestOptionalDoubleSeqHelper readOptional:is tag:1];
1439        p3 = [TestOptionalDoubleSeqHelper readOptional:is tag:3];
1440        [is endEncapsulation];
1441        test([p2 isEqual:bs] && [p3 isEqual:bs]);
1442
1443        is = [ICEUtil createInputStream:communicator data:outEncaps];
1444        [is startEncapsulation];
1445        [is endEncapsulation];
1446    }
1447
1448    {
1449        id p1 = ICENone;
1450        id p3 = ICENone;
1451        id p2 = [initial opStringSeq:p1 p3:&p3];
1452        test(p2 == ICENone && p3 == ICENone);
1453
1454        TestOptionalMutableStringSeq* ss = [TestOptionalMutableStringSeq array];
1455        [ss addObject:@"test1"];
1456        p1 = ss;
1457        p2 = [initial opStringSeq:p1 p3:&p3];
1458        test([p2 isEqual:ss] && [p3 isEqual:ss]);
1459
1460        os = [ICEUtil createOutputStream:communicator];
1461        [os startEncapsulation];
1462        [TestOptionalStringSeqHelper writeOptional:p1 stream:os tag:2];
1463        [os endEncapsulation];
1464        inEncaps = [os finished];
1465        [initial ice_invoke:@"opStringSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1466        is = [ICEUtil createInputStream:communicator data:outEncaps];
1467        [is startEncapsulation];
1468        p2 = [TestOptionalStringSeqHelper readOptional:is tag:1];
1469        p3 = [TestOptionalStringSeqHelper readOptional:is tag:3];
1470        [is endEncapsulation];
1471        test([p2 isEqual:ss] && [p3 isEqual:ss]);
1472
1473        is = [ICEUtil createInputStream:communicator data:outEncaps];
1474        [is startEncapsulation];
1475        [is endEncapsulation];
1476    }
1477
1478    {
1479        id p1 = ICENone;
1480        id p3 = ICENone;
1481        id p2 = [initial opFixedStructSeq:p1 p3:&p3];
1482        test(p2 == ICENone && p3 == ICENone);
1483
1484        p2 = [initial opFixedStructSeq:[TestOptionalMutableFixedStructSeq array] p3:&p3];
1485        test(p2 != nil && p3 != nil && [p2 count] == 0 && [p3 count] == 0);
1486
1487        TestOptionalMutableFixedStructSeq* fss = [TestOptionalMutableFixedStructSeq array];
1488        [fss addObject:[TestOptionalFixedStruct fixedStruct:1]];
1489        [fss addObject:[TestOptionalFixedStruct fixedStruct:2]];
1490        [fss addObject:[TestOptionalFixedStruct fixedStruct:3]];
1491        [fss addObject:[TestOptionalFixedStruct fixedStruct:4]];
1492        [fss addObject:[TestOptionalFixedStruct fixedStruct:5]];
1493        [fss addObject:[TestOptionalFixedStruct fixedStruct:6]];
1494        [fss addObject:[TestOptionalFixedStruct fixedStruct:7]];
1495        [fss addObject:[TestOptionalFixedStruct fixedStruct:8]];
1496        [fss addObject:[TestOptionalFixedStruct fixedStruct:9]];
1497        [fss addObject:[TestOptionalFixedStruct fixedStruct:10]];
1498        p1 = fss;
1499        p2 = [initial opFixedStructSeq:p1 p3:&p3];
1500        test(p2 != nil && p3 != nil);
1501        test([p2 isEqual:fss] && [p3 isEqual:fss]);
1502
1503        os = [ICEUtil createOutputStream:communicator];
1504        [os startEncapsulation];
1505        [TestOptionalFixedStructSeqHelper writeOptional:p1 stream:os tag:2];
1506        [os endEncapsulation];
1507        inEncaps = [os finished];
1508        [initial ice_invoke:@"opFixedStructSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1509        is = [ICEUtil createInputStream:communicator data:outEncaps];
1510        [is startEncapsulation];
1511        p2 = [TestOptionalFixedStructSeqHelper readOptional:is tag:1];
1512        p3 = [TestOptionalFixedStructSeqHelper readOptional:is tag:3];
1513        [is endEncapsulation];
1514        test(p2 != nil && p3 != nil);
1515        test([p2 isEqual:fss] && [p3 isEqual:fss]);
1516
1517        is = [ICEUtil createInputStream:communicator data:outEncaps];
1518        [is startEncapsulation];
1519        [is endEncapsulation];
1520    }
1521
1522    {
1523        id p1 = ICENone;
1524        id p3 = ICENone;
1525        id p2 = [initial opVarStructSeq:p1 p3:&p3];
1526        test(p2 == ICENone && p3 == ICENone);
1527
1528        p2 = [initial opVarStructSeq:[TestOptionalMutableVarStructSeq array] p3:&p3];
1529        test(p2 != nil && p3 != nil && [p2 count] == 0 && [p3 count] == 0);
1530
1531        TestOptionalMutableVarStructSeq* fss = [TestOptionalMutableVarStructSeq array];
1532        [fss addObject:[TestOptionalVarStruct varStruct:@"1"]];
1533        [fss addObject:[TestOptionalVarStruct varStruct:@"2"]];
1534        [fss addObject:[TestOptionalVarStruct varStruct:@"3"]];
1535        [fss addObject:[TestOptionalVarStruct varStruct:@"4"]];
1536        [fss addObject:[TestOptionalVarStruct varStruct:@"5"]];
1537        [fss addObject:[TestOptionalVarStruct varStruct:@"6"]];
1538        [fss addObject:[TestOptionalVarStruct varStruct:@"7"]];
1539        [fss addObject:[TestOptionalVarStruct varStruct:@"8"]];
1540        [fss addObject:[TestOptionalVarStruct varStruct:@"9"]];
1541        [fss addObject:[TestOptionalVarStruct varStruct:@"10"]];
1542        p1 = fss;
1543        p2 = [initial opVarStructSeq:p1 p3:&p3];
1544        test(p2 != nil && p3 != nil);
1545        test([p2 isEqual:fss] && [p3 isEqual:fss]);
1546
1547        os = [ICEUtil createOutputStream:communicator];
1548        [os startEncapsulation];
1549        [TestOptionalVarStructSeqHelper writeOptional:p1 stream:os tag:2];
1550        [os endEncapsulation];
1551        inEncaps = [os finished];
1552        [initial ice_invoke:@"opVarStructSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps];
1553        is = [ICEUtil createInputStream:communicator data:outEncaps];
1554        [is startEncapsulation];
1555        p2 = [TestOptionalVarStructSeqHelper readOptional:is tag:1];
1556        p3 = [TestOptionalVarStructSeqHelper readOptional:is tag:3];
1557        [is endEncapsulation];
1558        test(p2 != nil && p3 != nil);
1559        test([p2 isEqual:fss] && [p3 isEqual:fss]);
1560
1561        is = [ICEUtil createInputStream:communicator data:outEncaps];
1562        [is startEncapsulation];
1563        [is endEncapsulation];
1564    }
1565    tprintf("ok\n");
1566
1567    tprintf("testing optional parameters and dictionaries... ");
1568    {
1569        id p1 = ICENone;
1570        id p3 = ICENone;
1571        id p2 = [initial opIntIntDict:p1 p3:&p3];
1572        test(p2 == ICENone && p3 == ICENone);
1573
1574        p2 = [initial opIntIntDict:[TestOptionalIntIntDict dictionary] p3:&p3];
1575        test(p2 != nil && p3 != nil && [p2 count] == 0 && [p3 count] == 0);
1576
1577        TestOptionalMutableIntIntDict* iid = [TestOptionalMutableIntIntDict dictionary];
1578        [iid setObject:@45 forKey:@1];
1579        p1 = iid;
1580        p2 = [initial opIntIntDict:p1 p3:&p3];
1581        test(p2 != nil && p3 != nil);
1582        test([p2 isEqual:iid] && [p3 isEqual:iid]);
1583
1584        p1 = ICENone;
1585        p3 = ICENone;
1586        p2 = [initial opStringIntDict:p1 p3:&p3];
1587        test(p2 == ICENone && p3 == ICENone);
1588
1589        p2 = [initial opIntIntDict:[TestOptionalStringIntDict dictionary] p3:&p3];
1590        test(p2 != nil && p3 != nil && [p2 count] == 0 && [p3 count] == 0);
1591
1592        TestOptionalMutableStringIntDict* sid = [TestOptionalMutableStringIntDict dictionary];
1593        [sid setObject:@45 forKey:@"1"];
1594        p1 = sid;
1595        p2 = [initial opStringIntDict:p1 p3:&p3];
1596        test(p2 != nil && p3 != nil);
1597        test([p2 isEqual:sid] && [p3 isEqual:sid]);
1598
1599        p1 = ICENone;
1600        p3 = ICENone;
1601        p2 = [initial opIntOneOptionalDict:p1 p3:&p3];
1602        test(p2 == ICENone && p3 == ICENone);
1603
1604        p2 = [initial opIntOneOptionalDict:[TestOptionalStringIntDict dictionary] p3:&p3];
1605        test(p2 != nil && p3 != nil && [p2 count] == 0 && [p3 count] == 0);
1606
1607        TestOptionalMutableIntOneOptionalDict* iod = [TestOptionalMutableIntOneOptionalDict dictionary];
1608        TestOptionalOneOptional* oneOpt = [TestOptionalOneOptional oneOptional:@58];
1609        [iod setObject:oneOpt forKey:@1];
1610        p1 = iod;
1611        p2 = [initial opIntOneOptionalDict:p1 p3:&p3];
1612        test(p2 != nil && p3 != nil);
1613        test(((TestOptionalOneOptional*)[p2 objectForKey:@1]).a == 58 &&
1614             ((TestOptionalOneOptional*)[p3 objectForKey:@1]).a == 58);
1615    }
1616    tprintf("ok\n");
1617
1618    tprintf("testing exception optionals... ");
1619    {
1620        @try
1621        {
1622            [initial opOptionalException:ICENone b:ICENone o:ICENone];
1623            test(NO);
1624        }
1625        @catch(TestOptionalOptionalException* ex)
1626        {
1627            test(![ex hasA]);
1628            test(![ex hasB]);
1629            test(![ex hasO]);
1630        }
1631
1632        @try
1633        {
1634            [initial opOptionalException:@30 b:@"test" o:[TestOptionalOneOptional oneOptional:@53]];
1635            test(NO);
1636        }
1637        @catch(TestOptionalOptionalException* ex)
1638        {
1639            test(ex.a == 30);
1640            test([ex.b isEqualToString:@"test"]);
1641            test(ex.o.a == 53);
1642        }
1643
1644        @try
1645        {
1646            //
1647            // Use the 1.0 encoding with an exception whose only class members are optional.
1648            //
1649            [[initial ice_encodingVersion:ICEEncoding_1_0]
1650               opOptionalException:@30 b:@"test" o:[TestOptionalOneOptional oneOptional:@53]];
1651            test(NO);
1652        }
1653        @catch(TestOptionalOptionalException* ex)
1654        {
1655            test(![ex hasA]);
1656            test(![ex hasB]);
1657            test(![ex hasO]);
1658        }
1659
1660        @try
1661        {
1662            id a = ICENone;
1663            id b = ICENone;
1664            id o = ICENone;
1665            [initial opDerivedException:a b:b o:o];
1666            test(NO);
1667        }
1668        @catch(TestOptionalDerivedException* ex)
1669        {
1670            test(![ex hasA]);
1671            test(![ex hasB]);
1672            test(![ex hasO]);
1673            test(![ex hasSs]);
1674            test(![ex hasO2]);
1675        }
1676        @catch(TestOptionalOptionalException* ex)
1677        {
1678            test(NO);
1679        }
1680
1681        @try
1682        {
1683            id a = @30;
1684            id b = @"test2";
1685            TestOptionalOneOptional* o = [TestOptionalOneOptional oneOptional:@53];
1686            [initial opDerivedException:a b:b o:o];
1687            test(NO);
1688        }
1689        @catch(TestOptionalDerivedException* ex)
1690        {
1691            test(ex.a == 30);
1692            test([ex.b isEqualToString:@"test2"]);
1693            test(ex.o.a == 53);
1694            test([ex.ss isEqualToString:@"test2"]);
1695            test(ex.o2.a == 53);
1696        }
1697        @catch(TestOptionalOptionalException* ex)
1698        {
1699            test(NO);
1700        }
1701
1702        @try
1703        {
1704            id a = ICENone;
1705            id b = ICENone;
1706            id o = ICENone;
1707            [initial opRequiredException:a b:b o:o];
1708            test(NO);
1709        }
1710        @catch(TestOptionalRequiredException* ex)
1711        {
1712            test(![ex hasA]);
1713            test(![ex hasB]);
1714            test(![ex hasO]);
1715            test([ex.ss isEqualToString:@"test"]);
1716        }
1717        @catch(TestOptionalOptionalException* ex)
1718        {
1719            test(NO);
1720        }
1721
1722        @try
1723        {
1724            id a = @30;
1725            id b = @"test2";
1726            id o = [TestOptionalOneOptional oneOptional:@53];
1727            [initial opRequiredException:a b:b o:o];
1728            test(NO);
1729        }
1730        @catch(TestOptionalRequiredException* ex)
1731        {
1732            test(ex.a == 30);
1733            test([ex.b isEqualToString:@"test2"]);
1734            test(ex.o.a == 53);
1735            test([ex.ss isEqualToString:@"test2"]);
1736            test(ex.o2.a == 53);
1737        }
1738        @catch(TestOptionalOptionalException* ex)
1739        {
1740            test(NO);
1741        }
1742    }
1743    tprintf("ok\n");
1744
1745    tprintf("testing optionals with marshaled results... ");
1746    {
1747        test([initial opMStruct1]);
1748        test([initial opMDict1]);
1749        test([initial opMSeq1]);
1750        test([initial opMG1]);
1751
1752        {
1753            id p1, p2, p3;
1754            p3 = [initial opMStruct2:ICENone p2:&p2];
1755            test(p2 == ICENone && p3 == ICENone);
1756
1757            p1 = [TestOptionalSmallStruct smallStruct];
1758            p3 = [initial opMStruct2:p1 p2:&p2];
1759            test([p2 isEqual:p1] && [p3 isEqual:p1]);
1760        }
1761        {
1762            id p1, p2, p3;
1763            p3 = [initial opMSeq2:ICENone p2:&p2];
1764            test(p2 == ICENone && p3 == ICENone);
1765
1766            p1 = [TestOptionalStringSeq arrayWithObject:@"hello"];
1767            p3 = [initial opMSeq2:p1 p2:&p2];
1768            test([[p2 objectAtIndex:0] isEqualToString:@"hello"] &&
1769                 [[p3 objectAtIndex:0] isEqualToString:@"hello"]);
1770        }
1771        {
1772            id p1, p2, p3;
1773            p3 = [initial opMDict2:ICENone p2:&p2];
1774            test(p2 == ICENone && p3 == ICENone);
1775
1776            p1 = [TestOptionalStringIntDict dictionaryWithObjectsAndKeys:@54, @"test", nil];
1777            p3 = [initial opMDict2:p1 p2:&p2];
1778            test([[p2 objectForKey:@"test"] isEqual:@54] && [[p3 objectForKey:@"test"] isEqual:@54]);
1779        }
1780        {
1781            id p1, p2, p3;
1782            p3 = [initial opMG2:ICENone p2:&p2];
1783            test(p2 == ICENone && p3 == ICENone);
1784
1785            p1 = [TestOptionalG g];
1786            p3 = [initial opMG2:p1 p2:&p2];
1787            test(p2 != ICENone && p3 != ICENone && p3 == p2);
1788        }
1789    }
1790    tprintf("ok\n");
1791
1792    return initial;
1793}
1794