1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include <vector>
26 #include <cstdlib>
27 #include <ut/ut.h>
28 #include <protocol/protocol.h>
29 #include <base/time.h>
30 #include <base/base.h>
31 #include <base/paths.h>
32 #include "base/tests/MSFT_AllTypes.h"
33
34 #if defined(CONFIG_POSIX)
35 # include <unistd.h>
36 # include <errno.h>
37 # include <sys/socket.h>
38 # include <netinet/tcp.h>
39 # include <netinet/in.h>
40 # include <sys/time.h>
41 # include <sys/types.h>
42 # include <netdb.h>
43 mike 1.1 # include <fcntl.h>
44 # include <arpa/inet.h>
45 # include <signal.h>
46 #endif
47
48 #define PORT ut::getUnittestPortNumber()
49
50 using namespace std;
51 using namespace mi;
52
53 static vector<ProtocolEvent> s_events;
54
55 #if defined(_MSC_VER)
56 #undef BEGIN_EXTERNC
57 #undef END_EXTERNC
58 #define BEGIN_EXTERNC
59 #define END_EXTERNC
60 #endif
61
62 static void setUp()
63 {
64 mike 1.1 s_events.clear();
65 }
66
67 static void cleanup()
68 {
69 }
70
71 BEGIN_EXTERNC
72 static MI_Boolean _ServerCallback(
73 Protocol* protocol,
74 Message* message,
75 void* data)
76 {
77 // memorize request
78 Message** msgOut = (Message**)data;
79
80 UT_ASSERT( 0 == *msgOut ); // expecting only one message
81
82 *msgOut = message;
83 Message_AddRef( *msgOut );
84
85 mike 1.1 // send response
86 NoOpReq* req = (NoOpReq*)message;
87 NoOpRsp* rsp;
88
89 /* Send NoOp response back */
90 rsp = NoOpRsp_New(req->base.msgID);
91 rsp->base.clientID = req->base.clientID;
92 Protocol_Send(protocol, &rsp->base);
93 NoOpRsp_Release(rsp);
94
95 return MI_TRUE;
96 }
97 END_EXTERNC
98
99 BEGIN_EXTERNC
100 static MI_Boolean _ClientCallback(
101 Protocol* protocol,
102 Message* message,
103 void* data)
104 {
105 protocol = protocol;
106 mike 1.1
107 Message** msgOut = (Message**)data;
108
109 UT_ASSERT( 0 == *msgOut ); // expecting only one message
110
111 *msgOut = message;
112 Message_AddRef( *msgOut );
113
114 return MI_TRUE;
115 }
116 END_EXTERNC
117
118 static void TestHappyPass()
119 {
120 /* send noop-rqt and recv noop-rsp */
121 // create 2 protocols - listener and connector
122 Protocol *listener, *connector;
123 Message* recvMessageClient = 0; // response from server
124 Message* recvMessageServer = 0; // req received by server
125
126 UT_ASSERT( MI_RESULT_OK == Protocol_New_Listener(
127 mike 1.1 &listener, 0, GetPath(ID_SOCKETFILE), _ServerCallback, (void*)&recvMessageServer) );
128
129 UT_ASSERT(MI_RESULT_OK == Protocol_New_Connector(&connector, 0,
130 GetPath(ID_SOCKETFILE), _ClientCallback, (void*)&recvMessageClient, 0, 0, "unittest", "unittest"));
131
132
133 // send noop from client
134 NoOpReq* rqt = NoOpReq_New(777);
135 Protocol_Send(connector, &rqt->base);
136 NoOpReq_Release(rqt);
137
138 for ( int attempt = 0; attempt < 12 && !recvMessageClient; attempt++)
139 {
140 Protocol_Run(connector, 1000);
141 Protocol_Run(listener, 1000);
142 }
143
144 // check messages
145 UT_ASSERT( recvMessageServer );
146 UT_ASSERT( recvMessageServer->tag == NoOpReqTag );
147
148 mike 1.1 UT_ASSERT( recvMessageClient );
149 UT_ASSERT( recvMessageClient->tag == NoOpRspTag );
150 UT_ASSERT( recvMessageClient->msgID == 777 );
151
152 // free messages
153 Message_Release(recvMessageServer);
154 Message_Release(recvMessageClient);
155
156 UT_ASSERT( MI_RESULT_OK == Protocol_Delete(listener) );
157 UT_ASSERT( MI_RESULT_OK == Protocol_Delete(connector) );
158 }
159
160 BEGIN_EXTERNC
161 static void _TransferMessageUsingProtocol(
162 Message* msg,
163 Message** result,
164 bool listenerUsesExternalSelect = false,
165 bool connectorUsesExternalSelect = false,
166 Sock* socketPair = 0)
167 {
168 Selector internal_selector;
169 mike 1.1 Selector* selector = 0;
170 Message* recvMessageClient = 0; // response from server; assigned in _ClientCallback
171
172 if (listenerUsesExternalSelect || connectorUsesExternalSelect)
173 {
174 /* Initialize the network */
175 Sock_Start();
176
177 UT_ASSERT(Selector_Init(&internal_selector) == MI_RESULT_OK);
178 selector = &internal_selector;
179 }
180
181 /* send message to the server and return received message from server's callback */
182 // create 2 protocols - listener and connector
183 Protocol *listener, *connector;
184
185 if (0 == socketPair)
186 {
187 UT_ASSERT( MI_RESULT_OK == Protocol_New_Listener(
188 &listener, listenerUsesExternalSelect ? selector : 0, GetPath(ID_SOCKETFILE), _ServerCallback, (void*)result) );
189
190 mike 1.1 UT_ASSERT(MI_RESULT_OK == Protocol_New_Connector(&connector,
191 connectorUsesExternalSelect ? selector : 0, GetPath(ID_SOCKETFILE),
192 _ClientCallback, (void*)&recvMessageClient, 0, 0, "unittest", "unittest"));
193 }
194 else
195 {
196 UT_ASSERT( MI_RESULT_OK == Protocol_New_From_Socket(
197 &listener,
198 listenerUsesExternalSelect ? selector : 0,
199 socketPair[0],
200 MI_FALSE,
201 _ServerCallback, (void*)result,
202 0,0) );
203
204 UT_ASSERT(MI_RESULT_OK == Protocol_New_From_Socket(
205 &connector,
206 connectorUsesExternalSelect ? selector : 0,
207 socketPair[1],
208 MI_FALSE,
209 _ClientCallback, (void*)&recvMessageClient, 0, 0));
210 }
211 mike 1.1
212 // send noop from client
213 Protocol_Send(connector, msg);
214
215 for ( int attempt = 0; attempt < 12 && !*result; attempt++)
216 {
217 Protocol_Run(connector, 1000);
218 Protocol_Run(listener, 1000);
219 }
220
221 /* remove all handlers befroe destroying protocols */
222 if (selector)
223 Selector_RemoveAllHandlers(selector);
224
225 UT_ASSERT( MI_RESULT_OK == Protocol_Delete(listener) );
226 UT_ASSERT( MI_RESULT_OK == Protocol_Delete(connector) );
227
228 if (selector)
229 {
230 Selector_Destroy(selector);
231
232 mike 1.1 /* Shutdown the network */
233 Sock_Stop();
234 }
235
236 if (recvMessageClient)
237 Message_Release(recvMessageClient);
238
239 }
240 END_EXTERNC
241
242 static void TestTransferingEnumerateInstanceRequest()
243 {
244 EnumerateInstancesReq* msg = EnumerateInstancesReq_New( 1444, BinaryProtocolFlag );
245 Message* result = 0;
246
247 msg->deepInheritance = MI_TRUE;
248 msg->nameSpace = Batch_Strdup2(msg->base.batch, "name_space");
249 msg->className = Batch_Strdup2(msg->base.batch, "class_name");
250
251 _TransferMessageUsingProtocol( &msg->base, &result );
252
253 mike 1.1 /* free source message */
254 UT_ASSERT(msg->base.refCounter == 1);
255 EnumerateInstancesReq_Release(msg);
256
257 /* check received result */
258 UT_ASSERT( result );
259 UT_ASSERT( result->tag == EnumerateInstancesReqTag );
260
261 {
262 EnumerateInstancesReq* rsp = (EnumerateInstancesReq*)result;
263 UT_ASSERT( Zcmp(rsp->nameSpace, MI_T("name_space")) == 0 );
264 UT_ASSERT( Zcmp(rsp->className, MI_T("class_name")) == 0 );
265 UT_ASSERT( rsp->deepInheritance );
266 }
267
268 UT_ASSERT(result->refCounter == 1);
269 Message_Release(result);
270 }
271
272 static void TestTransferingResult()
273 {
274 mike 1.1 PostResultMsg* msg = PostResultMsg_New( 1444 );
275 Message* result = 0;
276
277 msg->result = MI_RESULT_NOT_FOUND;
278
279 _TransferMessageUsingProtocol( &msg->base, &result );
280
281 /* free source message */
282 UT_ASSERT(msg->base.refCounter == 1);
283 PostResultMsg_Release(msg);
284
285 /* check received result */
286 UT_ASSERT( result );
287 UT_ASSERT( result->tag == PostResultMsgTag );
288
289 {
290 PostResultMsg* rsp = (PostResultMsg*)result;
291 UT_ASSERT( rsp->result == MI_RESULT_NOT_FOUND);
292 }
293
294 UT_ASSERT(result->refCounter == 1);
295 mike 1.1 Message_Release(result);
296 }
297
298 BEGIN_EXTERNC
299 static void _DynamicToStatikInstance(
300 MI_Instance* dynamicInst,
301 Batch* batch,
302 MSFT_AllTypes_Class& inst)
303 {
304 MI_Instance* instOut = 0;
305
306 /* Allocate the instance for the provider */
307 instOut = (MI_Instance*)Batch_GetClear(batch,
308 MSFT_AllTypes_rtti.size);
309
310 /* Convert instance name to provider's format (borrow storage) */
311 MI_Result r = Instance_InitConvert(
312 instOut,
313 &MSFT_AllTypes_rtti,
314 dynamicInst,
315 MI_FALSE,
316 mike 1.1 MI_FALSE,
317 MI_FALSE,
318 batch);
319
320 UT_ASSERT( MI_RESULT_OK == r );
321
322 inst = MSFT_AllTypes_Class((const MSFT_AllTypes *)instOut, false);
323 }
324 END_EXTERNC
325
326 static void TestTransferingGetInstanceReqt()
327 {
328 GetInstanceReq* msg = GetInstanceReq_New( 1444, BinaryProtocolFlag );
329 Message* result = 0;
330
331 msg->nameSpace = Batch_Strdup2(msg->base.batch, "name_space");
332
333 // instance - reuse cxx sample instance
334 MSFT_AllTypes_Class inst;
335
336 // note - get-instance transfers keys only
337 mike 1.1 inst.Key_value(8);
338
339 UT_ASSERT( MI_RESULT_OK == InstanceToBatch(
340 *((MI_Instance**)&inst), NULL, NULL, msg->base.batch,
341 &msg->packedInstanceNamePtr, &msg->packedInstanceNameSize));
342
343 msg->includeClassOrigin = MI_TRUE;
344
345 _TransferMessageUsingProtocol( &msg->base, &result );
346
347 /* free source message */
348 UT_ASSERT(msg->base.refCounter == 1);
349 GetInstanceReq_Release(msg);
350
351 /* check received result */
352 UT_ASSERT( result );
353 UT_ASSERT( result->tag == GetInstanceReqTag );
354
355 {
356 GetInstanceReq* rsp = (GetInstanceReq*)result;
357 UT_ASSERT( Zcmp(rsp->nameSpace, MI_T("name_space")) == 0 );
358 mike 1.1 UT_ASSERT( rsp->includeClassOrigin );
359
360 // instance
361 UT_ASSERT(rsp->instanceName);
362 //MSFT_AllTypesClass recv_inst((const MSFT_AllTypes *)rsp->instanceName, false);
363 MSFT_AllTypes_Class recv_inst;
364 _DynamicToStatikInstance( rsp->instanceName, rsp->base.batch, recv_inst );
365
366 UT_ASSERT(recv_inst.Key_value() == 8);
367 }
368
369 UT_ASSERT(result->refCounter == 1);
370 Message_Release(result);
371 }
372
373 static void TestTransferingPostInstance()
374 {
375 PostInstanceMsg* msg = PostInstanceMsg_New( 1444 );
376 Message* result = 0;
377
378 // instance - reuse cxx sample instance
379 mike 1.1 MSFT_AllTypes_Class inst;
380 MI_ConstString test_string = MI_T("some very very very long string 1111111111111111111111111111111111111111111111111111111111111\
381 12333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333");
382
383 inst.Key_value(8);
384 inst.StringValue_value(test_string);
385
386 UT_ASSERT( MI_RESULT_OK == InstanceToBatch(
387 *((MI_Instance**)&inst), NULL, NULL, msg->base.batch,
388 &msg->packedInstancePtr, &msg->packedInstanceSize));
389
390 _TransferMessageUsingProtocol( &msg->base, &result );
391
392 /* free source message */
393 UT_ASSERT(msg->base.refCounter == 1);
394 PostInstanceMsg_Release(msg);
395
396 /* check received result */
397 UT_ASSERT( result );
398 UT_ASSERT( result->tag == PostInstanceMsgTag );
399
400 mike 1.1 {
401 PostInstanceMsg* rsp = (PostInstanceMsg*)result;
402
403 // instance
404 UT_ASSERT(rsp->instance);
405 //MSFT_AllTypesClass recv_inst((const MSFT_AllTypes *)rsp->instance, false);
406 MSFT_AllTypes_Class recv_inst;
407 _DynamicToStatikInstance( rsp->instance, rsp->base.batch, recv_inst );
408
409 UT_ASSERT(recv_inst.Key_value() == 8);
410 UT_ASSERT(recv_inst.StringValue_value() == test_string);
411 }
412
413 UT_ASSERT(result->refCounter == 1);
414 Message_Release(result);
415 }
416
417 BEGIN_EXTERNC
418 static void _TestTransferingInvoke(bool listenerUsesExternalSelect, bool connectorUsesExternalSelect, Sock* socketPair)
419 {
420 InvokeReq* msg = InvokeReq_New( 1444, BinaryProtocolFlag );
421 mike 1.1 Message* result = 0;
422
423 msg->nameSpace = Batch_Strdup2(msg->base.batch, "name_space");
424 msg->function = Batch_Strdup2(msg->base.batch, "function");
425 msg->className = Batch_Strdup2(msg->base.batch, "className");
426
427 // instance - reuse cxx sample instance
428 MSFT_AllTypes_Class inst;
429 MI_ConstString test_string = MI_T("some very very very long string 1111111111111111111111111111111111111111111111111111111111111\
430 12333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333");
431
432 inst.Key_value(8);
433 inst.StringValue_value(test_string);
434
435 UT_ASSERT( MI_RESULT_OK == InstanceToBatch(
436 *((MI_Instance**)&inst), NULL, NULL, msg->base.batch,
437 &msg->packedInstancePtr, &msg->packedInstanceSize));
438
439 UT_ASSERT( MI_RESULT_OK == InstanceToBatch(
440 *((MI_Instance**)&inst), NULL, NULL, msg->base.batch,
441 &msg->packedInstanceParamsPtr, &msg->packedInstanceParamsSize));
442 mike 1.1
443 _TransferMessageUsingProtocol( &msg->base, &result, listenerUsesExternalSelect, connectorUsesExternalSelect, socketPair );
444
445 /* free source message */
446 UT_ASSERT(msg->base.refCounter == 1);
447 InvokeReq_Release(msg);
448
449 /* check received result */
450 UT_ASSERT( result );
451 UT_ASSERT( result->tag == InvokeReqTag );
452
453 {
454 InvokeReq* rsp = (InvokeReq*)result;
455
456 UT_ASSERT( Zcmp(rsp->nameSpace, MI_T("name_space")) == 0 );
457 UT_ASSERT( Zcmp(rsp->function, MI_T("function")) == 0 );
458 UT_ASSERT( Zcmp(rsp->className, MI_T("className")) == 0 );
459
460 // instance
461 UT_ASSERT(rsp->instance);
462 UT_ASSERT(rsp->instanceParams);
463 mike 1.1 MSFT_AllTypes_Class recv_inst, recv_inst_params;
464 _DynamicToStatikInstance( rsp->instance, rsp->base.batch, recv_inst );
465 _DynamicToStatikInstance( rsp->instanceParams, rsp->base.batch, recv_inst_params );
466
467 UT_ASSERT(recv_inst.Key_value() == 8);
468 UT_ASSERT(recv_inst.StringValue_value() == test_string);
469
470 UT_ASSERT(recv_inst_params.Key_value() == 8);
471 UT_ASSERT(recv_inst_params.StringValue_value() == test_string);
472 }
473
474 UT_ASSERT(result->refCounter == 1);
475 Message_Release(result);
476 }
477 END_EXTERNC
478
479 static void TestTransferingInvoke()
480 {
481 _TestTransferingInvoke(false, false, 0);
482 }
483
484 mike 1.1 static void TestTransferingInvokeWithExternalSelector()
485 {
486 _TestTransferingInvoke(true, false, 0);
487 _TestTransferingInvoke(false, true, 0);
488 _TestTransferingInvoke(true, true, 0);
489 }
490
491 BEGIN_EXTERNC
492 static void _ProtocolEventCallback(
493 Protocol* protocol,
494 ProtocolEvent event,
495 void* data)
496 {
497 MI_UNUSED(protocol);
498 MI_UNUSED(data);
499
500 s_events.push_back(event);
501 }
502 END_EXTERNC
503
504 static void TestProtocolConnectOK()
505 mike 1.1 {
506 // create 2 protocols - listener and connector
507 Protocol *listener, *connector;
508 Message* recvMessageClient = 0; // response from server
509 Message* recvMessageServer = 0; // req received by server
510
511 UT_ASSERT( MI_RESULT_OK == Protocol_New_Listener(
512 &listener, 0, GetPath(ID_SOCKETFILE), _ServerCallback, (void*)&recvMessageServer) );
513
514 UT_ASSERT(MI_RESULT_OK == Protocol_New_Connector(&connector,
515 0, GetPath(ID_SOCKETFILE),
516 _ClientCallback, (void*)&recvMessageClient, _ProtocolEventCallback, 0, "unittest", "unittest"));
517
518 // send noop from client
519 NoOpReq* rqt = NoOpReq_New(777);
520 Protocol_Send(connector, &rqt->base);
521 NoOpReq_Release(rqt);
522
523 for ( int attempt = 0; attempt < 100 && !recvMessageClient; attempt++)
524 {
525 Protocol_Run(connector, 1000);
526 mike 1.1 Protocol_Run(listener, 1000);
527 }
528
529 // verify connect event
530 UT_ASSERT(s_events.size() == 1);
531 UT_ASSERT(s_events[0] == PROTOCOLEVENT_CONNECT);
532
533
534 UT_ASSERT( MI_RESULT_OK == Protocol_Delete(listener) );
535 s_events.clear();
536
537 // verify disconnect event
538 for ( int attempt = 0; attempt < 2 && s_events.empty(); attempt++)
539 {
540 Protocol_Run(connector, 1000);
541 }
542
543 UT_ASSERT(s_events.size() == 1);
544 UT_ASSERT(s_events[0] == PROTOCOLEVENT_DISCONNECT);
545
546 UT_ASSERT( MI_RESULT_OK == Protocol_Delete(connector) );
547 mike 1.1
548 // check messages
549 UT_ASSERT( recvMessageServer );
550 UT_ASSERT( recvMessageServer->tag == NoOpReqTag );
551
552 UT_ASSERT( recvMessageClient );
553 UT_ASSERT( recvMessageClient->tag == NoOpRspTag );
554 UT_ASSERT( recvMessageClient->msgID == 777 );
555
556 // free messages
557 Message_Release(recvMessageServer);
558 Message_Release(recvMessageClient);
559
560 }
561
562 static void TestProtocolConnectFailed()
563 {
564 // create only connector - should fail to connect
565 Protocol *connector;
566
567 MI_Result r = Protocol_New_Connector(&connector,
568 mike 1.1 0, GetPath(ID_SOCKETFILE),
569 _ClientCallback, 0, _ProtocolEventCallback, 0, "unittest", "unittest");
570
571 /* some platforms return 'failed' from connect even with non-blocking sockets */
572 if (MI_RESULT_FAILED == r)
573 return;
574
575 UT_ASSERT(MI_RESULT_OK == r);
576
577 // send noop from client
578 NoOpReq* rqt = NoOpReq_New(777);
579 Protocol_Send(connector, &rqt->base);
580 NoOpReq_Release(rqt);
581
582 for ( int attempt = 0; attempt < 10000 && s_events.empty(); attempt++)
583 {
584 Protocol_Run(connector, 1000);
585 }
586
587 // verify connect-failed event
588 UT_ASSERT(s_events.size() == 1);
589 mike 1.1 UT_ASSERT(s_events[0] == PROTOCOLEVENT_CONNECT_FAILED);
590
591 UT_ASSERT( MI_RESULT_OK == Protocol_Delete(connector) );
592 }
593
594 #ifdef CONFIG_POSIX
595 static void TestFromSocket()
596 {
597 Sock s[2];
598
599 UT_ASSERT(0 == socketpair(AF_UNIX, SOCK_STREAM, 0, s));
600 UT_ASSERT( MI_RESULT_OK == Sock_SetBlocking(s[0], MI_FALSE));
601 UT_ASSERT( MI_RESULT_OK == Sock_SetBlocking(s[1], MI_FALSE));
602
603 _TestTransferingInvoke(true, true, s);
604 }
605 #endif
606
607 static void RunTests()
608 {
609 #if defined(CONFIG_POSIX)
610 mike 1.1 /* Disable Auth for unit-tests */
611 IgnoreAuthCalls(1);
612 #endif
613
614 UT_TEST(TestHappyPass);
615 UT_TEST(TestTransferingEnumerateInstanceRequest);
616 UT_TEST(TestTransferingResult);
617 UT_TEST(TestTransferingGetInstanceReqt);
618 UT_TEST(TestTransferingPostInstance);
619 UT_TEST(TestTransferingInvokeWithExternalSelector);
620 UT_TEST(TestTransferingInvoke);
621
622 // Test protocol events
623 UT_TEST(TestProtocolConnectFailed);
624 UT_TEST(TestProtocolConnectOK);
625
626 #ifdef CONFIG_POSIX
627 UT_TEST(TestFromSocket);
628
629 #endif
630 }
631 mike 1.1
632 UT_ENTRY_POINT(RunTests);
|