xref: /trunk/main/testtools/source/bridgetest/cli/cli_cpp_bridgetest.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_testtools.hxx"
26 
27 #using <mscorlib.dll>
28 #using <System.dll>
29 #using <cli_basetypes.dll>
30 #using <cli_uretypes.dll>
31 #using <cli_ure.dll>
32 #using <cli_types_bridgetest.dll>
33 
34 using namespace System;
35 using namespace System::Diagnostics;
36 using namespace System::Reflection;
37 using namespace System::Threading;
38 using namespace uno;
39 using namespace uno::util;
40 using namespace unoidl::com::sun::star::uno;
41 using namespace unoidl::com::sun::star::lang;
42 //using namespace unoidl::com::sun::star::test::bridge;
43 using namespace unoidl::test::testtools::bridgetest;
44 namespace foo
45 {
46     public interface class MyInterface
47     {
48     };
49 }
50 
51 namespace cpp_bridgetest
52 {
53     ref class ORecursiveCall: public WeakBase, public XRecursiveCall
54     {
55         public:
56         // Implementing an interface method needs an explicit virtual in
57         // C++/CLI; MC++ inferred it from the base list.
58         virtual void  callRecursivly(XRecursiveCall ^ xCall, int nToCall)
59         {
60             Monitor::Enter(this);
61             try
62             {
63                 {
64                     if (nToCall > 0)
65                     {
66                         nToCall --;
67                         xCall->callRecursivly(this, nToCall);
68                     }
69                 }
70             }
71             __finally
72             {
73                 Monitor::Exit(this);
74             }
75 
76         }
77     };
78 
79 public ref class Constants
80 {
81 public:
82     static String ^ STRING_TEST_CONSTANT  = gcnew String("\" paco\' chorizo\\\' \"\'");
83 };
84 
85 public ref class BridgeTest : public WeakBase, public XMain
86 {
87     static bool compareData(Object ^ val1, Object ^ val2)
88     {
89         if (val1 == nullptr && val2 == nullptr || val1 == val2)
90             return true;
91         if ((val1 == nullptr && val2 != nullptr) ||
92             (val1 != nullptr && val2 == nullptr) || val1->GetType() != val2->GetType())
93             return false;
94 
95         bool ret = false;
96         Type ^ t1  = val1->GetType();
97             //Sequence
98         if (t1->IsArray)
99         {
100             ret = compareSequence(static_cast<Array ^>(val1),
101                                   static_cast<Array ^>(val2));
102         }
103             //String
104         else if (t1 == String::typeid)
105         {
106             ret = val1->Equals(val2);
107         }
108             // Interface implementation
109         else if (t1->GetInterfaces()->Length > 0 && ! t1->IsValueType)
110         {
111             ret = val1 == val2;
112         }
113             // Struct
114         else if ( ! t1->IsValueType)
115         {
116             ret = compareStruct(val1, val2);
117         }
118         else if (t1 == Any::typeid)
119         {
120             Any a1 = (Any) val1;
121             Any a2 = (Any) val2;
122             ret = a1.Type == a2.Type && compareData(a1.Value, a2.Value);
123         }
124         else if (t1->IsValueType)
125         {
126             //Any, enum, int, bool char, float, double etc.
127             ret = val1->Equals(val2);
128         }
129         else
130         {
131             Debug::Assert(false);
132         }
133         return ret;
134     }
135 
136     // Arrays have only one dimension
137     static bool compareSequence(Array ^ ar1, Array ^ ar2)
138     {
139         Debug::Assert(ar1 != nullptr && ar2 != nullptr);
140         Type ^ t1 = ar1->GetType();
141         Type ^ t2 = ar2->GetType();
142 
143         if (!(ar1->Rank == 1 && ar2->Rank == 1
144             && ar1->Length == ar2->Length && t1->GetElementType() == t2->GetElementType()))
145             return false;
146 
147         //arrays have same rank and size and element type.
148         int len  = ar1->Length;
149         bool ret = true;
150         for (int i = 0; i < len; i++)
151         {
152             if (compareData(ar1->GetValue(i), ar2->GetValue(i)) == false)
153             {
154                 ret = false;
155                 break;
156             }
157         }
158         return ret;
159     }
160 
161     static bool compareStruct(Object ^ val1, Object ^ val2)
162     {
163         Debug::Assert(val1 != nullptr && val2 != nullptr);
164         Type ^ t1 = val1->GetType();
165         Type ^ t2 = val2->GetType();
166         if (t1 != t2)
167             return false;
168         cli::array< FieldInfo ^ > ^ fields = t1->GetFields();
169         int cFields = fields->Length;
170         bool ret = true;
171         for (int i = 0; i < cFields; i++)
172         {
173             Object ^ fieldVal1 = fields[i]->GetValue(val1);
174             Object ^ fieldVal2 = fields[i]->GetValue(val2);
175             if ( ! compareData(fieldVal1, fieldVal2))
176             {
177                 ret = false;
178                 break;
179             }
180         }
181         return ret;
182     }
183 
184     static bool check( bool b , String ^ message )
185     {
186         if ( ! b)
187         Console::WriteLine("{0} failed\n" , message);
188         return b;
189     }
190 
191     static bool equals(TestElement ^ rData1, TestElement ^  rData2)
192     {
193         check( rData1->Bool == rData2->Bool, "### bool does not match!" );
194         check( rData1->Char == rData2->Char, "### char does not match!" );
195         check( rData1->Byte == rData2->Byte, "### byte does not match!" );
196         check( rData1->Short == rData2->Short, "### short does not match!" );
197         check( rData1->UShort == rData2->UShort, "### unsigned short does not match!" );
198         check( rData1->Long == rData2->Long, "### long does not match!" );
199         check( rData1->ULong == rData2->ULong, "### unsigned long does not match!" );
200         check( rData1->Hyper == rData2->Hyper, "### hyper does not match!" );
201         check( rData1->UHyper == rData2->UHyper, "### unsigned hyper does not match!" );
202         check( rData1->Float == rData2->Float, "### float does not match!" );
203         check( rData1->Double == rData2->Double, "### double does not match!" );
204         check( rData1->Enum == rData2->Enum, "### enum does not match!" );
205         check( rData1->String == rData2->String, "### string does not match!" );
206         check( rData1->Interface == rData2->Interface, "### interface does not match!" );
207         check( compareData((::System::Object ^)(rData1->Any), (::System::Object ^)(rData2->Any)), "### any does not match!" );
208 
209         return (rData1->Bool == rData2->Bool &&
210                 rData1->Char == rData2->Char &&
211                 rData1->Byte == rData2->Byte &&
212                 rData1->Short == rData2->Short &&
213                 rData1->UShort == rData2->UShort &&
214                 rData1->Long == rData2->Long &&
215                 rData1->ULong == rData2->ULong &&
216                 rData1->Hyper == rData2->Hyper &&
217                 rData1->UHyper == rData2->UHyper &&
218                 rData1->Float == rData2->Float &&
219                 rData1->Double == rData2->Double &&
220                 rData1->Enum == rData2->Enum &&
221                 rData1->String == rData2->String &&
222                 rData1->Interface == rData2->Interface &&
223                 compareData((::System::Object ^)(rData1->Any), (::System::Object ^)(rData2->Any)));
224     }
225 
226 static void assign( TestElement ^ rData,
227                     bool bBool, Char cChar, Byte nByte,
228                     Int16 nShort, UInt16 nUShort,
229                     Int32 nLong, UInt32 nULong,
230                     Int64 nHyper, UInt64 nUHyper,
231                     float fFloat, double fDouble,
232                     TestEnum eEnum, String ^ rStr,
233                     Object ^ xTest,
234                     uno::Any rAny )
235 {
236     rData->Bool = bBool;
237     rData->Char = cChar;
238     rData->Byte = nByte;
239     rData->Short = nShort;
240     rData->UShort = nUShort;
241     rData->Long = nLong;
242     rData->ULong = nULong;
243     rData->Hyper = nHyper;
244     rData->UHyper = nUHyper;
245     rData->Float = fFloat;
246     rData->Double = fDouble;
247     rData->Enum = eEnum;
248     rData->String = rStr;
249     rData->Interface = xTest;
250     rData->Any = rAny;
251 }
252 
253 static void assign( TestDataElements ^ rData,
254                     bool bBool, Char cChar, Byte nByte,
255                     Int16 nShort, UInt16 nUShort,
256                     Int32 nLong, UInt32 nULong,
257                     Int64 nHyper, UInt64 nUHyper,
258                     float fFloat, double fDouble,
259                     TestEnum eEnum, String ^ rStr,
260                     Object ^ xTest,
261                     Any rAny,
262                     cli::array< TestElement ^ > ^ rSequence)
263 {
264     assign( static_cast<TestElement ^>(rData),
265             bBool, cChar, nByte, nShort, nUShort, nLong, nULong, nHyper, nUHyper, fFloat, fDouble,
266             eEnum, rStr, xTest, rAny );
267     rData->Sequence = rSequence;
268 }
269 
270 static bool testAny(Type ^ typ, Object ^  value, XBridgeTest ^ xLBT )
271 {
272     Any any;
273     if (typ == nullptr)
274         any = Any(value->GetType(), value);
275     else
276         any = Any(typ, value);
277 
278     Any any2 = xLBT->transportAny(any);
279     bool ret = compareData((::System::Object ^)(any), (::System::Object ^)(any2));
280     if (!ret)
281     {
282         Console::WriteLine("any is different after roundtrip: in {0}, out {1}\n",
283                           any.Type->FullName, any2.Type->FullName);
284     }
285     return ret;
286 }
287 
288 
289 
290 static bool performAnyTest(XBridgeTest ^ xLBT,  TestDataElements ^ data)
291 {
292     bool bReturn = true;
293     bReturn = testAny( nullptr, (::System::Object ^)(data->Byte), xLBT ) && bReturn;
294     bReturn = testAny( nullptr, (::System::Object ^)(data->Short), xLBT ) && bReturn;
295     bReturn = testAny(  nullptr, (::System::Object ^)(data->UShort), xLBT ) && bReturn;
296     bReturn = testAny(  nullptr, (::System::Object ^)(data->Long), xLBT ) && bReturn;
297     bReturn = testAny(  nullptr, (::System::Object ^)(data->ULong), xLBT ) && bReturn;
298     bReturn = testAny(  nullptr, (::System::Object ^)(data->Hyper), xLBT ) && bReturn;
299     bReturn = testAny(  nullptr, (::System::Object ^)(data->UHyper), xLBT ) && bReturn;
300     bReturn = testAny( nullptr, (::System::Object ^)(data->Float), xLBT ) && bReturn;
301     bReturn = testAny( nullptr, (::System::Object ^)(data->Double),xLBT ) && bReturn;
302     bReturn = testAny( nullptr, (::System::Object ^)(data->Enum), xLBT ) && bReturn;
303     bReturn = testAny( nullptr, data->String,xLBT ) && bReturn;
304     bReturn = testAny(XWeak::typeid, data->Interface,xLBT ) && bReturn;
305     bReturn = testAny(nullptr, data, xLBT ) && bReturn;
306 
307     {
308         Any a1(true);
309         Any a2 = xLBT->transportAny( a1 );
310         bReturn = compareData((::System::Object ^)(a2), (::System::Object ^)(a1)) && bReturn;
311     }
312 
313     {
314         Any a1('A');
315         Any a2 = xLBT->transportAny(a1);
316         bReturn = compareData( (::System::Object ^)(a2), (::System::Object ^)(a1)) && bReturn;
317     }
318     return bReturn;
319 }
320 
321 static bool performSequenceOfCallTest(XBridgeTest ^ xLBT)
322 {
323     int i,nRounds;
324     int nGlobalIndex = 0;
325     const int nWaitTimeSpanMUSec = 10000;
326     for( nRounds = 0 ; nRounds < 10 ; nRounds ++ )
327     {
328         for( i = 0 ; i < nRounds ; i ++ )
329         {
330             // fire oneways
331             xLBT->callOneway(nGlobalIndex, nWaitTimeSpanMUSec);
332             nGlobalIndex++;
333         }
334 
335         // call synchron
336         xLBT->call(nGlobalIndex, nWaitTimeSpanMUSec);
337         nGlobalIndex++;
338     }
339     return xLBT->sequenceOfCallTestPassed();
340 }
341 
342 
343 
344 
345 static bool performRecursiveCallTest(XBridgeTest ^  xLBT)
346 {
347     xLBT->startRecursiveCall(gcnew ORecursiveCall(), 50);
348     // on failure, the test would lock up or crash
349     return true;
350 }
351 
352 static bool performQueryForUnknownType(XBridgeTest ^ xLBT)
353 {
354     bool bRet = false;
355     // test queryInterface for an unknown type
356     try
357     {
358         safe_cast< foo::MyInterface ^ >(xLBT);
359     }
360     catch( System::InvalidCastException ^)
361     {
362         bRet = true;
363     }
364 
365     return bRet;
366 }
367 
368 // //==================================================================================================
369 static bool performTest(XBridgeTest ^ xLBT)
370 {
371     check( xLBT != nullptr, "### no test interface!" );
372     bool bRet = true;
373     if (xLBT != nullptr)
374     {
375         // this data is never ever granted access to by calls other than equals(), assign()!
376         TestDataElements ^ aData = gcnew TestDataElements(); // test against this data
377 
378         Object ^ xI= gcnew WeakBase();
379 
380         Any aAny( Object::typeid, xI);
381         assign( static_cast<TestElement ^>(aData),
382                 true, '@', 17, 0x1234, 0xfedc, 0x12345678, 0xfedcba98,
383                 0x123456789abcdef0, 0xfedcba9876543210,
384                 17.0815f, 3.1415926359, TestEnum::LOLA,
385                 Constants::STRING_TEST_CONSTANT, xI,
386                 aAny);
387 
388         bRet = check( aData->Any.Value == xI, "### unexpected any!" ) && bRet;
389         bRet = check( !(aData->Any.Value != xI), "### unexpected any!" ) && bRet;
390 
391         aData->Sequence = gcnew cli::array< TestElement ^ >(2);
392         aData->Sequence[0] = gcnew TestElement(
393             aData->Bool, aData->Char, aData->Byte, aData->Short,
394             aData->UShort, aData->Long, aData->ULong,
395             aData->Hyper, aData->UHyper, aData->Float,
396             aData->Double, aData->Enum, aData->String,
397             aData->Interface, aData->Any); //(TestElement) aData;
398         aData->Sequence[1] = gcnew TestElement(); //is empty
399 
400         // aData complete
401         //
402         // this is a manually copy of aData for first setting...
403         TestDataElements ^ aSetData = gcnew TestDataElements();
404         Any aAnySet(Object::typeid, xI);
405         assign( static_cast<TestElement ^>(aSetData),
406                 aData->Bool,
407                 aData->Char,
408                 aData->Byte,
409                 aData->Short,
410                 aData->UShort,
411                 aData->Long, aData->ULong, aData->Hyper, aData->UHyper, aData->Float, aData->Double,
412                 aData->Enum,
413                 aData->String,
414                 xI,
415                 aAnySet);
416 
417         aSetData->Sequence = gcnew cli::array< TestElement ^ >(2);
418         aSetData->Sequence[0] = gcnew TestElement(
419             aSetData->Bool, aSetData->Char, aSetData->Byte, aSetData->Short,
420             aSetData->UShort, aSetData->Long, aSetData->ULong,
421             aSetData->Hyper, aSetData->UHyper, aSetData->Float,
422             aSetData->Double, aSetData->Enum, aSetData->String,
423             aSetData->Interface, aSetData->Any); //TestElement) aSetData;
424         aSetData->Sequence[1] = gcnew TestElement(); // empty struct
425 
426         xLBT->setValues(
427                 aSetData->Bool, aSetData->Char, aSetData->Byte, aSetData->Short, aSetData->UShort,
428                 aSetData->Long, aSetData->ULong, aSetData->Hyper, aSetData->UHyper, aSetData->Float, aSetData->Double,
429                 aSetData->Enum, aSetData->String, aSetData->Interface, aSetData->Any, aSetData->Sequence, aSetData );
430 
431         {
432         TestDataElements ^ aRet = gcnew TestDataElements();
433         TestDataElements ^ aRet2 = gcnew TestDataElements();
434         xLBT->getValues(
435             aRet->Bool, aRet->Char, aRet->Byte, aRet->Short, aRet->UShort,
436             aRet->Long, aRet->ULong, aRet->Hyper, aRet->UHyper,
437             aRet->Float, aRet->Double, aRet->Enum, aRet->String,
438             aRet->Interface, aRet->Any, aRet->Sequence, aRet2 );
439 
440         bRet = check( compareData( aData, aRet ) && compareData( aData, aRet2 ) , "getValues test") && bRet;
441 
442         // set last retrieved values
443         TestDataElements ^ aSV2ret = xLBT->setValues2(
444             aRet->Bool, aRet->Char, aRet->Byte, aRet->Short, aRet->UShort,
445             aRet->Long, aRet->ULong, aRet->Hyper, aRet->UHyper, aRet->Float,
446             aRet->Double, aRet->Enum, aRet->String, aRet->Interface, aRet->Any,
447             aRet->Sequence, aRet2 );
448 
449         // check inout sequence order
450         // => inout sequence parameter was switched by test objects
451         TestElement ^ temp = aRet->Sequence[ 0 ];
452         aRet->Sequence[ 0 ] = aRet->Sequence[ 1 ];
453         aRet->Sequence[ 1 ] = temp;
454 
455         bRet = check(
456             compareData( aData, aSV2ret ) && compareData( aData, aRet2 ),
457             "getValues2 test") && bRet;
458         }
459         {
460         TestDataElements ^ aRet = gcnew TestDataElements();
461         TestDataElements ^ aRet2 = gcnew TestDataElements();
462         TestDataElements ^ aGVret = xLBT->getValues(
463             aRet->Bool, aRet->Char, aRet->Byte, aRet->Short,
464             aRet->UShort, aRet->Long, aRet->ULong, aRet->Hyper,
465             aRet->UHyper, aRet->Float, aRet->Double, aRet->Enum,
466             aRet->String, aRet->Interface, aRet->Any, aRet->Sequence,
467             aRet2 );
468 
469         bRet = check( compareData( aData, aRet ) && compareData( aData, aRet2 ) && compareData( aData, aGVret ), "getValues test" ) && bRet;
470 
471         // set last retrieved values
472         xLBT->Bool = aRet->Bool;
473         xLBT->Char = aRet->Char;
474         xLBT->Byte = aRet->Byte;
475         xLBT->Short = aRet->Short;
476         xLBT->UShort = aRet->UShort;
477         xLBT->Long = aRet->Long;
478         xLBT->ULong = aRet->ULong;
479         xLBT->Hyper = aRet->Hyper;
480         xLBT->UHyper = aRet->UHyper;
481         xLBT->Float = aRet->Float;
482         xLBT->Double = aRet->Double;
483         xLBT->Enum = aRet->Enum;
484         xLBT->String = aRet->String;
485         xLBT->Interface = aRet->Interface;
486         xLBT->Any = aRet->Any;
487         xLBT->Sequence = aRet->Sequence;
488         xLBT->Struct = aRet2;
489         }
490         {
491         TestDataElements ^ aRet = gcnew TestDataElements();
492         TestDataElements ^ aRet2 = gcnew TestDataElements();
493         aRet->Hyper = xLBT->Hyper;
494         aRet->UHyper = xLBT->UHyper;
495         aRet->Float = xLBT->Float;
496         aRet->Double = xLBT->Double;
497         aRet->Byte = xLBT->Byte;
498         aRet->Char = xLBT->Char;
499         aRet->Bool = xLBT->Bool;
500         aRet->Short = xLBT->Short;
501         aRet->UShort = xLBT->UShort;
502         aRet->Long = xLBT->Long;
503         aRet->ULong = xLBT->ULong;
504         aRet->Enum = xLBT->Enum;
505         aRet->String = xLBT->String;
506         aRet->Interface = xLBT->Interface;
507         aRet->Any = xLBT->Any;
508         aRet->Sequence = xLBT->Sequence;
509         aRet2 = xLBT->Struct;
510 
511         bRet = check( compareData( aData, aRet ) && compareData( aData, aRet2 ) , "struct comparison test") && bRet;
512 
513         bRet = check(performSequenceTest(xLBT), "sequence test") && bRet;
514 
515         // any test
516         bRet = check( performAnyTest( xLBT , aData ) , "any test" ) && bRet;
517 
518         // sequence of call test
519         bRet = check( performSequenceOfCallTest( xLBT ) , "sequence of call test" ) && bRet;
520 
521         // recursive call test
522         bRet = check( performRecursiveCallTest( xLBT ) , "recursive test" ) && bRet;
523 
524         bRet = (compareData( aData, aRet ) && compareData( aData, aRet2 )) && bRet ;
525 
526         // check setting of null reference.  XInterface maps to Object^, and
527         // "= 0" on one BOXES the literal into an Int32 instead of storing
528         // null -- so the property ends up non-null and the comparison below
529         // is false whatever happens.  Neither has a check() message, which is
530         // why this failed as a bare "standard test failed".
531         xLBT->Interface = nullptr;
532         aRet->Interface = xLBT->Interface;
533         bRet = (aRet->Interface == nullptr) && bRet;
534 
535         }
536 
537 
538     }
539         return bRet;
540  }
541 static bool performSequenceTest(XBridgeTest ^ xBT)
542 {
543     bool bRet = true;
544     XBridgeTest2 ^  xBT2 = dynamic_cast<XBridgeTest2 ^>(xBT);
545     if ( xBT2 == nullptr)
546         return false;
547 
548     // perform sequence tests (XBridgeTest2)
549     // create the sequence which are compared with the results
550     cli::array< bool > ^ arBool = gcnew cli::array< bool >(3);
551     arBool[0] = true; arBool[1] = false; arBool[2] = true;
552     cli::array< Char > ^ arChar = gcnew cli::array< Char >(3);
553     arChar[0] = 'A'; arChar[1] = 'B'; arChar[2] = 'C';
554     cli::array< Byte > ^ arByte = gcnew cli::array< Byte >(3);
555     arByte[0] =  1; arByte[1] = 2; arByte[2] = 0xff;
556     cli::array< Int16 > ^ arShort = gcnew cli::array< Int16 >(3);
557     arShort[0] = Int16::MinValue; arShort[1] = 1; arShort[2] = Int16::MaxValue;
558     cli::array< UInt16 > ^ arUShort = gcnew cli::array< UInt16 >(3);
559     arUShort[0] = UInt16::MinValue; arUShort[1] = 1; arUShort[2] = UInt16::MaxValue;
560     cli::array< Int32 > ^ arLong = gcnew cli::array< Int32 >(3);
561     arLong[0] = Int32::MinValue; arLong[1] = 1; arLong[2] = Int32::MaxValue;
562     cli::array< UInt32 > ^ arULong = gcnew cli::array< UInt32 >(3);
563     arULong[0] = UInt32::MinValue; arULong[1] = 1; arULong[2] = UInt32::MaxValue;
564     cli::array< Int64 > ^ arHyper = gcnew cli::array< Int64 >(3);
565     arHyper[0] = Int64::MinValue; arHyper[1] = 1; arHyper[2] = Int64::MaxValue;
566     cli::array< UInt64 > ^ arUHyper = gcnew cli::array< UInt64 >(3);
567     arUHyper[0] = UInt64::MinValue; arUHyper[1] = 1;
568     arUHyper[2] = UInt64::MaxValue;
569     cli::array< Single > ^ arFloat = gcnew cli::array< Single >(3);
570     arFloat[0] = 1.1f; arFloat[1] = 2.2f; arFloat[2] = 3.3f;
571     cli::array< Double > ^ arDouble = gcnew cli::array< Double >(3);
572     arDouble[0] = 1.11; arDouble[1] = 2.22; arDouble[2] = 3.33;
573     cli::array< String ^ > ^ arString = gcnew cli::array< String ^ >( 3 );
574     arString[0] = gcnew String("String 1");
575     arString[1] = gcnew String("String 2");
576     arString[2] = gcnew String("String 3");
577 
578     cli::array< Any > ^ arAny = gcnew cli::array< Any >( 3 );
579     arAny[0] = Any(true); arAny[1] = Any(11111); arAny[2] = Any(3.14);
580     cli::array< Object ^ > ^ arObject = gcnew cli::array< Object ^ >( 3 );
581     arObject[0] = gcnew WeakBase(); arObject[1] =  gcnew WeakBase();
582     arObject[1] = gcnew WeakBase();
583 
584     //TestEnum arEnum[] = new TestEnum[3];
585     //arEnum[0] = TestEnum::ONE; arEnum[1] = TestEnum::TWO;
586     //arEnum[2] = TestEnum::CHECK;
587     Console::WriteLine(gcnew String("cli_cpp_bridgetest: Workaround for C++ compiler bug:"
588         " using Array of Int32 instead of Array of enums w"));
589     cli::array< Int32 > ^ arEnum = gcnew cli::array< Int32 >(3);
590     arEnum[0] = static_cast<Int32>(TestEnum::ONE);
591     arEnum[1] = static_cast<Int32>(TestEnum::TWO);
592     arEnum[2] = static_cast<Int32>(TestEnum::CHECK);
593 
594     cli::array< TestElement ^ > ^ arStruct = gcnew cli::array< TestElement ^ >(3);
595     arStruct[0] = gcnew TestElement(); arStruct[1] = gcnew TestElement();
596     arStruct[2] = gcnew TestElement();
597     assign( arStruct[0], true, '@', 17, 0x1234, 0xfedc, 0x12345678, 0xfedcba98,
598             0x123456789abcdef0, 0xfedcba9876543210, 17.0815f, 3.1415926359,
599             TestEnum::LOLA, Constants::STRING_TEST_CONSTANT, arObject[0],
600             Any( Object::typeid,  arObject[0]) );
601     assign( arStruct[1], true, 'A', 17, 0x1234, 0xfedc, 0x12345678, 0xfedcba98,
602             0x123456789abcdef0, 0xfedcba9876543210, 17.0815f, 3.1415926359,
603             TestEnum::TWO, Constants::STRING_TEST_CONSTANT, arObject[1],
604             Any( Object::typeid, arObject[1]) );
605     assign( arStruct[2], true, 'B', 17, 0x1234, 0xfedc, 0x12345678, 0xfedcba98,
606             0x123456789abcdef0, 0xfedcba9876543210, 17.0815f, 3.1415926359,
607             TestEnum::CHECK, Constants::STRING_TEST_CONSTANT, arObject[2],
608             Any( Object::typeid, arObject[2] ) );
609 
610 
611 //     int[][][] arLong3 = new int[][][]{
612 //         new int[][]{new int[]{1,2,3},new int[]{4,5,6}, new int[]{7,8,9} },
613 //         new int [][]{new int[]{1,2,3},new int[]{4,5,6}, new int[]{7,8,9}},
614 //         new int[][]{new int[]{1,2,3},new int[]{4,5,6}, new int[]{7,8,9}}};
615 
616     {
617 
618 //      Console::WriteLine(gcnew String("cli_cpp_bridgetest:
619 //     int[][] seqSeqRet = xBT2->setDim2(arLong3[0]);
620 //     bRet = check( compareData(seqSeqRet, arLong3[0]), "sequence test") && bRet;
621 //     int[][][] seqSeqRet2 = xBT2->setDim3(arLong3);
622 //     bRet = check( compareData(seqSeqRet2, arLong3), "sequence test") && bRet;
623 
624     cli::array< Any > ^ seqAnyRet = xBT2->setSequenceAny(arAny);
625     bRet = check( compareData(seqAnyRet, arAny), "sequence test") && bRet;
626     cli::array< Boolean > ^ seqBoolRet = xBT2->setSequenceBool(arBool);
627     bRet = check( compareData(seqBoolRet, arBool), "sequence test") && bRet;
628     cli::array< Byte > ^ seqByteRet = xBT2->setSequenceByte(arByte);
629     bRet = check( compareData(seqByteRet, arByte), "sequence test") && bRet;
630     cli::array< Char > ^ seqCharRet = xBT2->setSequenceChar(arChar);
631     bRet = check( compareData(seqCharRet, arChar), "sequence test") && bRet;
632     cli::array< Int16 > ^ seqShortRet = xBT2->setSequenceShort(arShort);
633     bRet = check( compareData(seqShortRet, arShort), "sequence test") && bRet;
634     cli::array< Int32 > ^ seqLongRet = xBT2->setSequenceLong(arLong);
635     bRet = check( compareData(seqLongRet, arLong), "sequence test") && bRet;
636     cli::array< Int64 > ^ seqHyperRet = xBT2->setSequenceHyper(arHyper);
637     bRet = check( compareData(seqHyperRet,arHyper), "sequence test") && bRet;
638     cli::array< Single > ^ seqFloatRet = xBT2->setSequenceFloat(arFloat);
639     bRet = check( compareData(seqFloatRet, arFloat), "sequence test") && bRet;
640     cli::array< Double > ^ seqDoubleRet = xBT2->setSequenceDouble(arDouble);
641     bRet = check( compareData(seqDoubleRet, arDouble), "sequence test") && bRet;
642     xBT2->setSequenceEnum(
643         safe_cast< cli::array< TestEnum > ^ >( (Object ^) arEnum ) );
644     //comparing seqEnumRet with arEnum will fail since they are of different
645     //types because of workaround. arEnum is Int32[].
646     Console::WriteLine(gcnew String("cli_cpp_bridgetest: Test omitted because "
647         "of C++ compiler bug. XBridgeTest2::setSequenceEnum(sequence<TestEnum>)"));
648 //    bRet = check( compareData(seqEnumRet, arEnum), "sequence test") && bRet;
649     cli::array< UInt16 > ^ seqUShortRet = xBT2->setSequenceUShort(arUShort);
650     bRet = check( compareData(seqUShortRet, arUShort), "sequence test") && bRet;
651     cli::array< UInt32 > ^ seqULongRet = xBT2->setSequenceULong(arULong);
652     bRet = check( compareData(seqULongRet, arULong), "sequence test") && bRet;
653     cli::array< UInt64 > ^ seqUHyperRet = xBT2->setSequenceUHyper(arUHyper);
654     bRet = check( compareData(seqUHyperRet, arUHyper), "sequence test") && bRet;
655     cli::array< Object ^ > ^ seqObjectRet = xBT2->setSequenceXInterface(arObject);
656     bRet = check( compareData(seqObjectRet, arObject), "sequence test") && bRet;
657     cli::array< String ^ > ^ seqStringRet = xBT2->setSequenceString(arString);
658     bRet = check( compareData(seqStringRet, arString), "sequence test") && bRet;
659     cli::array< TestElement ^ > ^ seqStructRet = xBT2->setSequenceStruct(arStruct);
660     bRet = check( compareData(seqStructRet, arStruct), "sequence test") && bRet;
661     }
662     {
663 //     Boolean arBoolTemp[] = static_cast<Boolean[]>( arBool->Clone());
664 //     Char arCharTemp[] = static_cast<Char[]>(arChar->Clone());
665 //     Byte arByteTemp[] = static_cast<Byte[]>(arByte->Clone());
666 //     Int16 arShortTemp[] = static_cast<Int16[]>(arShort->Clone());
667 //     UInt16 arUShortTemp[] = static_cast<UInt16[]>(arUShort->Clone());
668 //     Int32 arLongTemp[] = static_cast<Int32[]>(arLong->Clone());
669 //     UInt32 arULongTemp[] = static_cast<UInt32[]>(arULong->Clone());
670 //     Int64 arHyperTemp[] = static_cast<Int64[]>(arHyper->Clone());
671 //     UInt64 arUHyperTemp[] = static_cast<UInt64[]>(arUHyper->Clone());
672 //     Single arFloatTemp[] = static_cast<Single[]>(arFloat->Clone());
673 //     Double arDoubleTemp[] = static_cast<Double[]>(arDouble->Clone());
674 //     TestEnum arEnumTemp[] = static_cast<TestEnum[]>(arEnum->Clone());
675 //     cli::array< String ^ > ^ arStringTemp = static_cast<String ^[]>(arString->Clone());
676 //     Object ^ arObjectTemp = static_cast<Object ^[]>(arObject->Clone());
677 //     cli::array< Any > ^ arAnyTemp = static_cast<Any[]>(arAny->Clone());
678 //     // make sure this are has the same contents as arLong3[0]
679 //     int[][] arLong2Temp = new int[][]{new int[]{1,2,3},new int[]{4,5,6}, new int[]{7,8,9} };
680 //     // make sure this are has the same contents as arLong3
681 //     int[][][] arLong3Temp = new int[][][]{
682 //         new int[][]{new int[]{1,2,3},new int[]{4,5,6}, new int[]{7,8,9} },
683 //         new int [][]{new int[]{1,2,3},new int[]{4,5,6}, new int[]{7,8,9}},
684 //         new int[][]{new int[]{1,2,3},new int[]{4,5,6}, new int[]{7,8,9}}};
685     Console::WriteLine(gcnew String("cli_cpp_bridgetest: no test of "
686         "XBridgeTest2::setSequencesInOut and XBridgeTest2.setSequencesOut "
687         "because jagged arrays are not supported by C++ compiler"));
688 //     xBT2->setSequencesInOut(& arBoolTemp, & arCharTemp, & arByteTemp,
689 //                            & arShortTemp, & arUShortTemp, & arLongTemp,
690 //                            & arULongTemp,& arHyperTemp, & arUHyperTemp,
691 //                            & arFloatTemp,& arDoubleTemp, & arEnumTemp,
692 //                            & arStringTemp, &  arObjectTemp,
693 //                            & arAnyTemp, & arLong2Temp, & arLong3Temp);
694 //     bRet = check(
695 //         compareData(arBoolTemp, arBool) &&
696 //         compareData(arCharTemp , arChar) &&
697 //         compareData(arByteTemp , arByte) &&
698 //         compareData(arShortTemp , arShort) &&
699 //         compareData(arUShortTemp , arUShort) &&
700 //         compareData(arLongTemp , arLong) &&
701 //         compareData(arULongTemp , arULong) &&
702 //         compareData(arHyperTemp , arHyper) &&
703 //         compareData(arUHyperTemp , arUHyper) &&
704 //         compareData(arFloatTemp , arFloat) &&
705 //         compareData(arDoubleTemp , arDouble) &&
706 //         compareData(arEnumTemp , arEnum) &&
707 //         compareData(arStringTemp , arString) &&
708 //         compareData(arObjectTemp , arObject) &&
709 //         compareData(arAnyTemp , arAny) &&
710 //         compareData(arLong2Temp , arLong3[0]) &&
711 //         compareData(arLong3Temp , arLong3), "sequence test") && bRet;
712 
713     //Boolean arBoolOut[];
714     //Char arCharOut[];
715     //Byte arByteOut[];
716     //Int16 arShortOut[];
717     //UInt16 arUShortOut[];
718     //Int32 arLongOut[];
719     //UInt32 arULongOut[];
720     //Int64 arHyperOut[];
721     //UInt64 arUHyperOut[];
722     //Single arFloatOut[];
723     //Double arDoubleOut[];
724     //TestEnum arEnumOut[];
725     //cli::array< String ^ > ^ arStringOut;
726     //cli::array< Object ^ > ^ arObjectOut;
727     //cli::array< Any > ^ arAnyOut;
728 //     int[][] arLong2Out;
729 //     int[][][] arLong3Out;
730 
731 //     xBT2->setSequencesOut(out arBoolOut, out arCharOut, out arByteOut,
732 //                          out arShortOut, out arUShortOut, out arLongOut,
733 //                          out arULongOut, out arHyperOut, out arUHyperOut,
734 //                          out arFloatOut, out arDoubleOut, out arEnumOut,
735 //                          out arStringOut, out arObjectOut, out arAnyOut,
736 //                          out arLong2Out, out arLong3Out);
737 //     bRet = check(
738 //         compareData(arBoolOut, arBool) &&
739 //         compareData(arCharOut, arChar) &&
740 //         compareData(arByteOut, arByte) &&
741 //         compareData(arShortOut, arShort) &&
742 //         compareData(arUShortOut, arUShort) &&
743 //         compareData(arLongOut, arLong) &&
744 //         compareData(arULongOut, arULong) &&
745 //         compareData(arHyperOut, arHyper) &&
746 //         compareData(arUHyperOut, arUHyper) &&
747 //         compareData(arFloatOut, arFloat) &&
748 //         compareData(arDoubleOut, arDouble) &&
749 //         compareData(arEnumOut, arEnum) &&
750 //         compareData(arStringOut, arString) &&
751 //         compareData(arObjectOut, arObject) &&
752 //         compareData(arAnyOut, arAny) &&
753 //         compareData(arLong2Out, arLong3[0]) &&
754 //         compareData(arLong3Out, arLong3), "sequence test") && bRet;
755     }
756     {
757     //test with empty sequences
758    //  int[][] _arLong2 = new int[0][];
759 //     int[][] seqSeqRet = xBT2->setDim2(_arLong2);
760 //     bRet = check( compareData(seqSeqRet, _arLong2), "sequence test") && bRet;
761 //     int[][][] _arLong3 = new int[0][][];
762 //     int[][][] seqSeqRet2 = xBT2->setDim3(_arLong3);
763 //    bRet = check( compareData(seqSeqRet2, _arLong3), "sequence test") && bRet;
764     cli::array< Any > ^ _arAny = gcnew cli::array< Any >( 0 );
765     cli::array< Any > ^ seqAnyRet = xBT2->setSequenceAny(_arAny);
766     bRet = check( compareData(seqAnyRet, _arAny), "sequence test") && bRet;
767     cli::array< Boolean > ^ _arBool = gcnew cli::array< Boolean >(0);
768     cli::array< Boolean > ^ seqBoolRet = xBT2->setSequenceBool(_arBool);
769     bRet = check( compareData(seqBoolRet, _arBool), "sequence test") && bRet;
770     cli::array< Byte > ^ _arByte = gcnew cli::array< Byte >(0);
771     cli::array< Byte > ^ seqByteRet = xBT2->setSequenceByte(_arByte);
772     bRet = check( compareData(seqByteRet, _arByte), "sequence test") && bRet;
773     cli::array< Char > ^ _arChar = gcnew cli::array< Char >(0);
774     cli::array< Char > ^ seqCharRet = xBT2->setSequenceChar(_arChar);
775     bRet = check( compareData(seqCharRet, _arChar), "sequence test") && bRet;
776     cli::array< Int16 > ^ _arShort = gcnew cli::array< Int16 >(0);
777     cli::array< Int16 > ^ seqShortRet = xBT2->setSequenceShort(_arShort);
778     bRet = check( compareData(seqShortRet, _arShort), "sequence test") && bRet;
779     cli::array< Int32 > ^ _arLong = gcnew cli::array< Int32 >(0);
780     cli::array< Int32 > ^ seqLongRet = xBT2->setSequenceLong(_arLong);
781     bRet = check( compareData(seqLongRet, _arLong), "sequence test") && bRet;
782     cli::array< Int64 > ^ _arHyper = gcnew cli::array< Int64 >(0);
783     cli::array< Int64 > ^ seqHyperRet = xBT2->setSequenceHyper(_arHyper);
784     bRet = check( compareData(seqHyperRet, _arHyper), "sequence test") && bRet;
785     cli::array< Single > ^ _arFloat = gcnew cli::array< Single >(0);
786     cli::array< Single > ^ seqFloatRet = xBT2->setSequenceFloat(_arFloat);
787     bRet = check( compareData(seqFloatRet, _arFloat), "sequence test") && bRet;
788     cli::array< Double > ^ _arDouble = gcnew cli::array< Double >(0);
789     cli::array< Double > ^ seqDoubleRet = xBT2->setSequenceDouble(_arDouble);
790     bRet = check( compareData(seqDoubleRet, _arDouble), "sequence test") && bRet;
791     cli::array< TestEnum > ^ _arEnum = gcnew cli::array< TestEnum >(0);
792     xBT2->setSequenceEnum(_arEnum);
793 //  compiler bug: _arEnum has type System.Enum and not TestEnum
794 //    bRet = check( compareData(seqEnumRet, _arEnum), "sequence test") && bRet;
795     cli::array< UInt16 > ^ _arUShort = gcnew cli::array< UInt16 >(0);
796     cli::array< UInt16 > ^ seqUShortRet = xBT2->setSequenceUShort(_arUShort);
797     bRet = check( compareData(seqUShortRet, _arUShort), "sequence test") && bRet;
798     cli::array< UInt32 > ^ _arULong = gcnew cli::array< UInt32 >(0);
799     cli::array< UInt32 > ^ seqULongRet = xBT2->setSequenceULong(_arULong);
800     bRet = check( compareData(seqULongRet, _arULong), "sequence test") && bRet;
801     cli::array< UInt64 > ^ _arUHyper = gcnew cli::array< UInt64 >(0);
802     cli::array< UInt64 > ^ seqUHyperRet = xBT2->setSequenceUHyper(_arUHyper);
803     bRet = check( compareData(seqUHyperRet, _arUHyper), "sequence test") && bRet;
804     cli::array< Object ^ > ^ _arObject = gcnew cli::array< Object ^ >( 0 );
805     cli::array< Object ^ > ^ seqObjectRet = xBT2->setSequenceXInterface(_arObject);
806     bRet = check( compareData(seqObjectRet, _arObject), "sequence test") && bRet;
807     cli::array< String ^ > ^ _arString = gcnew cli::array< String ^ >( 0 );
808     cli::array< String ^ > ^ seqStringRet = xBT2->setSequenceString(_arString);
809     bRet = check( compareData(seqStringRet, _arString), "sequence test") && bRet;
810     cli::array< TestElement ^ > ^ _arStruct = gcnew cli::array< TestElement ^ >(0);
811     cli::array< TestElement ^ > ^ seqStructRet = xBT2->setSequenceStruct(_arStruct);
812     bRet = check( compareData(seqStructRet, _arStruct), "sequence test") && bRet;
813 
814     }
815     return bRet;
816 }
817 /** Test the System::Object method on the proxy object
818  */
819 static bool testObjectMethodsImplemention(XBridgeTest ^ xLBT)
820 {
821     bool ret = false;
822     Object ^ obj = gcnew Object();
823     XBridgeTestBase ^ xBase = dynamic_cast<XBridgeTestBase ^>(xLBT);
824     if (xBase == nullptr)
825         return false;
826     // Object.Equals
827     ret = xLBT->Equals(obj) == false;
828     ret = xLBT->Equals(xLBT) && ret;
829     ret = Object::Equals(obj, obj) && ret;
830     ret = Object::Equals(xLBT, xBase) && ret;
831     //Object.GetHashCode
832     // Don't know how to verify this. Currently it is not possible to get the object id from a proxy
833     int nHash = xLBT->GetHashCode();
834     ret = nHash == xBase->GetHashCode() && ret;
835 
836     //Object.ToString
837     // Don't know how to verify this automatically.
838     String ^ s = xLBT->ToString();
839     ret = (s->Length > 0) && ret;
840     return ret;
841 }
842 
843 
844 static bool raiseOnewayException(XBridgeTest ^ xLBT)
845 {
846     bool bReturn = true;
847     String ^ sCompare = Constants::STRING_TEST_CONSTANT;
848     try
849     {
850         // Note : the exception may fly or not (e.g. remote scenario).
851         //        When it flies, it must contain the correct elements.
852         xLBT->raiseRuntimeExceptionOneway(sCompare, xLBT->Interface );
853     }
854     catch (RuntimeException ^  e )
855     {
856         bReturn = ( xLBT->Interface == e->Context );
857     }
858     return bReturn;
859 }
860 
861 // //==================================================================================================
862 static bool raiseException(XBridgeTest ^ xLBT )
863 {
864     int nCount = 0;
865     try
866     {
867         try
868         {
869             try
870             {
871                 xLBT->raiseException(
872                     5, Constants::STRING_TEST_CONSTANT, xLBT->Interface );
873             }
874             catch (unoidl::com::sun::star::lang::IllegalArgumentException ^ aExc)
875             {
876                 if (aExc->ArgumentPosition == 5 &&
877                     aExc->Context == xLBT->Interface)
878                 {
879                     ++nCount;
880                 }
881                 else
882                 {
883                     check( false, "### unexpected exception content!" );
884                 }
885 
886                 /** it is certain, that the RuntimeException testing will fail,
887                     if no */
888                 xLBT->RuntimeException = 0;
889             }
890         }
891         catch (unoidl::com::sun::star::uno::RuntimeException ^ rExc)
892         {
893             if (rExc->Context == xLBT->Interface )
894             {
895                 ++nCount;
896             }
897             else
898             {
899                 check( false, "### unexpected exception content!" );
900             }
901 
902             /** it is certain, that the RuntimeException testing will fail, if no */
903             xLBT->RuntimeException = (int) 0xcafebabe;
904         }
905     }
906     catch (unoidl::com::sun::star::uno::Exception ^  rExc)
907     {
908         if (rExc->Context == xLBT->Interface)
909         {
910             ++nCount;
911         }
912         else
913 
914         {
915             check( false, "### unexpected exception content!" );
916         }
917         return (nCount == 3);
918     }
919     return false;
920 }
921 
922     static private void perform_test( XBridgeTest ^ xLBT )
923     {
924         bool bRet= true;
925        bRet = check( performTest( xLBT ), "standard test" ) && bRet;
926        bRet = check( raiseException( xLBT ) , "exception test" )&& bRet;
927        bRet = check( raiseOnewayException( xLBT ), "oneway exception test" ) && bRet;
928        bRet = check( testObjectMethodsImplemention(xLBT), "object methods test") && bRet;
929        bRet = performQueryForUnknownType( xLBT ) && bRet;
930         if (! bRet)
931         {
932             throw gcnew unoidl::com::sun::star::uno::RuntimeException(
933                 gcnew String("error: test failed!"), nullptr);
934         }
935     }
936     XComponentContext ^ m_xContext;
937 
938     public:
939     BridgeTest( XComponentContext ^ xContext )
940     {
941         m_xContext = xContext;
942     }
943 
944 
945 
946     virtual int run( cli::array< String ^ > ^ args )
947     {
948         try
949         {
950             if (args->Length < 1)
951             {
952                 throw gcnew RuntimeException(
953                     "missing argument for bridgetest!", this );
954             }
955             Object ^ test_obj =
956                 m_xContext->getServiceManager()->createInstanceWithContext(
957                     args[ 0 ], m_xContext );
958             if (test_obj == nullptr)
959                 test_obj = m_xContext->getValueByName( args[ 0 ] ).Value;
960 
961             Console::WriteLine(
962                 "cli target bridgetest obj: {0}", test_obj->ToString() );
963             XBridgeTest ^ xTest = safe_cast< XBridgeTest ^ >(test_obj) ;
964             perform_test( xTest );
965             Console::WriteLine( "\n### cli_uno C++  bridgetest succeeded." );
966             return 0;
967         }
968         catch (unoidl::com::sun::star::uno::RuntimeException ^ )
969         {
970             throw;
971         }
972         catch (System::Exception ^ exc)
973         {
974             System::Text::StringBuilder ^ s = gcnew System::Text::StringBuilder();
975             s->Append("cli_cpp_bridgetest: unexpected exception occurred in XMain::run. Original exception: ");
976             s->Append(exc->GetType()->Name);
977             s->Append("\n Message: ");
978             s->Append(exc->Message);
979             throw gcnew unoidl::com::sun::star::uno::RuntimeException(
980                 s->ToString(), nullptr);
981         }
982     }
983 };
984 
985 }
986