1 krisbash 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 krisbash 1.1 **==============================================================================
23 */
24
25 #include <vector>
26 #include <algorithm>
27 #include <ut/ut.h>
28 #include <indication/indimgr/classlist.h>
29 #include <indication/indimgr/host.h>
30 #include <pal/strings.h>
31 #include <pal/dir.h>
32 #include <base/paths.h>
33 #include <omi_error/OMI_Error.h>
34 #include "util.h"
35
36 using namespace std;
37
38 struct Test_ClasslistStruct
39 {
40 MI_ConstString query;
41 MI_ConstString queryDialect;
42 MI_ConstString nameSpace;
43 krisbash 1.1 Filter* filter;
44 MI_Boolean pregInited;
45 ProvReg* preg;
46 MI_Result lastErrorCode;
47 MI_Instance* lastError;
48 };
49
50 NITS_EXTERN_C void _ClassList_SetLastError(
51 _In_opt_ void* context,
52 _In_ MI_Instance* error,
53 MI_Result result)
54 {
55 Test_ClasslistStruct* tcs = (Test_ClasslistStruct*)context;
56 tcs->lastError = error;
57 tcs->lastErrorCode = result;
58 }
59
60 int _Filter_SetOneNamespace(_Inout_ Filter* self,
61 _In_ MI_ConstString nameSpace)
62 {
63 MI_StringA nsa;
64 krisbash 1.1 MI_String data[1];
65 nsa.size = 1;
66 nsa.data = data;
67 data[0] = (MI_Char*)nameSpace;
68 /* Clean _container field to workaround limitation of Filter_SetNamespace */
69 void* container = self->base.base._container;
70 self->base.base._container = NULL;
71 int r = Filter_SetNamespace(self, &nsa);
72 /* Reset _container field */
73 self->base.base._container = container;
74 return r;
75 }
76
77 void Test_ClasslistStruct_ResetLastError(
78 _In_ Test_ClasslistStruct* tcs)
79 {
80 if (tcs->lastError)
81 MI_Instance_Delete(tcs->lastError);
82 tcs->lastError = NULL;
83 tcs->lastErrorCode = MI_RESULT_OK;
84 }
85 krisbash 1.1
86 IndicationHost g_HostDefault = {NULL, NULL, NULL};
87
88
89 NitsSetup0(Test_Setup, Test_ClasslistStruct)
90 Test_ClasslistStruct* tcs = NitsContext()->_Test_ClasslistStruct;
91 tcs->lastError = NULL;
92 tcs->lastErrorCode = MI_RESULT_OK;
93
94 string root = OMI_GetPath(ID_PREFIX);
95 string omiregdir = root + "/tests/provreg/omiregister";
96 ProvReg* preg = (ProvReg*)PAL_Malloc(sizeof(ProvReg));
97 NitsAssert(NULL != preg, PAL_T("Failed to create ProgReg object"));
98 if (NULL == preg)
99 return;
100
101 tcs->preg = preg;
102 MI_Result r = ProvReg_Init(tcs->preg, omiregdir.c_str());
103 NitsAssert(r == MI_RESULT_OK, PAL_T("Failed to initialize ProgReg"));
104 tcs->pregInited = (r == MI_RESULT_OK) ? MI_TRUE : MI_FALSE;
105 Filter* filter = Filter_New(tcs->query, tcs->queryDialect, &tcs->lastError);
106 krisbash 1.1 NitsAssert(NULL != filter, PAL_T("Failed to create filter object"));
107 if (filter)
108 {
109 int r = _Filter_SetOneNamespace(filter, tcs->nameSpace);
110 NitsAssert(0 == r, PAL_T("Failed to set namespaces to filter object"));
111 filter->base.errhandler.context = (void*)tcs;
112 filter->base.errhandler.setlasterror = _ClassList_SetLastError;
113 filter->base.base._container = &g_HostDefault;
114
115 if (r == 0)
116 tcs->filter = filter;
117 }
118 NitsEndSetup
119
120
121 NitsCleanup(Test_Setup)
122 Test_ClasslistStruct* tcs = NitsContext()->_Test_ClasslistStruct;
123 if (MI_TRUE == tcs->pregInited)
124 {
125 ProvReg_Destroy(tcs->preg);
126 tcs->pregInited = MI_FALSE;
127 krisbash 1.1 }
128 if (NULL != tcs->preg)
129 {
130 PAL_Free(tcs->preg);
131 tcs->preg = NULL;
132 }
133 if (tcs->filter)
134 {
135 Filter_Release(tcs->filter);
136 tcs->filter = NULL;
137 }
138 if (tcs->lastError)
139 {
140 MI_Instance_Delete(tcs->lastError);
141 tcs->lastError = NULL;
142 }
143 NitsEndCleanup
144
145 static struct Test_ClasslistStruct sTestCS1 = {
146 MI_T("select * from XYZ_ChildIndication1"),
147 QUERY_LANGUAGE_WQL,
148 krisbash 1.1 MI_T("root/indication"),
149 NULL,
150 MI_FALSE,
151 NULL};
152
153 NitsTest1(TestClassList_Success_OneClass, Test_Setup, sTestCS1)
154 ProvReg* preg = NitsContext()->_Test_Setup->_Test_ClasslistStruct->preg;
155 Filter* filter = NitsContext()->_Test_Setup->_Test_ClasslistStruct->filter;
156
157 IndicationClassList* clist = IndicationClassList_NewByFilter(preg, filter);
158 NitsAssert(NULL != clist, PAL_T("failed to create classlist"));
159 if (NULL == clist)
160 return;
161 IndicationClassEntry* pce = clist->head;
162 NitsAssert(NULL != pce, PAL_T("ClassList is empty"));
163 if (pce)
164 {
165 NitsAssert(Tcscasecmp(pce->regentry->className, MI_T("XYZ_ChildIndication1")) == 0, PAL_T("Unexpected class was found"));
166 NitsAssert(NULL == pce->next, PAL_T("ClassList contains more than 1 class"));
167 }
168 IndicationClassList_Delete(clist);
169 krisbash 1.1 NitsEndTest
170
171 void _VerifyIndicaitonClassDiscoveryResult(
172 _In_ Test_ClasslistStruct* tcs,
173 _In_opt_ StringTagElement* ste,
174 _In_ MI_Uint32 steSize,
175 _In_ MI_Result errorCode = MI_RESULT_OK)
176 {
177 ProvReg* preg = tcs->preg;
178 Filter* filter = tcs->filter;
179 Test_ClasslistStruct_ResetLastError(tcs);
180 IndicationClassList* clist = IndicationClassList_NewByFilter(preg, filter);
181 if (errorCode == MI_RESULT_OK)
182 {
183 NitsAssert(NULL != clist, PAL_T("failed to create classlist"));
184 }
185 else
186 {
187 NitsCompare(errorCode, tcs->lastErrorCode, PAL_T("Unexpected error code"));
188 }
189
190 krisbash 1.1 if (NULL == clist)
191 return;
192
193 NitsAssert(NULL != clist->head, PAL_T("ClassList is empty"));
194 IndicationClassEntry* pce = clist->head;
195
196 /* copy sTestCS2_ClassList to classlist */
197 MI_Uint32 steBytesSize = sizeof(StringTagElement) * steSize;
198 StringTagElement* classlist = (StringTagElement*)PAL_Malloc(steBytesSize);
199 if (classlist == NULL)
200 {
201 NitsAssert(false, PAL_T("Allocate memory for classlist failed"));
202 IndicationClassList_Delete(clist);
203 return;
204 }
205
206 memcpy(classlist, ste, steBytesSize);
207 while(pce)
208 {
209 NitsAssert(1 == IsInArray(pce->regentry->className, classlist, steSize), PAL_T("Unexpected class was found"));
210 pce = pce->next;
211 krisbash 1.1 }
212 for (MI_Uint32 i = 0; i < steSize; i++)
213 {
214 if (classlist[i].tag != 1)
215 NitsAssert(false, PAL_T("Some class was not in classlist"));
216 }
217 PAL_Free(classlist);
218 IndicationClassList_Delete(clist);
219 }
220
221 static StringTagElement sTestCS2_ClassList[] =
222 {
223 { MI_T("XYZ_Indication"),0, 0},
224 { MI_T("XYZ_ChildIndication1"),0, 0},
225 { MI_T("XYZ_ChildIndication2"),0, 0},
226 { MI_T("XYZ_ChildIndication3"),0, 0},
227 { MI_T("XYZ_ChildIndication4"),0, 0},
228 };
229
230 static struct Test_ClasslistStruct sTestCS2 = {
231 MI_T("select * from CIM_IndicatiON"),
232 krisbash 1.1 QUERY_LANGUAGE_CQL,
233 MI_T("root/indication"),
234 NULL,
235 MI_FALSE,
236 NULL};
237
238 NitsTest1(TestClassList_Success_ClassHierarchy, Test_Setup, sTestCS2)
239 _VerifyIndicaitonClassDiscoveryResult(
240 NitsContext()->_Test_Setup->_Test_ClasslistStruct,
241 sTestCS2_ClassList,
242 MI_COUNT(sTestCS2_ClassList));
243 NitsEndTest
244
245 NitsTest1(TestClassList_NonexistNamespace, Test_Setup, sTestCS2)
246 Test_ClasslistStruct* tcs = NitsContext()->_Test_Setup->_Test_ClasslistStruct;
247 ProvReg* preg = tcs->preg;
248 Filter* filter = tcs->filter;
249 int r = _Filter_SetOneNamespace(filter, MI_T("nonexist/namespace"));
250 NitsAssert(0 == r, PAL_T("Failed to set namespaces to filter object"));
251 if (r == 0)
252 {
253 krisbash 1.1 Test_ClasslistStruct_ResetLastError(tcs);
254 IndicationClassList* clist = IndicationClassList_NewByFilter(preg, filter);
255 NitsAssert(NULL == clist, PAL_T("Should found no class"));
256 NitsIgnoringError(); // this is negative case and OOM and the user error result in same thing
257 }
258 NitsEndTest
259
260 static struct Test_ClasslistStruct sTestCS4 = {
261 MI_T("select * from CIM_NonExistIndication"),
262 QUERY_LANGUAGE_CQL,
263 MI_T("root/indication"),
264 NULL,
265 MI_FALSE,
266 NULL};
267 NitsTest1(TestClassList_NotFoundClass, Test_Setup, sTestCS4)
268 Test_ClasslistStruct* tcs = NitsContext()->_Test_Setup->_Test_ClasslistStruct;
269 ProvReg* preg = tcs->preg;
270 Filter* filter = tcs->filter;
271 Test_ClasslistStruct_ResetLastError(tcs);
272 IndicationClassList* clist = IndicationClassList_NewByFilter(preg, filter);
273 NitsAssert(NULL == clist, PAL_T("Unexpected class was discovered"));
274 krisbash 1.1 NitsIgnoringError(); // this is negative case and OOM and the user error result in same thing
275 NitsEndTest
276
277 /*
278 **==============================================================================
279 **
280 ** Positive test for lifecycle indication query
281 **
282 ** Following test case is designed to test discovery Indication Classes for a
283 ** given lifecycle query; Although the query is not a valid lifecycle query
284 ** since it has no isa operator; but there are explicit indication class derives
285 ** from CIM_InstIndication class under target namespace, so it is a supported
286 ** scenario
287 **
288 **==============================================================================
289 */
290 static StringTagElement sTestCS5_ClassList[] =
291 {
292 { MI_T("TEST_ProcessCreated"),0, 0},
293 { MI_T("TEST_ProcessTerminated"),0, 0},
294 };
295 krisbash 1.1 static struct Test_ClasslistStruct sTestCS5 = {
296 MI_T("select * from CIM_InstIndication"),
297 QUERY_LANGUAGE_CQL,
298 MI_T("root/indication2"),
299 NULL,
300 MI_FALSE,
301 NULL};
302 NitsTest1(TestClassList_Success_Lifecycle_IndicationClassOnly, Test_Setup, sTestCS5)
303 _VerifyIndicaitonClassDiscoveryResult(
304 NitsContext()->_Test_Setup->_Test_ClasslistStruct,
305 sTestCS5_ClassList,
306 MI_COUNT(sTestCS5_ClassList),
307 MI_RESULT_OK);
308 NitsEndTest
309
310 /*
311 **==============================================================================
312 **
313 ** Positive test for lifecycle indication query
314 ** Following test cases are designed to test discoverying Indication Classes for a
315 ** given lifecycle query targets to both indication & normal classes
316 krisbash 1.1 **
317 **==============================================================================
318 */
319 static StringTagElement s_ClassListMixed[] =
320 {
321 { MI_T("TEST_ProcessCreated"),0, 0},
322 { MI_T("TEST_ProcessTerminated"),0, 0},
323 { MI_T("MSFT_Person"),0, 0},
324 { MI_T("MSFT_Person2"),0, 0},
325 };
326 static struct Test_ClasslistStruct sTestCS_Mixed1 = {
327 MI_T("select * from CIM_InstIndication where SourceInstance isa MSFT_Base"),
328 QUERY_LANGUAGE_CQL,
329 MI_T("root/indication2"),
330 NULL,
331 MI_FALSE,
332 NULL};
333 NitsTest1(TestClassList_Success_Lifecycle_Mixed, Test_Setup, sTestCS_Mixed1)
334 _VerifyIndicaitonClassDiscoveryResult(
335 NitsContext()->_Test_Setup->_Test_ClasslistStruct,
336 s_ClassListMixed,
337 krisbash 1.1 MI_COUNT(s_ClassListMixed),
338 MI_RESULT_OK);
339 NitsEndTest
340
341 static struct Test_ClasslistStruct sTestCS_Mixed2 = {
342 MI_T("select * from CIM_InstIndication where (SourceInstance isa MSFT_Base) AND ((SourceInstanceHost <> NULL) OR (SourceInstanceHost <> \"test\"))"),
343 QUERY_LANGUAGE_CQL,
344 MI_T("root/indication2"),
345 NULL,
346 MI_FALSE,
347 NULL};
348 NitsTest1(TestClassList_Success_Lifecycle_Mixed2, Test_Setup, sTestCS_Mixed2)
349 _VerifyIndicaitonClassDiscoveryResult(
350 NitsContext()->_Test_Setup->_Test_ClasslistStruct,
351 s_ClassListMixed,
352 MI_COUNT(s_ClassListMixed),
353 MI_RESULT_OK);
354 NitsEndTest
355
356 /*
357 **==============================================================================
358 krisbash 1.1 **
359 ** Positive test for lifecycle indication query
360 ** Following test cases are designed to test discoverying Indication Classes for a
361 ** given lifecycle query targets to only normal classes (no indication class
362 ** inherits from CIM_InstModification under root/indication2
363 **
364 **==============================================================================
365 */
366 static StringTagElement s_ClassList_NormalClassOnly[] =
367 {
368 { MI_T("MSFT_Person"),0, 0},
369 { MI_T("MSFT_Person2"),0, 0},
370 };
371 static struct Test_ClasslistStruct sTestCS_NormalClassOnly = {
372 MI_T("select * from CIM_InstModification where (SourceInstance isa MSFT_Animal) AND (PreviousInstance <> NULL)"),
373 QUERY_LANGUAGE_CQL,
374 MI_T("root/indication2"),
375 NULL,
376 MI_FALSE,
377 NULL};
378 NitsTest1(TestClassList_Success_Lifecycle_Mixed3, Test_Setup, sTestCS_NormalClassOnly)
379 krisbash 1.1 _VerifyIndicaitonClassDiscoveryResult(
380 NitsContext()->_Test_Setup->_Test_ClasslistStruct,
381 s_ClassList_NormalClassOnly,
382 MI_COUNT(s_ClassList_NormalClassOnly),
383 MI_RESULT_OK);
384 NitsEndTest
385
386 static struct Test_ClasslistStruct sTestCS_NormalClassOnly2 = {
387 MI_T("select * from CIM_InstModification where (PreviousInstance isa MSFT_Base) AND ((SourceInstanceHost <> NULL) OR (SourceInstanceHost <> \"test\") OR (2>1) )"),
388 QUERY_LANGUAGE_CQL,
389 MI_T("root/indication2"),
390 NULL,
391 MI_FALSE,
392 NULL};
393 NitsTest1(TestClassList_Success_Lifecycle_Mixed4, Test_Setup, sTestCS_NormalClassOnly2)
394 _VerifyIndicaitonClassDiscoveryResult(
395 NitsContext()->_Test_Setup->_Test_ClasslistStruct,
396 s_ClassList_NormalClassOnly,
397 MI_COUNT(s_ClassList_NormalClassOnly),
398 MI_RESULT_OK);
399 NitsEndTest
400 krisbash 1.1
401 /*
402 **==============================================================================
403 **
404 ** Positive test for lifecycle indication query
405 ** Following test cases are designed to test discoverying Indication Classes for a
406 ** given lifecycle query targets to only one class
407 **
408 **==============================================================================
409 */
410 static StringTagElement s_ClassList_OneClass[] =
411 {
412 { MI_T("MSFT_Person2"),0, 0},
413 };
414 static struct Test_ClasslistStruct sTestCS_OneClass = {
415 MI_T("select * from CIM_InstMethodCall where (SourceInstance ISA MSFT_Person2)"),
416 QUERY_LANGUAGE_CQL,
417 MI_T("root/indication2"),
418 NULL,
419 MI_FALSE,
420 NULL};
421 krisbash 1.1 NitsTest1(TestClassList_Success_Lifecycle_OneClass, Test_Setup, sTestCS_OneClass)
422 _VerifyIndicaitonClassDiscoveryResult(
423 NitsContext()->_Test_Setup->_Test_ClasslistStruct,
424 s_ClassList_OneClass,
425 MI_COUNT(s_ClassList_OneClass),
426 MI_RESULT_OK);
427 NitsEndTest
428
429 /*
430 **==============================================================================
431 **
432 ** Negative test for lifecycle indication query,
433 ** no indication class found
434 **
435 **==============================================================================
436 */
437 static struct Test_ClasslistStruct sTestCS_NOTFOUND = {
438 MI_T("select * from CIM_InstRead where SourceInstance isa NON_EXIST_CLASS"),
439 QUERY_LANGUAGE_CQL,
440 MI_T("root/indication2"),
441 NULL,
442 krisbash 1.1 MI_FALSE,
443 NULL};
444 NitsTest1(TestClassList_Fail_Lifecycle_NOT_FOUND, Test_Setup, sTestCS_NOTFOUND)
445 Test_ClasslistStruct* tcs = NitsContext()->_Test_Setup->_Test_ClasslistStruct;
446 _VerifyIndicaitonClassDiscoveryResult(
447 tcs,
448 NULL,
449 0,
450 MI_RESULT_NOT_FOUND);
451 NitsEndTest
452
453 /*
454 **==============================================================================
455 **
456 ** Negative test for lifecycle indication query,
457 ** Invalid lifecycle indication query: ISA operator WITHIN OR sub-clause
458 **
459 **==============================================================================
460 */
461 static struct Test_ClasslistStruct sTestCS_InvalidQuery1 = {
462 MI_T("select * from CIM_InstRead where (SourceInstance isa UnkownClass) OR (2>1)"),
463 krisbash 1.1 QUERY_LANGUAGE_CQL,
464 MI_T("root/indication2"),
465 NULL,
466 MI_FALSE,
467 NULL};
468 NitsTest1(TestClassList_Fail_Lifecycle_InvalidQuery1, Test_Setup, sTestCS_InvalidQuery1)
469 Test_ClasslistStruct* tcs = NitsContext()->_Test_Setup->_Test_ClasslistStruct;
470 _VerifyIndicaitonClassDiscoveryResult(
471 tcs,
472 NULL,
473 0,
474 MI_RESULT_NOT_SUPPORTED);
475 NitsEndTest
476
477 /*
478 **==============================================================================
479 **
480 ** Negative test for lifecycle indication query,
481 ** Invalid lifecycle indication query: Non-exist embedded property name
482 **
483 **==============================================================================
484 krisbash 1.1 */
485 static struct Test_ClasslistStruct sTestCS_InvalidQuery2 = {
486 MI_T("select * from CIM_InstRead where (UnknownProperty isa MSFT_Base)"),
487 QUERY_LANGUAGE_CQL,
488 MI_T("root/indication2"),
489 NULL,
490 MI_FALSE,
491 NULL};
492 NitsTest1(TestClassList_Fail_Lifecycle_InvalidQuery2, Test_Setup, sTestCS_InvalidQuery2)
493 Test_ClasslistStruct* tcs = NitsContext()->_Test_Setup->_Test_ClasslistStruct;
494 _VerifyIndicaitonClassDiscoveryResult(
495 tcs,
496 NULL,
497 0,
498 MI_RESULT_INVALID_QUERY);
499 NitsEndTest
500
501 /*
502 **==============================================================================
503 **
504 ** Negative test for lifecycle indication query,
505 krisbash 1.1 ** Invalid lifecycle indication query: ISA operator WITHIN OR clause
506 **
507 **==============================================================================
508 */
509 static struct Test_ClasslistStruct sTestCS_InvalidQuery3 = {
510 MI_T("select * from CIM_InstModification where (PreviousInstance isa MSFT_Base) AND ((SourceInstanceHost <> NULL) AND (SourceInstanceHost <> \"test\")) OR (2>1)"),
511 QUERY_LANGUAGE_CQL,
512 MI_T("root/indication2"),
513 NULL,
514 MI_FALSE,
515 NULL};
516 NitsTest1(TestClassList_Fail_Lifecycle_InvalidQuery3, Test_Setup, sTestCS_InvalidQuery3)
517 Test_ClasslistStruct* tcs = NitsContext()->_Test_Setup->_Test_ClasslistStruct;
518 _VerifyIndicaitonClassDiscoveryResult(
519 tcs,
520 NULL,
521 0,
522 MI_RESULT_NOT_SUPPORTED);
523 NitsEndTest
524
|