/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
**
** Licensed under the Apache License, Version 2.0 (the "License"); you may not
** use this file except in compliance with the License. You may obtain a copy
** of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
** MERCHANTABLITY OR NON-INFRINGEMENT.
**
** See the Apache 2 License for the specific language governing permissions
** and limitations under the License.
**
**==============================================================================
*/
#include <string>
#include <vector>
#include <iostream>
#include <ut/ut.h>
#include <base/lib.h>
#include <base/paths.h>
#include <base/base.h>
#if MI_CHAR_TYPE == 1
typedef std::string String;
#else
typedef std::wstring String;
#endif
static inline void* LoadLib(const char* file)
{
char path[MAX_PATH_SIZE];
Lib_Format(path, GetPath(ID_LIBDIR), file);
void* lib = Lib_Open(path);
if (lib)
return lib;
/* try just name - needed by build team, since they have different output folders */
return Lib_Open(file);
}
using namespace std;
//==============================================================================
//
// Context
//
//==============================================================================
#define CONTEXT_MAGIC 0X82D183A8
class Context : public MI_Context
{
public:
Context()
{
// Set magic number.
magic = CONTEXT_MAGIC;
Batch_Init(&batch, 64);
// Initialize function table.
memset(&_ft, 0, sizeof(_ft));
_ft.PostResult = Context::_PostResult;
_ft.ConstructInstance = Context::_ConstructInstance;
_ft.ConstructParameters = Context::_ConstructParameters;
_ft.PostInstance = Context::_PostInstance;
ft = &_ft;
}
~Context()
{
magic = 0;
clearResults();
Batch_Destroy(&batch);
}
Batch batch;
MI_Result result;
vector<MI_Instance*> instances;
void clearResults()
{
result = MI_RESULT_OK;
for (size_t i = 0; i < instances.size(); i++)
{
MI_Result r = __MI_Instance_Delete(instances[i]);
UT_ASSERT(r == MI_RESULT_OK);
}
instances.clear();
}
private:
MI_ContextFT _ft;
static MI_Result MI_CALL _PostResult(
MI_Context* context,
MI_Result result)
{
Context* ctx = (Context*)context;
UT_ASSERT(ctx->magic == CONTEXT_MAGIC);
ctx->result = result;
return MI_RESULT_OK;
}
static MI_Result MI_CALL _ConstructInstance(
MI_Context* context,
const MI_ClassDecl* classDecl,
MI_Instance* instance)
{
Context* ctx = (Context*)context;
UT_ASSERT(ctx->magic == CONTEXT_MAGIC);
MI_Result r = Instance_Construct(instance, classDecl, &ctx->batch);
if (r != MI_RESULT_OK)
return MI_RESULT_FAILED;
return MI_RESULT_OK;
}
static MI_Result MI_CALL _ConstructParameters(
MI_Context* context,
const MI_MethodDecl* methodDecl,
MI_Instance* instance)
{
Context* ctx = (Context*)context;
UT_ASSERT(ctx->magic == CONTEXT_MAGIC);
MI_Result r = Parameters_Init(instance, methodDecl, &ctx->batch);
if (r != MI_RESULT_OK)
return MI_RESULT_FAILED;
return MI_RESULT_OK;
}
static MI_Result MI_CALL _PostInstance(
MI_Context* context,
const MI_Instance* instance)
{
Context* ctx = (Context*)context;
UT_ASSERT(ctx->magic == CONTEXT_MAGIC);
ctx->result = MI_RESULT_OK;
UT_ASSERT(instance != 0);
MI_Instance* inst = NULL;
Instance_Clone(instance, &inst, &ctx->batch);
UT_ASSERT(inst != NULL);
ctx->instances.push_back(inst);
return MI_RESULT_OK;
}
MI_Uint32 magic;
};
//==============================================================================
//
// Module
//
//==============================================================================
//extern "C" MI_EXPORT MI_Module* MI_Main(MI_Context* context);
typedef MI_Module* (*PfnMI_Main)(MI_Context* context);
class ModuleHandle
{
public:
ModuleHandle(Context& context, const MI_Char* className, const char* lib_file) :
_context(context),
_classDecl(0),
_classSelf(0),
_className(className)
{
_lib = LoadLib(lib_file);
UT_ASSERT( _lib != 0 );
PfnMI_Main pfn = (PfnMI_Main)Lib_Sym(_lib, "MI_Main" );
UT_ASSERT( pfn != 0 );
// Call MI_Main() to get an instance of the provider.
_module = pfn((MI_Context*)&_context);
UT_ASSERT(_module != 0);
UT_ASSERT(_module->version == MI_VERSION);
UT_ASSERT(_module->schemaDecl != 0);
// Load the provider.
UT_ASSERT(_module->Load);
_module->Load(&_moduleSelf, (MI_Context*)&_context);
}
~ModuleHandle()
{
_context.clearResults();
// Unload the provider.
UT_ASSERT(_module != 0);
UT_ASSERT(_module->Unload != 0);
UT_ASSERT(_context.ft != 0);
_module->Unload(_moduleSelf, (MI_Context*)&_context);
if ( _lib != 0 )
Lib_Close(_lib);
}
MI_Instance* newClass()
{
UT_ASSERT(_classDecl != 0);
MI_Instance* inst;
MI_Result r = Instance_New(&inst, _classDecl, &_context.batch);
UT_ASSERT(r == MI_RESULT_OK);
return inst;
}
MI_Instance* newClass(const MI_Char* className)
{
MI_ClassDecl* cd = SchemaDecl_FindClassDecl(_module->schemaDecl,
className);
UT_ASSERT(cd != 0);
MI_Instance* inst;
MI_Result r = Instance_New(&inst, cd, &_context.batch);
UT_ASSERT(r == MI_RESULT_OK);
return inst;
}
MI_Instance* newParameters(const MI_Char* methodName)
{
UT_ASSERT(_classDecl != 0);
MI_MethodDecl* md = ClassDecl_FindMethodDecl(_classDecl, methodName);
UT_ASSERT(md);
MI_Instance* result;
MI_Result r = Parameters_New(&result, md, &_context.batch);
UT_ASSERT(r == MI_RESULT_OK);
return result;
}
void callLoad()
{
// Find the class declaration for the given class.
_classDecl = SchemaDecl_FindClassDecl(
_module->schemaDecl, _className.c_str());
UT_ASSERT(_classDecl != 0);
// Call the class initialize function.
UT_ASSERT(_classDecl->providerFT);
UT_ASSERT(_classDecl->providerFT->Load);
_classDecl->providerFT->Load(&_classSelf, _moduleSelf, (MI_Context*)&_context);
}
void callUnload()
{
// Unload the class provider.
UT_ASSERT(_classDecl->providerFT);
UT_ASSERT(_classDecl->providerFT->Unload);
_classDecl->providerFT->Unload(_classSelf, (MI_Context*)&_context);
_classDecl = 0;
}
void callGet(
const MI_Instance* instanceName,
const MI_PropertySet* propertySet)
{
UT_ASSERT(_classDecl);
return _classDecl->providerFT->GetInstance(
_classSelf,
(MI_Context*)&_context,
__nameSpace,
__className,
instanceName,
propertySet);
}
void callInvoke(
const MI_Char* methodName,
const MI_Instance* instanceName,
const MI_Instance* parameters)
{
UT_ASSERT(instanceName != 0);
UT_ASSERT(parameters != 0);
UT_ASSERT(_classDecl != 0);
MI_MethodDecl* md = ClassDecl_FindMethodDecl(_classDecl,
methodName);
UT_ASSERT(md);
return md->function(_classSelf, (MI_Context*)&_context,
__nameSpace, __className, __methodName, instanceName, parameters);
}
void callEnumerate()
{
UT_ASSERT(_classDecl);
return _classDecl->providerFT->EnumerateInstances(
_classSelf,
(MI_Context*)&_context,
__nameSpace,
__className,
NULL,
MI_FALSE,
NULL);
}
void callCreate(
const MI_Instance* newInstance)
{
return _classDecl->providerFT->CreateInstance(
_classSelf,
(MI_Context*)&_context,
__nameSpace,
__className,
newInstance);
}
void callModify(
const MI_Instance* modifiedInstance,
const MI_PropertySet* propertySet)
{
UT_ASSERT(_classDecl);
return _classDecl->providerFT->ModifyInstance(
_classSelf,
(MI_Context*)&_context,
__nameSpace,
__className,
modifiedInstance,
propertySet);
}
void callDelete(
const MI_Instance* instanceName)
{
UT_ASSERT(_classDecl);
return _classDecl->providerFT->DeleteInstance(
_classSelf,
(MI_Context*)&_context,
__nameSpace,
__className,
instanceName);
}
void callAssociators(MI_Instance* instanceName)
{
UT_ASSERT(_classDecl);
const MI_Char* role1 = 0;
const MI_Char* role2 = 0;
for (MI_Uint32 i = 0; i < _classDecl->numProperties; i++)
{
const MI_PropertyDecl* pd = _classDecl->properties[i];
if (pd->type == MI_REFERENCE)
{
if (!role1)
role1 = pd->name;
else if (!role2)
role2 = pd->name;
}
}
_classDecl->providerFT->AssociatorInstances(
_classSelf,
(MI_Context*)&_context,
__nameSpace,
__className,
instanceName, /* instanceName */
NULL, /* resultClass */
role1, /* role */
role2, /* resultRole */
NULL, /* propertySet */
MI_FALSE, /* keysOnly */
NULL); /* filter */
_classDecl->providerFT->AssociatorInstances(
_classSelf,
(MI_Context*)&_context,
__nameSpace,
__className,
instanceName, /* instanceName */
NULL, /* resultClass */
role2, /* role */
role1, /* resultRole */
NULL, /* propertySet */
MI_FALSE, /* keysOnly */
NULL); /* filter */
}
void callReferences(MI_Instance* instanceName)
{
UT_ASSERT(_classDecl);
const MI_Char* role1 = 0;
const MI_Char* role2 = 0;
for (MI_Uint32 i = 0; i < _classDecl->numProperties; i++)
{
const MI_PropertyDecl* pd = _classDecl->properties[i];
if (pd->type == MI_REFERENCE)
{
if (!role1)
role1 = pd->name;
else if (!role2)
role2 = pd->name;
}
}
_classDecl->providerFT->ReferenceInstances(
_classSelf,
(MI_Context*)&_context,
__nameSpace,
__className,
instanceName, /* instanceName */
role1, /* role */
NULL, /* propertySet */
MI_FALSE, /* keysOnly */
NULL); /* filter */
_classDecl->providerFT->ReferenceInstances(
_classSelf,
(MI_Context*)&_context,
__nameSpace,
__className,
instanceName, /* instanceName */
role2, /* role */
NULL, /* propertySet */
MI_FALSE, /* keysOnly */
NULL); /* filter */
}
MI_ClassDecl* getClassDecl()
{
return _classDecl;
}
private:
ModuleHandle();
ModuleHandle& operator=(const ModuleHandle&);
Context& _context;
// Module and self.
MI_Module* _module;
MI_Module_Self* _moduleSelf;
// Person class and self.
MI_ClassDecl* _classDecl;
void* _classSelf;
String _className;
void* _lib;
};
//==============================================================================
//
// Test functions
//
//==============================================================================
static void setUp()
{
}
static void cleanup()
{
}
static void ExpectNotFound(
Context& ctx,
ModuleHandle& mh,
MI_Uint32 key)
{
MI_Result r;
// Prepare instanceName
MI_Instance* instanceName = mh.newClass();
{
MI_Value value;
value.uint32 = key;
r = __MI_Instance_SetElement(instanceName, MI_T("Key"), &value, MI_UINT32, 0);
UT_ASSERT(r == MI_RESULT_OK);
}
// Call the provider's Get method.
mh.callGet((MI_Instance*)instanceName, NULL);
// Check the result.
UT_ASSERT(ctx.result == MI_RESULT_NOT_FOUND);
UT_ASSERT(ctx.instances.size() == 0);
ctx.instances.clear();
__MI_Instance_Delete(instanceName);
}
static void GetPerson(
Context& ctx,
ModuleHandle& mh,
MI_Uint32 key,
const MI_Char* first,
const MI_Char* last)
{
MI_Result r;
// Prepare instanceName
MI_Instance* instanceName = mh.newClass();
{
MI_Value value;
value.uint32 = key;
r = __MI_Instance_SetElement(instanceName, MI_T("Key"), &value, MI_UINT32, 0);
UT_ASSERT(r == MI_RESULT_OK);
}
// Call the provider's Get method.
mh.callGet((MI_Instance*)instanceName, NULL);
__MI_Instance_Delete(instanceName); instanceName = 0;
// Check the result.
UT_ASSERT(ctx.result == MI_RESULT_OK);
UT_ASSERT(ctx.instances.size() == 1);
MI_Instance* inst = ctx.instances[0];
ctx.instances.clear();
// Check MSFT_Person.Key
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst, MI_T("Key"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_UINT32);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.uint32 == key);
}
// Check MSFT_Person.First
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst, MI_T("First"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_STRING);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.string != NULL);
UT_ASSERT(value.string == String(first));
}
// Check MSFT_Person.Last
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst, MI_T("Last"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_STRING);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.string != NULL);
UT_ASSERT(value.string == String(last));
}
__MI_Instance_Delete(inst);
}
static void EnumeratePerson(
Context& ctx,
ModuleHandle& mh)
{
MI_Result r;
// Call the provider's enumeate method.
mh.callEnumerate();
// Check the result.
UT_ASSERT(ctx.result == MI_RESULT_OK);
UT_ASSERT(ctx.instances.size() == 2);
MI_Instance* inst0 = ctx.instances[0];
MI_Instance* inst1 = ctx.instances[1];
ctx.instances.clear();
#if 0
__MI_Instance_Print(stdout, inst0);
#endif
// Check inst0:
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst0, MI_T("Key"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_UINT32);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.uint32 == 1);
}
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst0, MI_T("First"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_STRING);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.string != NULL);
UT_ASSERT(value.string == String(MI_T("George")));
}
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst0, MI_T("Last"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_STRING);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.string != NULL);
UT_ASSERT(value.string == String(MI_T("Washington")));
}
__MI_Instance_Delete(inst0);
// Check inst1:
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst1, MI_T("Key"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_UINT32);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.uint32 == 2);
}
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst1, MI_T("First"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_STRING);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.string != NULL);
UT_ASSERT(value.string == String(MI_T("John")));
}
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst1, MI_T("Last"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_STRING);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.string != NULL);
UT_ASSERT(value.string == String(MI_T("Adams")));
}
__MI_Instance_Delete(inst1);
}
static void CreatePerson(
Context& ctx,
ModuleHandle& mh,
MI_Uint32 key,
const MI_Char* first,
const MI_Char* last)
{
MI_Result r;
// Prepare the newInstance argument.
MI_Instance* newInstance = mh.newClass();
{
MI_Value value;
value.uint32 = key;
// MSFT_Person.Key:
r = __MI_Instance_SetElement(newInstance, MI_T("Key"), &value, MI_UINT32, 0);
UT_ASSERT(r == MI_RESULT_OK);
// MSFT_Person.First:
value.string = (MI_Char*)first;
r = __MI_Instance_SetElement(newInstance, MI_T("First"), &value, MI_STRING, 0);
UT_ASSERT(r == MI_RESULT_OK);
// MSFT_Person.Last:
value.string = (MI_Char*)last;
r = __MI_Instance_SetElement(newInstance, MI_T("Last"), &value, MI_STRING, 0);
UT_ASSERT(r == MI_RESULT_OK);
}
// Call the provider's Create method.
mh.callCreate((MI_Instance*)newInstance);
UT_ASSERT(ctx.result == MI_RESULT_OK);
UT_ASSERT(ctx.instances.size() == 1);
ctx.clearResults();
// Call the provider's Create method.
mh.callModify((MI_Instance*)newInstance, NULL);
__MI_Instance_Delete(newInstance); newInstance = 0;
UT_ASSERT(ctx.result == MI_RESULT_NOT_SUPPORTED);
UT_ASSERT(ctx.instances.size() == 0);
}
static void DeletePerson(
Context& ctx,
ModuleHandle& mh,
MI_Uint32 key)
{
MI_Result r;
// Prepare instanceName
MI_Instance* instanceName = mh.newClass();
{
MI_Value value;
value.uint32 = key;
r = __MI_Instance_SetElement(instanceName, MI_T("Key"), &value, MI_UINT32, 0);
UT_ASSERT(r == MI_RESULT_OK);
}
// Call the provider's Delete method.
mh.callDelete((MI_Instance*)instanceName);
__MI_Instance_Delete(instanceName); instanceName = 0;
// Check the result.
UT_ASSERT(ctx.result == MI_RESULT_OK);
}
static void InvokePersonAdd(
Context& ctx,
ModuleHandle& mh)
{
// Prepare instanceName
MI_Instance* instanceName = mh.newClass();
Instance_SetUint32(instanceName, MI_T("Key"), 1);
{
MI_Result r;
MI_Instance* params = mh.newParameters(MI_T("Add"));
UT_ASSERT(params);
Instance_SetReal32(params, MI_T("X"), 100);
Instance_SetReal32(params, MI_T("Y"), 200);
#if 0
__MI_Instance_Print(stdout, params);
#endif
mh.callInvoke(MI_T("Add"), instanceName, params);
__MI_Instance_Delete(instanceName); instanceName = 0;
__MI_Instance_Delete(params); params = 0;
UT_ASSERT(ctx.result == MI_RESULT_OK);
UT_ASSERT(ctx.instances.size() == 1);
MI_Instance* out = ctx.instances[0];
UT_ASSERT(out != 0);
ctx.instances.clear();
MI_Real32 z;
r = Instance_GetReal32(out, MI_T("Z"), &z);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(z == 300.0);
#if 0
__MI_Instance_Print(stdout, out);
#endif
__MI_Instance_Delete(out);
}
}
template<typename T, typename C_ARRAY_T, MI_Type type>
static void TestArray(const MI_Char* prop_name, const vector< T >& in_array, MI_Instance* param)
{
C_ARRAY_T value;
T sum = 0;
for ( size_t i = 0; i < in_array.size(); i++ )
sum += in_array[i];
UT_ASSERT(MI_RESULT_OK == Instance_GetValue(param,prop_name,&value,type));
UT_ASSERT(value.size == 2);
UT_ASSERT(value.data[0] == (T)in_array.size());
UT_ASSERT(value.data[1] == sum);
}
static void InvokeTestAllTypes(
Context& ctx,
ModuleHandle& mh)
{
// Prepare instanceName
MI_Instance* instanceName = mh.newClass();
Instance_SetUint32(instanceName, MI_T("Key"), 1);
{
MI_Instance* params = mh.newParameters(MI_T("TestAllTypes"));
UT_ASSERT(params);
UT_ASSERT(MI_RESULT_OK == Instance_SetBoolean(params, MI_T("b"), MI_TRUE));
UT_ASSERT(MI_RESULT_OK == Instance_SetUint8(params, MI_T("u8"), 8));
UT_ASSERT(MI_RESULT_OK == Instance_SetSint8(params, MI_T("s8"), -8));
UT_ASSERT(MI_RESULT_OK == Instance_SetUint16(params, MI_T("u16"), 16));
UT_ASSERT(MI_RESULT_OK == Instance_SetSint16(params, MI_T("s16"), -16));
UT_ASSERT(MI_RESULT_OK == Instance_SetUint32(params, MI_T("u32"), 32));
UT_ASSERT(MI_RESULT_OK == Instance_SetSint32(params, MI_T("s32"), -32));
UT_ASSERT(MI_RESULT_OK == Instance_SetUint64(params, MI_T("u64"), 64));
UT_ASSERT(MI_RESULT_OK == Instance_SetSint64(params, MI_T("s64"), -64));
UT_ASSERT(MI_RESULT_OK == Instance_SetReal32(params, MI_T("r32"), 32.32f));
UT_ASSERT(MI_RESULT_OK == Instance_SetReal64(params, MI_T("r64"), 64.64));
MI_Datetime dt;
dt.isTimestamp = 1;
dt.u.timestamp.year = 1;
dt.u.timestamp.month = 2;
dt.u.timestamp.day = 3;
dt.u.timestamp.hour = 4;
dt.u.timestamp.minute = 5;
dt.u.timestamp.second = 6;
dt.u.timestamp.microseconds = 7;
dt.u.timestamp.utc = 8;
UT_ASSERT(MI_RESULT_OK == Instance_SetDatetime(params, MI_T("dt"), &dt));
UT_ASSERT(MI_RESULT_OK == Instance_SetString(params, MI_T("s"), MI_T("input string")));
UT_ASSERT(MI_RESULT_OK == Instance_SetChar16(params, MI_T("c16"), 1616));
// reference
MI_Instance* new_ref = mh.newClass();
MI_Value value;
value.reference = new_ref;
UT_ASSERT(MI_RESULT_OK == Instance_SetUint32(value.reference, MI_T("Key"), 19));
UT_ASSERT(MI_RESULT_OK == __MI_Instance_SetElement(params, MI_T("rf"), &value, MI_REFERENCE, 0));
// arrays of types
MI_Boolean ba[] = {MI_FALSE};
value.booleana.data = ba;
value.booleana.size = MI_COUNT(ba);
UT_ASSERT(MI_RESULT_OK == __MI_Instance_SetElement(params, MI_T("ba"), &value, MI_BOOLEANA, 0));
#define DECLARE_ARRAY_SET_PROP(a_type,a_name,a_size,a_value_field,a_var_str_name,a_enum_type) \
vector<a_type> a_name; \
{ int count = a_size; while( count-- > 0 ) {a_name.push_back( (a_type)rand());} }\
/* several special values */ \
a_name.push_back(0); a_name.push_back((a_type)-1); a_name.push_back( (a_type)((MI_Uint64(1)<<(sizeof(a_type)*8-1))-1) ); \
/*MI_Sint8 s8A[] = {-128,0,7,127,4}; */ \
value.a_value_field.data = &a_name[0]; \
value.a_value_field.size = (MI_Uint32)a_name.size(); \
/*value.sint8a.data = s8A; value.sint8a.size = MI_COUNT(s8A); */ \
UT_ASSERT(MI_RESULT_OK == __MI_Instance_SetElement(params, a_var_str_name, &value, a_enum_type, 0));
DECLARE_ARRAY_SET_PROP(MI_Uint8,u8A,554,uint8a,MI_T("u8A"),MI_UINT8A);
DECLARE_ARRAY_SET_PROP(MI_Sint8,s8A,4,sint8a,MI_T("s8A"),MI_SINT8A);
DECLARE_ARRAY_SET_PROP(MI_Uint16,u16A,4,uint16a,MI_T("u16A"),MI_UINT16A);
DECLARE_ARRAY_SET_PROP(MI_Sint16,s16A,4,sint16a,MI_T("s16A"),MI_SINT16A);
DECLARE_ARRAY_SET_PROP(MI_Uint32,u32A,4,uint32a,MI_T("u32A"),MI_UINT32A);
DECLARE_ARRAY_SET_PROP(MI_Sint32,s32A,4,sint32a,MI_T("s32A"),MI_SINT32A);
DECLARE_ARRAY_SET_PROP(MI_Uint64,u64A,4,uint64a,MI_T("u64A"),MI_UINT64A);
DECLARE_ARRAY_SET_PROP(MI_Sint64,s64A,40,sint64a,MI_T("s64A"),MI_SINT64A);
// arrays of types
MI_String sa[] = {(MI_Char*)MI_T("in str1"),(MI_Char*)MI_T("in str2") };
value.stringa.data = sa;
value.stringa.size = MI_COUNT(sa);
UT_ASSERT(MI_RESULT_OK == __MI_Instance_SetElement(params, MI_T("sa"), &value, MI_STRINGA, 0));
#if 0
__MI_Instance_Print(stdout, params);
#endif
mh.callInvoke(MI_T("TestAllTypes"), instanceName, params);
__MI_Instance_Delete(instanceName); instanceName = 0;
__MI_Instance_Delete(params); params = 0;
__MI_Instance_Delete(new_ref); new_ref = 0;
UT_ASSERT(ctx.result == MI_RESULT_OK);
UT_ASSERT(ctx.instances.size() == 1);
MI_Instance* out = ctx.instances[0];
UT_ASSERT(out != 0);
ctx.instances.clear();
// verify output
MI_Boolean b;
UT_ASSERT(MI_RESULT_OK == Instance_GetBoolean(out, MI_T("b"), &b));
UT_ASSERT( b == MI_FALSE );
MI_Uint8 u8;
UT_ASSERT(MI_RESULT_OK == Instance_GetUint8(out, MI_T("u8"), &u8));
UT_ASSERT( u8 == 9 );
MI_Sint8 s8;
UT_ASSERT(MI_RESULT_OK == Instance_GetSint8(out, MI_T("s8"), &s8));
UT_ASSERT( s8 == -7 );
MI_Uint16 u16;
UT_ASSERT(MI_RESULT_OK == Instance_GetUint16(out, MI_T("u16"), &u16));
UT_ASSERT( u16 == 17 );
MI_Sint16 s16;
UT_ASSERT(MI_RESULT_OK == Instance_GetSint16(out, MI_T("s16"), &s16));
UT_ASSERT( s16 == -15 );
MI_Uint32 u32;
UT_ASSERT(MI_RESULT_OK == Instance_GetUint32(out, MI_T("u32"), &u32));
UT_ASSERT( u32 == 33 );
MI_Sint32 s32;
UT_ASSERT(MI_RESULT_OK == Instance_GetSint32(out, MI_T("s32"), &s32));
UT_ASSERT( s32 == -31 );
MI_Uint64 u64;
UT_ASSERT(MI_RESULT_OK == Instance_GetUint64(out, MI_T("u64"), &u64));
UT_ASSERT( u64 == 65 );
MI_Sint64 s64;
UT_ASSERT(MI_RESULT_OK == Instance_GetSint64(out, MI_T("s64"), &s64));
UT_ASSERT( s64 == -63 );
MI_Real32 r32;
UT_ASSERT(MI_RESULT_OK == Instance_GetReal32(out, MI_T("r32"), &r32));
UT_ASSERT(r32 == -32.32f);
MI_Real64 r64;
UT_ASSERT(MI_RESULT_OK == Instance_GetReal64(out, MI_T("r64"), &r64));
UT_ASSERT(r64 > -64.65 && r64 < -64.63);
UT_ASSERT(MI_RESULT_OK == Instance_GetDatetime(out, MI_T("dt"), &dt));
UT_ASSERT(dt.isTimestamp == 1 &&
dt.u.timestamp.year == 2 &&
dt.u.timestamp.month == 3 &&
dt.u.timestamp.day == 4 &&
dt.u.timestamp.hour == 5 &&
dt.u.timestamp.minute == 6 &&
dt.u.timestamp.second == 7 &&
dt.u.timestamp.microseconds == 8 &&
dt.u.timestamp.utc == 9);
MI_Instance* rf = 0;
MI_Uint32 rf_key = 0;
UT_ASSERT(MI_RESULT_OK == Instance_GetReference(out, MI_T("rf"), &rf));
UT_ASSERT( 0 != rf );
UT_ASSERT(MI_RESULT_OK == Instance_GetUint32(rf,MI_T("Key"), &rf_key ));
UT_ASSERT(rf_key == 20);
// string
MI_String s = 0;
UT_ASSERT(MI_RESULT_OK == Instance_GetString(out,MI_T("s"), &s ));
UT_ASSERT(0 == memcmp(s, MI_T("inp!"),5*sizeof(MI_Char)));
// char16
MI_Char16 c16;
UT_ASSERT(MI_RESULT_OK == Instance_GetChar16(out,MI_T("c16"), &c16 ));
UT_ASSERT(1617 == c16);
// return value
UT_ASSERT(MI_RESULT_OK == Instance_GetString(out,MI_T("MIReturn"), &s ));
UT_ASSERT(0 == memcmp(s, MI_T("100"),4*sizeof(MI_Char)));
// arrays
MI_BooleanA out_ba;
UT_ASSERT(MI_RESULT_OK == Instance_GetValue(out,MI_T("ba"),&out_ba,MI_BOOLEANA));
UT_ASSERT(out_ba.size == 2);
UT_ASSERT(out_ba.data[0] == 0);
UT_ASSERT(out_ba.data[1] == 1);
TestArray<MI_Uint8,MI_Uint8A,MI_UINT8A>(MI_T("u8A"),u8A,out);
TestArray<MI_Sint8,MI_Sint8A,MI_SINT8A>(MI_T("s8A"),s8A,out);
TestArray<MI_Uint16,MI_Uint16A,MI_UINT16A>(MI_T("u16A"),u16A,out);
TestArray<MI_Sint16,MI_Sint16A,MI_SINT16A>(MI_T("s16A"),s16A,out);
TestArray<MI_Uint32,MI_Uint32A,MI_UINT32A>(MI_T("u32A"),u32A,out);
TestArray<MI_Sint32,MI_Sint32A,MI_SINT32A>(MI_T("s32A"),s32A,out);
TestArray<MI_Uint64,MI_Uint64A,MI_UINT64A>(MI_T("u64A"),u64A,out);
TestArray<MI_Sint64,MI_Sint64A,MI_SINT64A>(MI_T("s64A"),s64A,out);
// strings
MI_StringA out_sa;
UT_ASSERT(MI_RESULT_OK == Instance_GetValue(out,MI_T("sa"),&out_sa,MI_STRINGA));
UT_ASSERT(out_sa.size == 3);
UT_ASSERT(0 == memcmp(out_sa.data[0], MI_T("str1"),5*sizeof(MI_Char)));
UT_ASSERT(0 == memcmp(out_sa.data[1], MI_T("str2"),5*sizeof(MI_Char)));
UT_ASSERT(0 == memcmp(out_sa.data[2], MI_T("*"),2*sizeof(MI_Char)));
#if 0
__MI_Instance_Print(stdout, out);
#endif
__MI_Instance_Delete(out);
}
}
static void TestCloning()
{
MI_Result r;
// find rtti form person provider
Context ctx;
ModuleHandle mh(ctx, MI_T("MSFT_Person"), "PersonProvider");
mh.callLoad();
MI_ClassDecl* cl = mh.getClassDecl();
// Create a new person.
MI_Instance* inst1;
r = Instance_New(&inst1, cl, &ctx.batch);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(inst1 != 0);
{
MI_Value value;
value.uint32 = 1;
// MSFT_Person.Key:
r = __MI_Instance_SetElement(inst1, MI_T("Key"), &value, MI_UINT32, 0);
UT_ASSERT(r == MI_RESULT_OK);
// MSFT_Person.First:
value.string = (MI_Char*)MI_T("George");
r = __MI_Instance_SetElement(inst1, MI_T("First"), &value, MI_STRING, 0);
UT_ASSERT(r == MI_RESULT_OK);
// MSFT_Person.Last:
value.string = (MI_Char*)MI_T("Washington");
r = __MI_Instance_SetElement(inst1, MI_T("Last"), &value, MI_STRING, 0);
UT_ASSERT(r == MI_RESULT_OK);
}
// Check fields.
{
// Check MSFT_Person.Key
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst1, MI_T("Key"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_UINT32);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.uint32 == 1);
}
// Check MSFT_Person.First
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst1, MI_T("First"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_STRING);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.string != NULL);
UT_ASSERT(value.string == String(MI_T("George")));
}
// Check MSFT_Person.Last
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst1, MI_T("Last"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_STRING);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.string != NULL);
UT_ASSERT(value.string == String(MI_T("Washington")));
}
}
// Clone the person.
MI_Instance* inst2;
Instance_Clone(inst1, &inst2, &ctx.batch);
UT_ASSERT(inst2 != NULL);
// Get fields back.
{
// Check MSFT_Person.Key
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst2, MI_T("Key"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_UINT32);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.uint32 == 1);
}
// Check MSFT_Person.First
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst2, MI_T("First"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_STRING);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.string != NULL);
UT_ASSERT(value.string == String(MI_T("George")));
}
// Check MSFT_Person.Last
{
MI_Uint32 flags;
MI_Value value;
MI_Type type;
r = __MI_Instance_GetElement(inst2, MI_T("Last"), &value, &type, &flags, 0);
UT_ASSERT(r == MI_RESULT_OK);
UT_ASSERT(type == MI_STRING);
UT_ASSERT(!(flags & MI_FLAG_NULL));
UT_ASSERT(value.string != NULL);
UT_ASSERT(value.string == String(MI_T("Washington")));
}
}
// Release the instances.
__MI_Instance_Delete(inst1);
__MI_Instance_Delete(inst2);
}
static void TestPersonProvider(const char* provider_file)
{
Context ctx;
ModuleHandle mh(ctx, MI_T("MSFT_Person"), provider_file);
mh.callLoad();
// Test create:
ExpectNotFound(ctx, mh, 1);
CreatePerson(ctx, mh, 1, MI_T("George"), MI_T("Washington"));
ExpectNotFound(ctx, mh, 2);
CreatePerson(ctx, mh, 2, MI_T("John"), MI_T("Adams"));
// Test get:
GetPerson(ctx, mh, 1, MI_T("George"), MI_T("Washington"));
GetPerson(ctx, mh, 2, MI_T("John"), MI_T("Adams"));
// Test enumerate:
EnumeratePerson(ctx, mh);
// Test delete:
DeletePerson(ctx, mh, 1);
ExpectNotFound(ctx, mh, 1);
// Test Person.Add():
InvokePersonAdd(ctx, mh);
mh.callUnload();
}
static void TestPersonProviderAllTypes(const char* provider_file)
{
Context ctx;
ModuleHandle mh(ctx, MI_T("MSFT_Person"), provider_file);
mh.callLoad();
// Test Person.Add():
InvokeTestAllTypes(ctx, mh);
mh.callUnload();
}
static void TestFriendsProvider(const char* provider_file)
{
Context ctx;
ModuleHandle mh(ctx, MI_T("MSFT_Friends"), provider_file);
MI_Result r;
// Load the 'MSFT_Friends' provider.
mh.callLoad();
// Create an instance of class MSFT_Person.
MI_Instance* person = mh.newClass(MI_T("MSFT_Person"));
UT_ASSERT(person != NULL);
r = Instance_SetUint32(person, MI_T("Key"), 1);
UT_ASSERT(r == MI_RESULT_OK);
#if 0
__MI_Instance_Print(stdout, person);
#endif
// Find associators of this person.
mh.callAssociators(person);
// Check the result.
UT_ASSERT(ctx.result == MI_RESULT_OK);
// Check that we got back exactly one friend.
UT_ASSERT(ctx.instances.size() == 1);
MI_Instance* inst = ctx.instances[0];
UT_ASSERT(inst != 0);
ctx.instances.clear();
// Print the instance.
#if 0
__MI_Instance_Print(stdout, inst);
#endif
// Now call references.
mh.callReferences(person);
UT_ASSERT(ctx.result == MI_RESULT_NOT_SUPPORTED);
__MI_Instance_Delete(person); person=0;
// Unload the 'MSFT_Friends' class provider.
mh.callUnload();
// Release the instance.
__MI_Instance_Delete(inst);
}
static void TestPersonProvider_C()
{
TestPersonProvider("PersonProvider");
}
static void TestPersonProviderAllTypes_C()
{
TestPersonProviderAllTypes("PersonProvider");
}
static void TestFriendsProvider_C()
{
TestFriendsProvider("PersonProvider");
}
static void TestPersonProvider_CXX()
{
TestPersonProvider("PersonProviderCXX");
}
static void TestPersonProviderAllTypes_CXX()
{
TestPersonProviderAllTypes("PersonProviderCXX");
}
static void TestFriendsProvider_CXX()
{
TestFriendsProvider("PersonProviderCXX");
}
static void AllProviderTests()
{
UT_TEST(TestCloning);
UT_TEST(TestPersonProvider_C);
UT_TEST(TestPersonProviderAllTypes_C);
UT_TEST(TestFriendsProvider_C);
UT_TEST(TestPersonProvider_CXX);
UT_TEST(TestFriendsProvider_CXX);
UT_TEST(TestPersonProviderAllTypes_CXX);
}
UT_ENTRY_POINT(AllProviderTests);