http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/src/json_rpc.c ---------------------------------------------------------------------- diff --git a/dfi/src/json_rpc.c b/dfi/src/json_rpc.c new file mode 100644 index 0000000..f2b0c56 --- /dev/null +++ b/dfi/src/json_rpc.c @@ -0,0 +1,341 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +#include "json_rpc.h" +#include "json_serializer.h" +#include "dyn_type.h" +#include "dyn_interface.h" +#include <jansson.h> +#include <assert.h> +#include <stdint.h> +#include <string.h> +#include <ffi.h> + + +static int OK = 0; +static int ERROR = 1; + +DFI_SETUP_LOG(jsonRpc); + +typedef void (*gen_func_type)(void); + +struct generic_service_layout { + void *handle; + gen_func_type methods[]; +}; + +int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, char **out) { + int status = OK; + + dyn_type* returnType = NULL; + + LOG_DEBUG("Parsing data: %s\n", request); + json_error_t error; + json_t *js_request = json_loads(request, 0, &error); + json_t *arguments = NULL; + const char *sig; + if (js_request) { + if (json_unpack(js_request, "{s:s}", "m", &sig) != 0) { + LOG_ERROR("Got json error '%s'\n", error.text); + } else { + arguments = json_object_get(js_request, "a"); + } + } else { + LOG_ERROR("Got json error '%s' for '%s'\n", error.text, request); + return 0; + } + + LOG_DEBUG("Looking for method %s\n", sig); + struct methods_head *methods = NULL; + dynInterface_methods(intf, &methods); + struct method_entry *entry = NULL; + struct method_entry *method = NULL; + TAILQ_FOREACH(entry, methods, entries) { + if (strcmp(sig, entry->id) == 0) { + method = entry; + break; + } + } + + if (method == NULL) { + status = ERROR; + LOG_ERROR("Cannot find method with sig '%s'", sig); + } + else if (status == OK) { + LOG_DEBUG("RSA: found method '%s'\n", entry->id); + returnType = dynFunction_returnType(method->dynFunc); + } + + void (*fp)(void) = NULL; + void *handle = NULL; + if (status == OK) { + struct generic_service_layout *serv = service; + handle = serv->handle; + fp = serv->methods[method->index]; + } + + dyn_function_type *func = NULL; + int nrOfArgs = 0; + if (status == OK) { + nrOfArgs = dynFunction_nrOfArguments(entry->dynFunc); + func = entry->dynFunc; + } + + void *args[nrOfArgs]; + + json_t *value = NULL; + + int i; + int index = 0; + + void *ptr = NULL; + void *ptrToPtr = &ptr; + + for (i = 0; i < nrOfArgs; i += 1) { + dyn_type *argType = dynFunction_argumentTypeForIndex(func, i); + enum dyn_function_argument_meta meta = dynFunction_argumentMetaForIndex(func, i); + if (meta == DYN_FUNCTION_ARGUMENT_META__STD) { + value = json_array_get(arguments, index++); + status = jsonSerializer_deserializeJson(argType, value, &(args[i])); + } else if (meta == DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT) { + dynType_alloc(argType, &args[i]); + } else if (meta == DYN_FUNCTION_ARGUMENT_META__OUTPUT) { + args[i] = &ptrToPtr; + } else if (meta == DYN_FUNCTION_ARGUMENT_META__HANDLE) { + args[i] = &handle; + } + + if (status != OK) { + break; + } + } + json_decref(js_request); + + if (status == OK) { + if (dynType_descriptorType(returnType) != 'N') { + //NOTE To be able to handle exception only N as returnType is supported + LOG_ERROR("Only interface methods with a native int are supported. Found type '%c'", (char)dynType_descriptorType(returnType)); + status = ERROR; + } + } + + ffi_sarg returnVal = 1; + + if (status == OK) { + status = dynFunction_call(func, fp, (void *) &returnVal, args); + } + + int funcCallStatus = (int)returnVal; + if (funcCallStatus != 0) { + LOG_WARNING("Error calling remote endpoint function, got error code %i", funcCallStatus); + } + + json_t *jsonResult = NULL; + for(i = 0; i < nrOfArgs; i += 1) { + dyn_type *argType = dynFunction_argumentTypeForIndex(func, i); + enum dyn_function_argument_meta meta = dynFunction_argumentMetaForIndex(func, i); + if (meta == DYN_FUNCTION_ARGUMENT_META__STD) { + dynType_free(argType, args[i]); + } + } + + if (funcCallStatus == 0 && status == OK) { + for (i = 0; i < nrOfArgs; i += 1) { + dyn_type *argType = dynFunction_argumentTypeForIndex(func, i); + enum dyn_function_argument_meta meta = dynFunction_argumentMetaForIndex(func, i); + if (meta == DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT) { + if (status == OK) { + status = jsonSerializer_serializeJson(argType, args[i], &jsonResult); + } + dynType_free(argType, args[i]); + } else if (meta == DYN_FUNCTION_ARGUMENT_META__OUTPUT) { + if (ptr != NULL) { + dyn_type *typedType = NULL; + if (status == OK) { + status = dynType_typedPointer_getTypedType(argType, &typedType); + } + if (dynType_descriptorType(typedType) == 't') { + status = jsonSerializer_serializeJson(typedType, (void*) &ptr, &jsonResult); + free(ptr); + } else { + dyn_type *typedTypedType = NULL; + if (status == OK) { + status = dynType_typedPointer_getTypedType(typedType, &typedTypedType); + } + + if(status == OK){ + status = jsonSerializer_serializeJson(typedTypedType, ptr, &jsonResult); + } + + if (status == OK) { + dynType_free(typedTypedType, ptr); + } + } + + } else { + LOG_DEBUG("Output ptr is null"); + } + } + + if (status != OK) { + break; + } + } + } + + char *response = NULL; + if (status == OK) { + LOG_DEBUG("creating payload\n"); + json_t *payload = json_object(); + if (funcCallStatus == 0) { + if (jsonResult == NULL) { + //ignore -> no result + } else { + LOG_DEBUG("Setting result payload"); + json_object_set_new(payload, "r", jsonResult); + } + } else { + LOG_DEBUG("Setting error payload"); + json_object_set_new(payload, "e", json_integer(funcCallStatus)); + } + response = json_dumps(payload, JSON_DECODE_ANY); + json_decref(payload); + LOG_DEBUG("status ptr is %p. response is '%s'\n", status, response); + } + + if (status == OK) { + *out = response; + } else { + free(response); + } + + return status; +} + +int jsonRpc_prepareInvokeRequest(dyn_function_type *func, const char *id, void *args[], char **out) { + int status = OK; + + + LOG_DEBUG("Calling remote function '%s'\n", id); + json_t *invoke = json_object(); + json_object_set_new(invoke, "m", json_string(id)); + + json_t *arguments = json_array(); + json_object_set_new(invoke, "a", arguments); + + int i; + int nrOfArgs = dynFunction_nrOfArguments(func); + for (i = 0; i < nrOfArgs; i +=1) { + dyn_type *type = dynFunction_argumentTypeForIndex(func, i); + enum dyn_function_argument_meta meta = dynFunction_argumentMetaForIndex(func, i); + if (meta == DYN_FUNCTION_ARGUMENT_META__STD) { + json_t *val = NULL; + + int rc = jsonSerializer_serializeJson(type, args[i], &val); + if (rc == 0) { + json_array_append_new(arguments, val); + } else { + status = ERROR; + break; + } + } else { + //skip handle / output types + } + } + + char *invokeStr = json_dumps(invoke, JSON_DECODE_ANY); + json_decref(invoke); + + if (status == OK) { + *out = invokeStr; + } + + return status; +} + +int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]) { + int status = OK; + + json_error_t error; + json_t *replyJson = json_loads(reply, JSON_DECODE_ANY, &error); + if (replyJson == NULL) { + status = ERROR; + LOG_ERROR("Error parsing json '%s', got error '%s'", reply, error.text); + } + + json_t *result = NULL; + if (status == OK) { + result = json_object_get(replyJson, "r"); //TODO check + if (result == NULL) { + status = ERROR; + LOG_ERROR("Cannot find r entry in json reply '%s'", reply); + } + } + + if (status == OK) { + int nrOfArgs = dynFunction_nrOfArguments(func); + int i; + for (i = 0; i < nrOfArgs; i += 1) { + dyn_type *argType = dynFunction_argumentTypeForIndex(func, i); + enum dyn_function_argument_meta meta = dynFunction_argumentMetaForIndex(func, i); + if (meta == DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT) { + void *tmp = NULL; + void **out = (void **) args[i]; + + size_t size = 0; + + if (dynType_descriptorType(argType) == 't') { + status = jsonSerializer_deserializeJson(argType, result, &tmp); + if(tmp!=NULL){ + size = strnlen(((char *) *(char**) tmp), 1024 * 1024); + memcpy(*out, *(void**) tmp, size); + } + } else { + dynType_typedPointer_getTypedType(argType, &argType); + status = jsonSerializer_deserializeJson(argType, result, &tmp); + if(tmp!=NULL){ + size = dynType_size(argType); + memcpy(*out, tmp, size); + } + } + + dynType_free(argType, tmp); + } else if (meta == DYN_FUNCTION_ARGUMENT_META__OUTPUT) { + dyn_type *subType = NULL; + + dynType_typedPointer_getTypedType(argType, &subType); + + if (dynType_descriptorType(subType) == 't') { + void ***out = (void ***) args[i]; + status = jsonSerializer_deserializeJson(subType, result, *out); + } else { + dyn_type *subSubType = NULL; + dynType_typedPointer_getTypedType(subType, &subSubType); + void ***out = (void ***) args[i]; + status = jsonSerializer_deserializeJson(subSubType, result, *out); + } + } else { + //skip + } + } + } + + json_decref(replyJson); + + return status; +}
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/src/json_serializer.c ---------------------------------------------------------------------- diff --git a/dfi/src/json_serializer.c b/dfi/src/json_serializer.c new file mode 100644 index 0000000..4b78aeb --- /dev/null +++ b/dfi/src/json_serializer.c @@ -0,0 +1,484 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +#include "json_serializer.h" +#include "dyn_type.h" +#include "dyn_interface.h" + +#include <jansson.h> +#include <assert.h> +#include <stdint.h> +#include <string.h> + +static int jsonSerializer_createType(dyn_type *type, json_t *object, void **result); +static int jsonSerializer_parseObject(dyn_type *type, json_t *object, void *inst); +static int jsonSerializer_parseObjectMember(dyn_type *type, const char *name, json_t *val, void *inst); +static int jsonSerializer_parseSequence(dyn_type *seq, json_t *array, void *seqLoc); +static int jsonSerializer_parseAny(dyn_type *type, void *input, json_t *val); + +static int jsonSerializer_writeAny(dyn_type *type, void *input, json_t **val); + +static int jsonSerializer_writeComplex(dyn_type *type, void *input, json_t **val); + +static int jsonSerializer_writeSequence(dyn_type *type, void *input, json_t **out); + +static int OK = 0; +static int ERROR = 1; + +DFI_SETUP_LOG(jsonSerializer); + +int jsonSerializer_deserialize(dyn_type *type, const char *input, void **result) { + assert(dynType_type(type) == DYN_TYPE_COMPLEX || dynType_type(type) == DYN_TYPE_SEQUENCE); + int status = 0; + + json_error_t error; + json_t *root = json_loads(input, JSON_DECODE_ANY, &error); + + if (root != NULL) { + status = jsonSerializer_deserializeJson(type, root, result); + json_decref(root); + } else { + status = ERROR; + LOG_ERROR("Error parsing json input '%s'. Error is: %s\n", input, error.text); + } + + if (status != OK) { + LOG_ERROR("Error cannot deserialize json. Input is '%s'\n", input); + } + return status; +} + +int jsonSerializer_deserializeJson(dyn_type *type, json_t *input, void **out) { + return jsonSerializer_createType(type, input, out); +} + +static int jsonSerializer_createType(dyn_type *type, json_t *val, void **result) { + assert(val != NULL); + int status = OK; + void *inst = NULL; + + if (dynType_descriptorType(type) == 't') { + if (json_typeof(val) == JSON_STRING) { + inst = strdup(json_string_value(val)); + } else { + status = ERROR; + LOG_ERROR("Expected json_string type got %i\n", json_typeof(val)); + } + } else { + status = dynType_alloc(type, &inst); + + if (status == OK) { + assert(inst != NULL); + status = jsonSerializer_parseAny(type, inst, val); + } + } + + if (status == OK) { + *result = inst; + } + else{ + dynType_free(type, inst); + } + + return status; +} + +static int jsonSerializer_parseObject(dyn_type *type, json_t *object, void *inst) { + assert(object != NULL); + int status = 0; + json_t *value; + const char *key; + + json_object_foreach(object, key, value) { + status = jsonSerializer_parseObjectMember(type, key, value, inst); + if (status != OK) { + break; + } + } + + return status; +} + +static int jsonSerializer_parseObjectMember(dyn_type *type, const char *name, json_t *val, void *inst) { + int status = OK; + void *valp = NULL; + dyn_type *valType = NULL; + + int index = dynType_complex_indexForName(type, name); + if (index < 0) { + LOG_ERROR("Cannot find index for member '%s'", name); + status = ERROR; + } + + if (status == OK) { + status = dynType_complex_valLocAt(type, index, inst, &valp); + } + + if (status == OK ) { + status = dynType_complex_dynTypeAt(type, index, &valType); + } + + if (status == OK) { + status = jsonSerializer_parseAny(valType, valp, val); + } + + return status; +} + +static int jsonSerializer_parseAny(dyn_type *type, void *loc, json_t *val) { + int status = OK; + + dyn_type *subType = NULL; + char c = dynType_descriptorType(type); + + /* + printf("parseAny with descriptor '%c' :", c); + json_dumpf(val, stdout, 0); //TODO remove + printf("\n"); + */ + + bool *z; //Z + float *f; //F + double *d; //D + char *b; //B + int *n; //N + int16_t *s; //S + int32_t *i; //I + int64_t *l; //J + uint8_t *ub; //b + uint16_t *us; //s + uint32_t *ui; //i + uint64_t *ul; //j + + switch (c) { + case 'Z' : + z = loc; + *z = (bool) json_is_true(val); + break; + case 'F' : + f = loc; + *f = (float) json_real_value(val); + break; + case 'D' : + d = loc; + *d = json_real_value(val); + break; + case 'N' : + n = loc; + *n = (int) json_integer_value(val); + break; + case 'B' : + b = loc; + *b = (char) json_integer_value(val); + break; + case 'S' : + s = loc; + *s = (int16_t) json_integer_value(val); + break; + case 'I' : + i = loc; + *i = (int32_t) json_integer_value(val); + break; + case 'J' : + l = loc; + *l = (int64_t) json_integer_value(val); + break; + case 'b' : + ub = loc; + *ub = (uint8_t) json_integer_value(val); + break; + case 's' : + us = loc; + *us = (uint16_t) json_integer_value(val); + break; + case 'i' : + ui = loc; + *ui = (uint32_t) json_integer_value(val); + break; + case 'j' : + ul = loc; + *ul = (uint64_t) json_integer_value(val); + break; + case 't' : + if (json_is_string(val)) { + dynType_text_allocAndInit(type, loc, json_string_value(val)); + } else { + status = ERROR; + LOG_ERROR("Expected json string type got %i", json_typeof(val)); + } + break; + case '[' : + if (json_is_array(val)) { + status = jsonSerializer_parseSequence(type, val, loc); + } else { + status = ERROR; + LOG_ERROR("Expected json array type got '%i'", json_typeof(val)); + } + break; + case '{' : + if (status == OK) { + status = jsonSerializer_parseObject(type, val, loc); + } + break; + case '*' : + status = dynType_typedPointer_getTypedType(type, &subType); + if (status == OK) { + status = jsonSerializer_createType(subType, val, (void **) loc); + } + break; + case 'P' : + status = ERROR; + LOG_WARNING("Untyped pointer are not supported for serialization"); + break; + default : + status = ERROR; + LOG_ERROR("Error provided type '%c' not supported for JSON\n", dynType_descriptorType(type)); + break; + } + + return status; +} + +static int jsonSerializer_parseSequence(dyn_type *seq, json_t *array, void *seqLoc) { + assert(dynType_type(seq) == DYN_TYPE_SEQUENCE); + int status = OK; + + size_t size = json_array_size(array); + //LOG_DEBUG("Allocating sequence with capacity %zu", size); + status = dynType_sequence_alloc(seq, seqLoc, (int) size); + + if (status == OK) { + dyn_type *itemType = dynType_sequence_itemType(seq); + size_t index; + json_t *val; + json_array_foreach(array, index, val) { + void *valLoc = NULL; + status = dynType_sequence_increaseLengthAndReturnLastLoc(seq, seqLoc, &valLoc); + //LOG_DEBUG("Got sequence loc %p for index %zu", valLoc, index); + + if (status == OK) { + status = jsonSerializer_parseAny(itemType, valLoc, val); + if (status != OK) { + break; + } + } + } + } + + return status; +} + +int jsonSerializer_serialize(dyn_type *type, const void* input, char **output) { + int status = OK; + + json_t *root = NULL; + status = jsonSerializer_serializeJson(type, input, &root); + + if (status == OK) { + *output = json_dumps(root, JSON_COMPACT); + json_decref(root); + } + + return status; +} + +int jsonSerializer_serializeJson(dyn_type *type, const void* input, json_t **out) { + return jsonSerializer_writeAny(type, (void*)input /*TODO update static function to take const void**/, out); +} + +static int jsonSerializer_writeAny(dyn_type *type, void* input, json_t **out) { + int status = OK; + + int descriptor = dynType_descriptorType(type); + json_t *val = NULL; + dyn_type *subType = NULL; + + bool *z; //Z + float *f; //F + double *d; //D + char *b; //B + int *n; //N + int16_t *s; //S + int32_t *i; //I + int64_t *l; //J + uint8_t *ub; //b + uint16_t *us; //s + uint32_t *ui; //i + uint64_t *ul; //j + + switch (descriptor) { + case 'Z' : + z = input; + val = json_boolean((bool)*z); + break; + case 'B' : + b = input; + val = json_integer((json_int_t)*b); + break; + case 'S' : + s = input; + val = json_integer((json_int_t)*s); + break; + case 'I' : + i = input; + val = json_integer((json_int_t)*i); + break; + case 'J' : + l = input; + val = json_integer((json_int_t)*l); + break; + case 'b' : + ub = input; + val = json_integer((json_int_t)*ub); + break; + case 's' : + us = input; + val = json_integer((json_int_t)*us); + break; + case 'i' : + ui = input; + val = json_integer((json_int_t)*ui); + break; + case 'j' : + ul = input; + val = json_integer((json_int_t)*ul); + break; + case 'N' : + n = input; + val = json_integer((json_int_t)*n); + break; + case 'F' : + f = input; + val = json_real((double) *f); + break; + case 'D' : + d = input; + val = json_real(*d); + break; + case 't' : + val = json_string(*(const char **) input); + break; + case '*' : + status = dynType_typedPointer_getTypedType(type, &subType); + if (status == OK) { + status = jsonSerializer_writeAny(subType, *(void **)input, &val); + } + break; + case '{' : + status = jsonSerializer_writeComplex(type, input, &val); + break; + case '[' : + status = jsonSerializer_writeSequence(type, input, &val); + break; + case 'P' : + LOG_WARNING("Untyped pointer not supported for serialization. ignoring"); + break; + default : + LOG_ERROR("Unsupported descriptor '%c'", descriptor); + status = ERROR; + break; + } + + if (status == OK && val != NULL) { + *out = val; + } + + return status; +} + +static int jsonSerializer_writeSequence(dyn_type *type, void *input, json_t **out) { + assert(dynType_type(type) == DYN_TYPE_SEQUENCE); + int status = OK; + + json_t *array = json_array(); + dyn_type *itemType = dynType_sequence_itemType(type); + uint32_t len = dynType_sequence_length(input); + + int i = 0; + void *itemLoc = NULL; + json_t *item = NULL; + for (i = 0; i < len; i += 1) { + item = NULL; + status = dynType_sequence_locForIndex(type, input, i, &itemLoc); + if (status == OK) { + status = jsonSerializer_writeAny(itemType, itemLoc, &item); + if (status == OK) { + json_array_append(array, item); + json_decref(item); + } + } + + if (status != OK) { + break; + } + } + + if (status == OK && array != NULL) { + *out = array; + } + + return status; +} + +static int jsonSerializer_writeComplex(dyn_type *type, void *input, json_t **out) { + assert(dynType_type(type) == DYN_TYPE_COMPLEX); + int status = OK; + + json_t *val = json_object(); + struct complex_type_entry *entry = NULL; + struct complex_type_entries_head *entries = NULL; + int index = -1; + + status = dynType_complex_entries(type, &entries); + if (status == OK) { + TAILQ_FOREACH(entry, entries, entries) { + void *subLoc = NULL; + json_t *subVal = NULL; + dyn_type *subType = NULL; + index = dynType_complex_indexForName(type, entry->name); + if (index < 0) { + LOG_ERROR("Cannot find index for member '%s'", entry->name); + status = ERROR; + } + if(status == OK){ + status = dynType_complex_valLocAt(type, index, input, &subLoc); + } + if (status == OK) { + status = dynType_complex_dynTypeAt(type, index, &subType); + } + if (status == OK) { + status = jsonSerializer_writeAny(subType, subLoc, &subVal); + } + if (status == OK) { + json_object_set(val, entry->name, subVal); + json_decref(subVal); + } + + if (status != OK) { + break; + } + } + } + + if (status == OK && val != NULL) { + *out = val; + } + + return status; +} + http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/avro_descriptor_translator_tests.cpp ---------------------------------------------------------------------- diff --git a/dfi/test/avro_descriptor_translator_tests.cpp b/dfi/test/avro_descriptor_translator_tests.cpp new file mode 100644 index 0000000..5bab518 --- /dev/null +++ b/dfi/test/avro_descriptor_translator_tests.cpp @@ -0,0 +1,180 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +#include <CppUTest/TestHarness.h> +#include "CppUTest/CommandLineTestRunner.h" + +extern "C" { + +#include <stdio.h> +#include <assert.h> +#include <string.h> + +#include "dyn_common.h" +#include "descriptor_translator.h" + +#if defined(BSD) || defined(__APPLE__) +#include "open_memstream.h" +#include "fmemopen.h" +#endif + + static void stdLog(void *handle, int level, const char *file, int line, const char *msg, ...) { + va_list ap; + const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"}; + fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line); + va_start(ap, msg); + vfprintf(stderr, msg, ap); + fprintf(stderr, "\n"); + va_end(ap); + } + + + static char *readSchema(const char *file) { + size_t size = 0; + char *ptr = NULL; + + FILE *schema = fopen(file, "r"); + FILE *stream = open_memstream(&ptr, &size); + + assert(schema != NULL); + assert(stream != NULL); + + int c = fgetc(schema); + while (c != EOF ) { + fputc(c, stream); + c = fgetc(schema); + } + fclose(schema); + fclose(stream); + + assert(ptr != NULL); + return ptr; + } + + static dyn_interface_type *createInterfaceInfo(const char *schemaFile) { + char *schema = readSchema(schemaFile); + dyn_interface_type *ift= NULL; + + int status = descriptorTranslator_translate(schema, &ift); + CHECK_EQUAL(0, status); + + free(schema); + return ift; + } + + static int countMethodInfos(dyn_interface_type *info) { + int count = 0; + method_info_type *mInfo = NULL; + TAILQ_FOREACH(mInfo, &info->methodInfos, entries) { + count +=1; + } + return count; + } + + static int countTypeInfos(dyn_interface_type *info) { + int count = 0; + type_info_type *tInfo = NULL; + TAILQ_FOREACH(tInfo, &info->typeInfos, entries) { + count +=1; + } + return count; + } + + static void simple(void) { + //first argument void *handle, last argument output pointer for result and return int with status for exception handling + //sum(DD)D -> sum(PDD*D)N + //sub(DD)D -> sub(PDD*D)N + //sqrt(D)D -> sqrt(PD*D)N + + dyn_interface_type *intf = createInterfaceInfo("schemas/simple.avpr"); + + int count = countMethodInfos(intf); + CHECK_EQUAL(3, count); + + count = countTypeInfos(intf); + CHECK_EQUAL(0, count); + + method_info_type *mInfo = NULL; + TAILQ_FOREACH(mInfo, &intf->methodInfos, entries) { + if (strcmp("sum", mInfo->name) == 0) { + STRCMP_EQUAL("sum(PDD*D)N", mInfo->descriptor); + } else if (strcmp("add", mInfo->name) == 0) { + STRCMP_EQUAL("add(PDD*D)N", mInfo->descriptor); + } else if (strcmp("sqrt", mInfo->name) == 0) { + STRCMP_EQUAL("sqrt(PD*D)N", mInfo->descriptor); + } + } + + dynInterface_destroy(intf); + } + + static void complex(void) { + dyn_interface_type *intf = createInterfaceInfo("schemas/complex.avpr"); + + int count = countMethodInfos(intf); + CHECK_EQUAL(1, count); + + method_info_type *mInfo = TAILQ_FIRST(&intf->methodInfos); + STRCMP_EQUAL("stats", mInfo->name); + STRCMP_EQUAL("stats(P[D*LStatResult;)N", mInfo->descriptor); + + count = countTypeInfos(intf); + CHECK_EQUAL(1, count); + + type_info_type *tInfo = TAILQ_FIRST(&intf->typeInfos); + STRCMP_EQUAL("StatResult", tInfo->name); + STRCMP_EQUAL("{DDD[D sum min max input}", tInfo->descriptor); + + dynInterface_destroy(intf); + } + + static void invalid(const char *file) { + char *schema = readSchema(file); + dyn_interface_type *ift= NULL; + + int status = descriptorTranslator_translate(schema, &ift); + CHECK(status != 0); + + free(schema); + } +} + +TEST_GROUP(AvroDescTranslatorTest) { + void setup() { + descriptorTranslator_logSetup(stdLog, NULL, 3); + dynInterface_logSetup(stdLog, NULL, 3); + dynType_logSetup(stdLog, NULL, 3); + dynCommon_logSetup(stdLog, NULL, 3); + } +}; + +TEST(AvroDescTranslatorTest, simple) { + simple(); +} + +TEST(AvroDescTranslatorTest, complex) { + complex(); +} + +TEST(AvroDescTranslatorTest, invalid1) { + invalid("schemas/invalid1.avpr"); +} + +TEST(AvroDescTranslatorTest, invalid2) { + invalid("schemas/invalid2.avpr"); +} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/example1.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/example1.descriptor b/dfi/test/descriptors/example1.descriptor new file mode 100644 index 0000000..771dc5e --- /dev/null +++ b/dfi/test/descriptors/example1.descriptor @@ -0,0 +1,13 @@ +:header +type=interface +name=calculator +version=1.0.0 +:annotations +classname=org.example.Calculator +:types +StatsResult={DDD[D average min max input} +:methods +add(DD)D=add(#am=handle;PDD#am=pre;*D)N +sub(DD)D=sub(#am=handle;PDD*#am=pre;D)N +sqrt(D)D=sqrt(#am=handle;PD*#am=pre;D)N +stats([D)LStatsResult;=stats(#am=handle;P[D#am=out;*LStatsResult;)N http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/example2.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/example2.descriptor b/dfi/test/descriptors/example2.descriptor new file mode 100644 index 0000000..38bf442 --- /dev/null +++ b/dfi/test/descriptors/example2.descriptor @@ -0,0 +1,9 @@ +:header +type=interface +name=example +version=1.0.0 +:annotations +:types +item={DD a b} +:methods +example1=items(#am=handle;P#am=out;**[Litem;)N http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/example3.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/example3.descriptor b/dfi/test/descriptors/example3.descriptor new file mode 100644 index 0000000..c89d969 --- /dev/null +++ b/dfi/test/descriptors/example3.descriptor @@ -0,0 +1,11 @@ +:header +type=interface +name=detection_provider +version=1.0.0 +:annotations +:types +location={DD lat lon} +target={Jllocation;DDJ id location speed heading lastUpdated} +detection={Jllocation;Dltarget; id center range simulated} +:methods +getDetections()Ljava/util/List;=getDetections(#am=handle;P#am=out;**[Ldetection;)N http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/example4.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/example4.descriptor b/dfi/test/descriptors/example4.descriptor new file mode 100644 index 0000000..4c959c4 --- /dev/null +++ b/dfi/test/descriptors/example4.descriptor @@ -0,0 +1,8 @@ +:header +type=interface +name=example4 +version=1.0.0 +:annotations +:types +:methods +getName(V)t=getName(#am=handle;P#am=out;*t)N http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalid.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalid.descriptor b/dfi/test/descriptors/invalids/invalid.descriptor new file mode 100644 index 0000000..fead964 --- /dev/null +++ b/dfi/test/descriptors/invalids/invalid.descriptor @@ -0,0 +1,13 @@ +:header +type=interface +name=calculator X +version=1.0.0 +:annotations +classname=org.example.Calculator +:types +StatsResult={DDD[D average min max input} +:methods +add(DD)D=add(#am=handle;PDD#am=pre;*D)N +sub(DD)D=sub(#am=handle;PDD*#am=pre;D)N +sqrt(D)D=sqrt(#am=handle;PD*#am=pre;D)N +stats([D)LStatsResult;=stats(#am=handle;P[D#am=out;*LStatsResult;)N http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidMetaType.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidMetaType.descriptor b/dfi/test/descriptors/invalids/invalidMetaType.descriptor new file mode 100644 index 0000000..2d17c47 --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidMetaType.descriptor @@ -0,0 +1,8 @@ +:header +type=interface +name=calculator +version=1.0.0 +:annotations +classname=org.example.Calculator +:methods +add(DD)D=add(#am=invalid;PDD#am=pre;*D)N http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidMethod.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidMethod.descriptor b/dfi/test/descriptors/invalids/invalidMethod.descriptor new file mode 100644 index 0000000..eaef7b1 --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidMethod.descriptor @@ -0,0 +1,8 @@ +:header +type=interface +name=calculator +version=1.0.0 +:annotations +classname=org.example.Calculator +:methods +add(DD)D=add(#am=handle;PDD#am=pre;*D)N X http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidMethodReturnType.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidMethodReturnType.descriptor b/dfi/test/descriptors/invalids/invalidMethodReturnType.descriptor new file mode 100644 index 0000000..26f75f8 --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidMethodReturnType.descriptor @@ -0,0 +1,8 @@ +:header +type=interface +name=calculator +version=1.0.0 +:annotations +classname=org.example.Calculator +:methods +add(DD)D=add(#am=handle;PDD#am=pre;*D)D http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidMsgHdr.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidMsgHdr.descriptor b/dfi/test/descriptors/invalids/invalidMsgHdr.descriptor new file mode 100644 index 0000000..ae9b131 --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidMsgHdr.descriptor @@ -0,0 +1,9 @@ +:header +type=message +name=poi +:annotations +classname=org.example.PointOfInterest +:types +location={DD lat long} +:message +{llocation;tt location name description} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidMsgInvalidName.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidMsgInvalidName.descriptor b/dfi/test/descriptors/invalids/invalidMsgInvalidName.descriptor new file mode 100644 index 0000000..787dd4c --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidMsgInvalidName.descriptor @@ -0,0 +1,9 @@ +:header +type=message +name=poi X +:annotations +classname=org.example.PointOfInterest +:types +location={DD lat long} +:message +{llocation;tt location name description} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidMsgInvalidSection.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidMsgInvalidSection.descriptor b/dfi/test/descriptors/invalids/invalidMsgInvalidSection.descriptor new file mode 100644 index 0000000..02a593c --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidMsgInvalidSection.descriptor @@ -0,0 +1,10 @@ +:header +type=message +name=poi +version=1.0.0 +:invalid +classname=org.example.PointOfInterest +:types +location={DD lat long} +:message +{llocation;tt location name description} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidMsgInvalidType.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidMsgInvalidType.descriptor b/dfi/test/descriptors/invalids/invalidMsgInvalidType.descriptor new file mode 100644 index 0000000..5008311 --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidMsgInvalidType.descriptor @@ -0,0 +1,9 @@ +:header +type=message +name=poi +:annotations +classname=org.example.PointOfInterest +:types +location={DD lat long} X +:message +{llocation;tt location name description} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidMsgInvalidVersion.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidMsgInvalidVersion.descriptor b/dfi/test/descriptors/invalids/invalidMsgInvalidVersion.descriptor new file mode 100644 index 0000000..6cffbdc --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidMsgInvalidVersion.descriptor @@ -0,0 +1,10 @@ +:header +type=message +name=poi +version=1.0.f +:annotations +classname=org.example.PointOfInterest +:types +location={DD lat long} +:message +{llocation;tt location name description} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidMsgMissingVersion.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidMsgMissingVersion.descriptor b/dfi/test/descriptors/invalids/invalidMsgMissingVersion.descriptor new file mode 100644 index 0000000..1fd3595 --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidMsgMissingVersion.descriptor @@ -0,0 +1,10 @@ +:head +type=message +name=poi +version=1.0.0 +:annotations +classname=org.example.PointOfInterest +:types +location={DD lat long} +:message +{llocation;tt location name description} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidSection.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidSection.descriptor b/dfi/test/descriptors/invalids/invalidSection.descriptor new file mode 100644 index 0000000..b8a11a6 --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidSection.descriptor @@ -0,0 +1,6 @@ +:header +type=interface +name=calculator +version=1.0.0 +:invalidSection +invalidKey=invalidValue \ No newline at end of file http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidType.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidType.descriptor b/dfi/test/descriptors/invalids/invalidType.descriptor new file mode 100644 index 0000000..7b7ce1c --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidType.descriptor @@ -0,0 +1,10 @@ +:header +type=interface +name=calculator +version=1.0.0 +:annotations +classname=org.example.Calculator +:types +StatsResult={DDD[D average min max input} X +:methods +stats([D)LStatsResult;=stats(#am=handle;P[D#am=out;*LStatsResult;)N http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/invalidVersion.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/invalidVersion.descriptor b/dfi/test/descriptors/invalids/invalidVersion.descriptor new file mode 100644 index 0000000..bfe4d38 --- /dev/null +++ b/dfi/test/descriptors/invalids/invalidVersion.descriptor @@ -0,0 +1,9 @@ +:header +type=interface +name=example +version=q.0.0 +:annotations +:types +item={DD a b} +:methods +example1=items(#am=handle;P#am=out;**[Litem;)N http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/invalids/noVersion.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/invalids/noVersion.descriptor b/dfi/test/descriptors/invalids/noVersion.descriptor new file mode 100644 index 0000000..731a9e6 --- /dev/null +++ b/dfi/test/descriptors/invalids/noVersion.descriptor @@ -0,0 +1,12 @@ +:header +type=interface +name=calculator +:annotations +classname=org.example.Calculator +:types +StatsResult={DDD[D average min max input} +:methods +add(DD)D=add(#am=handle;PDD#am=pre;*D)N +sub(DD)D=sub(#am=handle;PDD*#am=pre;D)N +sqrt(D)D=sqrt(#am=handle;PD*#am=pre;D)N +stats([D)LStatsResult;=stats(#am=handle;P[D#am=out;*LStatsResult;)N http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/msg_example1.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/msg_example1.descriptor b/dfi/test/descriptors/msg_example1.descriptor new file mode 100644 index 0000000..576523a --- /dev/null +++ b/dfi/test/descriptors/msg_example1.descriptor @@ -0,0 +1,10 @@ +:header +type=message +name=poi +version=1.0.0 +:annotations +classname=org.example.PointOfInterest +:types +location={DD lat long} +:message +{llocation;tt location name description} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/msg_example2.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/msg_example2.descriptor b/dfi/test/descriptors/msg_example2.descriptor new file mode 100644 index 0000000..128049d --- /dev/null +++ b/dfi/test/descriptors/msg_example2.descriptor @@ -0,0 +1,12 @@ +:header +type=message +name=track +version=0.0.1 +:annotations +classname=org.example.Track +:types +timestamp={SSSSSSI day month year hour minute second microseconds} +latlonpos={DD lat lon} +polarpos={DDD azimuth elevation range} +:message +{Iltimestamp;llatlonpos;lpolarpos;SS trackid lastupdate abspos relpos classification identity} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/msg_example3.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/msg_example3.descriptor b/dfi/test/descriptors/msg_example3.descriptor new file mode 100644 index 0000000..7b69380 --- /dev/null +++ b/dfi/test/descriptors/msg_example3.descriptor @@ -0,0 +1,10 @@ +:header +type=message +name=logEntry +version=1.0.0 +:annotations +classname=org.example.LogEntry +:types +timestamp={SSSSSSI day month year hour minute second microseconds} +:message +{ltimestamp;St timestamp severity eventdescription} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/descriptors/msg_example4.descriptor ---------------------------------------------------------------------- diff --git a/dfi/test/descriptors/msg_example4.descriptor b/dfi/test/descriptors/msg_example4.descriptor new file mode 100644 index 0000000..e99e443 --- /dev/null +++ b/dfi/test/descriptors/msg_example4.descriptor @@ -0,0 +1,10 @@ +:header +type=message +name=exmpl4 +version=1.1.0 +:annotations +:types +info={Jladditional_info; id info} +additional_info={Jt; id descr} +:message +{Jlinfo; id info} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/dyn_closure_tests.cpp ---------------------------------------------------------------------- diff --git a/dfi/test/dyn_closure_tests.cpp b/dfi/test/dyn_closure_tests.cpp new file mode 100644 index 0000000..9c1abe6 --- /dev/null +++ b/dfi/test/dyn_closure_tests.cpp @@ -0,0 +1,162 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +#include <CppUTest/TestHarness.h> +#include "CppUTest/CommandLineTestRunner.h" + +extern "C" { + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "dyn_common.h" +#include "dyn_function.h" + +static int g_count; + +static void stdLog(void*, int level, const char *file, int line, const char *msg, ...) { + va_list ap; + const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"}; + fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line); + va_start(ap, msg); + vfprintf(stderr, msg, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +#define EXAMPLE1_DESCRIPTOR "example(III)I" +static void example1_binding(void*, void* args[], void *out) { + int32_t a = *((int32_t *)args[0]); + int32_t b = *((int32_t *)args[1]); + int32_t c = *((int32_t *)args[2]); + int32_t *ret = (int32_t *)out; + *ret = a + b + c; + g_count += 1; +} + +#define EXAMPLE2_DESCRIPTOR "example(I{DDD val1 val2 val3}I)D" +struct example2_arg2 { + double val1; + double val2; + double val3; +}; +void example2_binding(void*, void* args[], void *out) { + int32_t a = *((int32_t *)args[0]); + struct example2_arg2 b = *((struct example2_arg2 *)args[1]); + int32_t c = *((int32_t *)args[2]); + double *ret = (double *)out; + *ret = a + b.val1 + b.val2 + b.val3 + c; + g_count += 1; +} + + +#define EXAMPLE3_DESCRIPTOR "example(III){III sum max min}" +struct example3_ret { + int32_t sum; + int32_t max; + int32_t min; +}; + +static void example3_binding(void*, void* args[], void *out) { + int32_t a = *((int32_t *)args[0]); + int32_t b = *((int32_t *)args[1]); + int32_t c = *((int32_t *)args[2]); + struct example3_ret *result = (struct example3_ret *)calloc(1,sizeof(struct example3_ret)); + result->sum = a + b + c; + result->min = a <= b ? a : b; + result->max = a >= b ? a : b; + result->min = result->min <= c ? result->min : c; + result->max = result->max >= c ? result->max : c; + + struct example3_ret **ret = (struct example3_ret **)out; + (*ret) = result; + g_count += 1; +} + +static void tests() { + dyn_function_type *dynFunction = NULL; + int rc = 0; + + { + int32_t (*func)(int32_t a, int32_t b, int32_t c) = NULL; + rc = dynFunction_parseWithStr(EXAMPLE1_DESCRIPTOR, NULL, &dynFunction); + CHECK_EQUAL(0, rc); + rc = dynFunction_createClosure(dynFunction, example1_binding, NULL, (void(**)(void))&func); + CHECK_EQUAL(0, rc); + int32_t ret = func(2,3,4); + CHECK_EQUAL(1, g_count); + CHECK_EQUAL(9, ret); + dynFunction_destroy(dynFunction); + } + + { + double (*func)(int32_t a, struct example2_arg2 b, int32_t c) = NULL; + double (*func2)(int32_t a, struct example2_arg2 b, int32_t c) = NULL; + dynFunction = NULL; + rc = dynFunction_parseWithStr(EXAMPLE2_DESCRIPTOR, NULL, &dynFunction); + CHECK_EQUAL(0, rc); + rc = dynFunction_createClosure(dynFunction, example2_binding, NULL, (void(**)(void))&func); + CHECK_EQUAL(0, rc); + rc = dynFunction_getFnPointer(dynFunction, (void(**)(void))&func2); + CHECK_EQUAL(0, rc); + CHECK(func == func2); + struct example2_arg2 b; + b.val1 = 1.0; + b.val2 = 1.5; + b.val3 = 2.0; + double ret = func(2,b,4); + CHECK_EQUAL(2, g_count); + CHECK_EQUAL(10.5, ret); + dynFunction_destroy(dynFunction); + } + + { + struct example3_ret * (*func)(int32_t a, int32_t b, int32_t c) = NULL; + dynFunction = NULL; + rc = dynFunction_parseWithStr(EXAMPLE3_DESCRIPTOR, NULL, &dynFunction); + CHECK_EQUAL(0, rc); + rc = dynFunction_createClosure(dynFunction, example3_binding, NULL, (void(**)(void))&func); + CHECK_EQUAL(0, rc); + struct example3_ret *ret = func(2,8,4); + CHECK_EQUAL(3, g_count); + CHECK_EQUAL(14, ret->sum); + dynFunction_destroy(dynFunction); + free(ret); + } +} + +} + + +TEST_GROUP(DynClosureTests) { + void setup() { + int lvl = 1; + dynFunction_logSetup(stdLog, NULL, lvl); + dynType_logSetup(stdLog, NULL, lvl); + dynCommon_logSetup(stdLog, NULL, lvl); + g_count = 0; + } +}; + +TEST(DynClosureTests, DynCLosureTest1) { + //TODO split up + tests(); +} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/dyn_function_tests.cpp ---------------------------------------------------------------------- diff --git a/dfi/test/dyn_function_tests.cpp b/dfi/test/dyn_function_tests.cpp new file mode 100644 index 0000000..58ad662 --- /dev/null +++ b/dfi/test/dyn_function_tests.cpp @@ -0,0 +1,274 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +#include <CppUTest/TestHarness.h> +#include "CppUTest/CommandLineTestRunner.h" + +extern "C" { + #include <stdio.h> + #include <stdint.h> + #include <stdlib.h> + #include <string.h> + #include <ctype.h> + + + #include "dyn_common.h" + #include "dyn_function.h" + + static void stdLog(void*, int level, const char *file, int line, const char *msg, ...) { + va_list ap; + const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"}; + fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line); + va_start(ap, msg); + vfprintf(stderr, msg, ap); + fprintf(stderr, "\n"); + va_end(ap); + } + + #define EXAMPLE1_DESCRIPTOR "example(III)I" + int32_t example1(int32_t a, int32_t b, int32_t c) { + CHECK_EQUAL(2, a); + CHECK_EQUAL(4, b); + CHECK_EQUAL(8, c); + return 1; + } + + void test_example1(void) { + dyn_function_type *dynFunc = NULL; + int rc; + void (*fp)(void) = (void (*)(void)) example1; + + rc = dynFunction_parseWithStr(EXAMPLE1_DESCRIPTOR, NULL, &dynFunc); + CHECK_EQUAL(0, rc); + + int32_t a = 2; + int32_t b = 4; + int32_t c = 8; + void *values[3]; + int32_t rVal = 0; + values[0] = &a; + values[1] = &b; + values[2] = &c; + + rc = dynFunction_call(dynFunc, fp, &rVal, values); + CHECK_EQUAL(0, rc); + CHECK_EQUAL(1, rVal); + dynFunction_destroy(dynFunc); + } + + #define EXAMPLE2_DESCRIPTOR "example(I{IID val1 val2 val3}D)D" + struct example2_arg { + int32_t val1; + int32_t val2; + double val3; + }; + + double example2(int32_t arg1, struct example2_arg arg2, double arg3) { + CHECK_EQUAL(2, arg1); + CHECK_EQUAL(2, arg2.val1); + CHECK_EQUAL(3, arg2.val2); + CHECK_EQUAL(4.1, arg2.val3); + CHECK_EQUAL(8.1, arg3); + return 2.2; + } + + void test_example2(void) { + dyn_function_type *dynFunc = NULL; + int rc; + void (*fp)(void) = (void (*)(void)) example2; + + rc = dynFunction_parseWithStr(EXAMPLE2_DESCRIPTOR, NULL, &dynFunc); + CHECK_EQUAL(0, rc); + + int32_t arg1 = 2; + struct example2_arg arg2; + arg2.val1 = 2; + arg2.val2 = 3; + arg2.val3 = 4.1; + double arg3 = 8.1; + double returnVal = 0; + void *values[3]; + values[0] = &arg1; + values[1] = &arg2; + values[2] = &arg3; + + rc = dynFunction_call(dynFunc, fp, &returnVal, values); + CHECK_EQUAL(0, rc); + CHECK_EQUAL(2.2, returnVal); + dynFunction_destroy(dynFunc); + } + + static void test_access_functions(void) { + dyn_function_type *dynFunc = NULL; + int rc; + rc = dynFunction_parseWithStr("add(D{DD a b}*D)V", NULL, &dynFunc); + + CHECK_EQUAL(0, rc); + + int nrOfArgs = dynFunction_nrOfArguments(dynFunc); + CHECK_EQUAL(3, nrOfArgs); + + dyn_type *arg1 = dynFunction_argumentTypeForIndex(dynFunc, 1); + CHECK(arg1 != NULL); + CHECK_EQUAL('{', (char) dynType_descriptorType(arg1)); + + dyn_type *nonExist = dynFunction_argumentTypeForIndex(dynFunc, 10); + CHECK(nonExist == NULL); + + dyn_type *returnType = dynFunction_returnType(dynFunc); + CHECK_EQUAL('V', (char) dynType_descriptorType(returnType)); + + dynFunction_destroy(dynFunc); + } + + //example with gen pointer and output + #define EXAMPLE3_DESCRIPTOR "example(PD*D)N" + + static int testExample3(void *ptr, double a, double *out) { + double *b = (double *)ptr; + CHECK_EQUAL(2.0, *b) + CHECK_EQUAL(a, 2.0); + *out = *b * a; + return 0; + } + + static void test_example3(void) { + dyn_function_type *dynFunc = NULL; + void (*fp)(void) = (void(*)(void)) testExample3; + int rc; + + rc = dynFunction_parseWithStr(EXAMPLE3_DESCRIPTOR, NULL, &dynFunc); + CHECK_EQUAL(0, rc); + double result = -1.0; + double *input = &result; + double a = 2.0; + void *ptr = &a; + void *args[3]; + args[0] = &ptr; + args[1] = &a; + args[2] = &input; + int rVal = 0; + rc = dynFunction_call(dynFunc, fp, &rVal, args); + CHECK_EQUAL(0, rc); + CHECK_EQUAL(4.0, result); + + + double *inMemResult = (double *)calloc(1, sizeof(double)); + a = 2.0; + ptr = &a; + args[0] = &ptr; + args[1] = &a; + args[2] = &inMemResult; + rVal = 0; + rc = dynFunction_call(dynFunc, fp, &rVal, args); + CHECK_EQUAL(0, rc); + CHECK_EQUAL(4.0, result); + free(inMemResult); + + dynFunction_destroy(dynFunc); + } + + struct tst_seq { + uint32_t cap; + uint32_t len; + double *buf; + }; + + #define EXAMPLE4_DESCRIPTOR "example([D)V" + + static void example4Func(struct tst_seq seq) { + CHECK_EQUAL(4, seq.cap); + CHECK_EQUAL(2, seq.len); + CHECK_EQUAL(1.1, seq.buf[0]); + CHECK_EQUAL(2.2, seq.buf[1]); + } + + static void test_example4(void) { + dyn_function_type *dynFunc = NULL; + void (*fp)(void) = (void(*)(void)) example4Func; + int rc; + + rc = dynFunction_parseWithStr(EXAMPLE4_DESCRIPTOR, NULL, &dynFunc); + CHECK_EQUAL(0, rc); + + double buf[4]; + buf[0] = 1.1; + buf[1] = 2.2; + struct tst_seq seq; + seq.cap = 4; + seq.len = 2; + seq.buf = buf; + + void *args[1]; + args[0] = &seq; + rc = dynFunction_call(dynFunc, fp, NULL, args); + CHECK_EQUAL(0, rc); + + dynFunction_destroy(dynFunc); + } + + #define INVALID_FUNC_DESCRIPTOR "example$[D)V"//$ is an invalid symbol, missing ( + + static void test_invalidDynFunc(void) { + dyn_function_type *dynFunc = NULL; + int rc = dynFunction_parseWithStr(INVALID_FUNC_DESCRIPTOR, NULL, &dynFunc); + CHECK_EQUAL(2, rc); //Mem error + } + + #define INVALID_FUNC_TYPE_DESCRIPTOR "example(H)A"//H and A are invalid types + + static void test_invalidDynFuncType(void) { + dyn_function_type *dynFunc = NULL; + int rc = dynFunction_parseWithStr(INVALID_FUNC_TYPE_DESCRIPTOR, NULL, &dynFunc); + CHECK_EQUAL(3, rc); //Parse Error + } +} + +TEST_GROUP(DynFunctionTests) { + void setup() { + int lvl = 1; + dynFunction_logSetup(stdLog, NULL, lvl); + dynType_logSetup(stdLog, NULL, lvl); + dynCommon_logSetup(stdLog, NULL, lvl); + } +}; + +TEST(DynFunctionTests, DynFuncTest1) { + test_example1(); +} + +TEST(DynFunctionTests, DynFuncTest2) { + test_example2(); +} + +TEST(DynFunctionTests, DynFuncAccTest) { + test_access_functions(); +} + +TEST(DynFunctionTests, DynFuncTest3) { + test_example3(); +} + +TEST(DynFunctionTests, DynFuncTest4) { + test_example4(); +} + +TEST(DynFunctionTests, InvalidDynFuncTest) { + test_invalidDynFunc(); + test_invalidDynFuncType(); +} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/dyn_interface_tests.cpp ---------------------------------------------------------------------- diff --git a/dfi/test/dyn_interface_tests.cpp b/dfi/test/dyn_interface_tests.cpp new file mode 100644 index 0000000..df9752f --- /dev/null +++ b/dfi/test/dyn_interface_tests.cpp @@ -0,0 +1,207 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +#include <CppUTest/TestHarness.h> +#include "CppUTest/CommandLineTestRunner.h" +extern "C" { + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> + +#include "dyn_common.h" +#include "dyn_interface.h" + +#if defined(BSD) || defined(__APPLE__) +#include "open_memstream.h" +#include "fmemopen.h" +#endif + + static void stdLog(void*, int level, const char *file, int line, const char *msg, ...) { + va_list ap; + const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"}; + fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line); + va_start(ap, msg); + vfprintf(stderr, msg, ap); + fprintf(stderr, "\n"); + va_end(ap); + } + + static void checkInterfaceVersion(dyn_interface_type* dynIntf, const char* v) { + int status; + + char *version = NULL; + status = dynInterface_getVersionString(dynIntf, &version); + CHECK_EQUAL(0, status); + STRCMP_EQUAL(v, version); + version_pt msgVersion = NULL, localMsgVersion = NULL; + int cmpVersion = -1; + version_createVersionFromString(version, &localMsgVersion); + status = dynInterface_getVersion(dynIntf, &msgVersion); + CHECK_EQUAL(0, status); + version_compareTo(msgVersion, localMsgVersion, &cmpVersion); + CHECK_EQUAL(cmpVersion, 0); + version_destroy(localMsgVersion); + } + + static void test1(void) { + int status = 0; + dyn_interface_type *dynIntf = NULL; + FILE *desc = fopen("descriptors/example1.descriptor", "r"); + assert(desc != NULL); + status = dynInterface_parse(desc, &dynIntf); + CHECK_EQUAL(0, status); + fclose(desc); + + char *name = NULL; + status = dynInterface_getName(dynIntf, &name); + CHECK_EQUAL(0, status); + STRCMP_EQUAL("calculator", name); + + checkInterfaceVersion(dynIntf,"1.0.0"); + + char *annVal = NULL; + status = dynInterface_getAnnotationEntry(dynIntf, "classname", &annVal); + CHECK_EQUAL(0, status); + STRCMP_EQUAL("org.example.Calculator", annVal); + + char *nonExist = NULL; + status = dynInterface_getHeaderEntry(dynIntf, "nonExisting", &nonExist); + CHECK(status != 0); + CHECK(nonExist == NULL); + + struct methods_head *list = NULL; + status = dynInterface_methods(dynIntf, &list); + CHECK(status == 0); + CHECK(list != NULL); + + int count = dynInterface_nrOfMethods(dynIntf); + CHECK_EQUAL(4, count); + + dynInterface_destroy(dynIntf); + } + + static void test2(void) { + int status = 0; + dyn_interface_type *dynIntf = NULL; + FILE *desc = fopen("descriptors/example3.descriptor", "r"); + assert(desc != NULL); + status = dynInterface_parse(desc, &dynIntf); + CHECK_EQUAL(0, status); + fclose(desc); + + dynInterface_destroy(dynIntf); + } + + static void testInvalid(void) { + int status = 0; + + /* Invalid field */ + dyn_interface_type *dynIntf = NULL; + FILE *desc = fopen("descriptors/invalids/invalid.descriptor", "r"); + assert(desc != NULL); + status = dynInterface_parse(desc, &dynIntf); + //dynInterface_destroy(dynIntf); + CHECK_EQUAL(1, status); //Test fails because of a space at the end of the name + fclose(desc); desc=NULL; + + + /* Header without Version */ + desc = fopen("descriptors/invalids/noVersion.descriptor", "r"); + assert(desc != NULL); + status = dynInterface_parse(desc, &dynIntf); + //dynInterface_destroy(dynIntf); + CHECK_EQUAL(1, status); //Test fails because of missing version field in header section + fclose(desc); desc=NULL; + + /* Invalid section */ + desc = fopen("descriptors/invalids/invalidSection.descriptor", "r"); + assert(desc != NULL); + status = dynInterface_parse(desc, &dynIntf); + //dynInterface_destroy(dynIntf); + CHECK_EQUAL(1, status); //Test fails because of unknown section type + fclose(desc); desc=NULL; + + /* Invalid return type */ + desc = fopen("descriptors/invalids/invalidMethodReturnType.descriptor", "r"); + assert(desc != NULL); + status = dynInterface_parse(desc, &dynIntf); + //dynInterface_destroy(dynIntf); + CHECK_EQUAL(1, status); //Test fails because of invalid return type (D instead of N) + fclose(desc); desc=NULL; + + /* Invalid method section */ + desc = fopen("descriptors/invalids/invalidMethod.descriptor", "r"); + assert(desc != NULL); + status = dynInterface_parse(desc, &dynIntf); + //dynInterface_destroy(dynIntf); + CHECK_EQUAL(1, status); //Test fails because of space at the end of the method + fclose(desc); desc=NULL; + + /* Invalid type */ + desc = fopen("descriptors/invalids/invalidType.descriptor", "r"); + assert(desc != NULL); + status = dynInterface_parse(desc, &dynIntf); + //dynInterface_destroy(dynIntf); + CHECK_EQUAL(1, status); //Test fails because of space at the end of the type + fclose(desc); desc=NULL; + + /* Invalid metatype in method description */ + desc = fopen("descriptors/invalids/invalidMetaType.descriptor", "r"); + assert(desc != NULL); + status = dynInterface_parse(desc, &dynIntf); + dynInterface_destroy(dynIntf); + CHECK_EQUAL(0, status); //Invalid meta type doesn't generate errors, just warnings + fclose(desc); desc=NULL; dynIntf=NULL; + + /* Invalid version section */ + desc = fopen("descriptors/invalids/invalidVersion.descriptor", "r"); + assert(desc != NULL); + status = dynInterface_parse(desc, &dynIntf); + //dynInterface_destroy(dynIntf); + CHECK_EQUAL(1, status); //Invalid meta type doesn't generate errors, just warnings + fclose(desc); desc=NULL; + + } +} + + +TEST_GROUP(DynInterfaceTests) { + void setup() { + int level = 1; + dynCommon_logSetup(stdLog, NULL, level); + dynType_logSetup(stdLog, NULL, level); + dynFunction_logSetup(stdLog, NULL, level); + dynInterface_logSetup(stdLog, NULL, level); + } +}; + +TEST(DynInterfaceTests, test1) { + test1(); +} + +TEST(DynInterfaceTests, test2) { + test2(); +} + +TEST(DynInterfaceTests, testInvalid) { + testInvalid(); +} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/dyn_message_tests.cpp ---------------------------------------------------------------------- diff --git a/dfi/test/dyn_message_tests.cpp b/dfi/test/dyn_message_tests.cpp new file mode 100644 index 0000000..e310537 --- /dev/null +++ b/dfi/test/dyn_message_tests.cpp @@ -0,0 +1,253 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +#include <CppUTest/TestHarness.h> +#include "CppUTest/CommandLineTestRunner.h" + +extern "C" { + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> + +#include "dyn_common.h" +#include "dyn_message.h" + +#if defined(BSD) || defined(__APPLE__) +#include "open_memstream.h" +#include "fmemopen.h" +#endif + +static void stdLog(void*, int level, const char *file, int line, const char *msg, ...) { + va_list ap; + const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"}; + fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line); + va_start(ap, msg); + vfprintf(stderr, msg, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void checkMessageVersion(dyn_message_type* dynMsg, const char* v){ + int status = 0; + + char *version = NULL; + status = dynMessage_getVersionString(dynMsg, &version); + CHECK_EQUAL(0, status); + STRCMP_EQUAL(v, version); + version_pt msgVersion = NULL, localMsgVersion = NULL; + int cmpVersion = -1; + version_createVersionFromString(version,&localMsgVersion); + status = dynMessage_getVersion(dynMsg,&msgVersion); + CHECK_EQUAL(0, status); + version_compareTo(msgVersion,localMsgVersion,&cmpVersion); + CHECK_EQUAL(cmpVersion,0); + version_destroy(localMsgVersion); + +} + + +static void msg_test1(void) { + int status = 0; + dyn_message_type *dynMsg = NULL; + FILE *desc = fopen("descriptors/msg_example1.descriptor", "r"); + assert(desc != NULL); + status = dynMessage_parse(desc, &dynMsg); + CHECK_EQUAL(0, status); + fclose(desc); + + char *name = NULL; + status = dynMessage_getName(dynMsg, &name); + CHECK_EQUAL(0, status); + STRCMP_EQUAL("poi", name); + + checkMessageVersion(dynMsg,"1.0.0"); + + char *annVal = NULL; + status = dynMessage_getAnnotationEntry(dynMsg, "classname", &annVal); + CHECK_EQUAL(0, status); + STRCMP_EQUAL("org.example.PointOfInterest", annVal); + + char *nonExist = NULL; + status = dynMessage_getHeaderEntry(dynMsg, "nonExisting", &nonExist); + CHECK(status != 0); + CHECK(nonExist == NULL); + + dyn_type *msgType = NULL; + status = dynMessage_getMessageType(dynMsg, &msgType); + CHECK_EQUAL(0, status); + CHECK(msgType != NULL); + + dynMessage_destroy(dynMsg); +} + + +static void msg_test2(void) { + int status = 0; + dyn_message_type *dynMsg = NULL; + FILE *desc = fopen("descriptors/msg_example2.descriptor", "r"); + assert(desc != NULL); + status = dynMessage_parse(desc, &dynMsg); + CHECK_EQUAL(0, status); + fclose(desc); + + char *name = NULL; + status = dynMessage_getName(dynMsg, &name); + CHECK_EQUAL(0, status); + STRCMP_EQUAL("track", name); + + checkMessageVersion(dynMsg,"0.0.1"); + + char *annVal = NULL; + status = dynMessage_getAnnotationEntry(dynMsg, "classname", &annVal); + CHECK_EQUAL(0, status); + STRCMP_EQUAL("org.example.Track", annVal); + + char *nonExist = NULL; + status = dynMessage_getHeaderEntry(dynMsg, "nonExisting", &nonExist); + CHECK(status != 0); + CHECK(nonExist == NULL); + + dyn_type *msgType = NULL; + status = dynMessage_getMessageType(dynMsg, &msgType); + CHECK_EQUAL(0, status); + CHECK(msgType != NULL); + + dynMessage_destroy(dynMsg); +} + +static void msg_test3(void) { + int status = 0; + dyn_message_type *dynMsg = NULL; + FILE *desc = fopen("descriptors/msg_example3.descriptor", "r"); + assert(desc != NULL); + status = dynMessage_parse(desc, &dynMsg); + CHECK_EQUAL(0, status); + fclose(desc); + + char *name = NULL; + status = dynMessage_getName(dynMsg, &name); + CHECK_EQUAL(0, status); + STRCMP_EQUAL("logEntry", name); + + checkMessageVersion(dynMsg,"1.0.0"); + + char *annVal = NULL; + status = dynMessage_getAnnotationEntry(dynMsg, "classname", &annVal); + CHECK_EQUAL(0, status); + STRCMP_EQUAL("org.example.LogEntry", annVal); + + char *nonExist = NULL; + status = dynMessage_getHeaderEntry(dynMsg, "nonExisting", &nonExist); + CHECK(status != 0); + CHECK(nonExist == NULL); + + dyn_type *msgType = NULL; + status = dynMessage_getMessageType(dynMsg, &msgType); + CHECK_EQUAL(0, status); + CHECK(msgType != NULL); + + dynMessage_destroy(dynMsg); +} + +static void msg_test4(void) { + int status = 0; + dyn_message_type *dynMsg = NULL; + FILE *desc = fopen("descriptors/msg_example4.descriptor", "r"); + assert(desc != NULL); + status = dynMessage_parse(desc, &dynMsg); + CHECK(status != 0); + fclose(desc); +} + +static void msg_invalid(void) { + int status = 0; + dyn_message_type *dynMsg = NULL; + FILE *desc = fopen("descriptors/invalids/invalidMsgHdr.descriptor", "r"); + assert(desc != NULL); + status = dynMessage_parse(desc, &dynMsg); + CHECK_EQUAL(1, status); + fclose(desc); + + desc = fopen("descriptors/invalids/invalidMsgMissingVersion.descriptor", "r"); + assert(desc != NULL); + status = dynMessage_parse(desc, &dynMsg); + CHECK_EQUAL(1, status); + fclose(desc); + + desc = fopen("descriptors/invalids/invalidMsgInvalidSection.descriptor", "r"); + assert(desc != NULL); + status = dynMessage_parse(desc, &dynMsg); + CHECK_EQUAL(1, status); + fclose(desc); + + desc = fopen("descriptors/invalids/invalidMsgInvalidName.descriptor", "r"); + assert(desc != NULL); + status = dynMessage_parse(desc, &dynMsg); + CHECK_EQUAL(1, status); + fclose(desc); + + desc = fopen("descriptors/invalids/invalidMsgInvalidType.descriptor", "r"); + assert(desc != NULL); + status = dynMessage_parse(desc, &dynMsg); + CHECK_EQUAL(1, status); + fclose(desc); + + desc = fopen("descriptors/invalids/invalidMsgInvalidVersion.descriptor", "r"); + assert(desc != NULL); + status = dynMessage_parse(desc, &dynMsg); + CHECK_EQUAL(1, status); + fclose(desc); + +} + +} + + +TEST_GROUP(DynMessageTests) { + void setup() { + int level = 1; + dynCommon_logSetup(stdLog, NULL, level); + dynType_logSetup(stdLog, NULL, level); + dynMessage_logSetup(stdLog, NULL, level); + } +}; + + +TEST(DynMessageTests, msg_test1) { + msg_test1(); +} + +TEST(DynMessageTests, msg_test2) { + msg_test2(); +} + +TEST(DynMessageTests, msg_test3) { + msg_test3(); +} + +TEST(DynMessageTests, msg_test4) { + msg_test4(); +} + +TEST(DynMessageTests, msg_invalid) { + msg_invalid(); +} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/dyn_type_tests.cpp ---------------------------------------------------------------------- diff --git a/dfi/test/dyn_type_tests.cpp b/dfi/test/dyn_type_tests.cpp new file mode 100644 index 0000000..52f9537 --- /dev/null +++ b/dfi/test/dyn_type_tests.cpp @@ -0,0 +1,297 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you 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 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +#include <CppUTest/TestHarness.h> +#include "CppUTest/CommandLineTestRunner.h" + +extern "C" { + #include <stdarg.h> + + #include "dyn_common.h" + #include "dyn_type.h" + + static void stdLog(void*, int level, const char *file, int line, const char *msg, ...) { + va_list ap; + const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"}; + fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line); + va_start(ap, msg); + vfprintf(stderr, msg, ap); + fprintf(stderr, "\n"); + va_end(ap); + } + + static void runTest(const char *descriptorStr, const char *exName) { + dyn_type *type; + type = NULL; + //printf("\n-- example %s with descriptor string '%s' --\n", exName, descriptorStr); + int status = dynType_parseWithStr(descriptorStr, exName, NULL, &type); + CHECK_EQUAL(0, status); + + //MEM check, to try to ensure no mem leaks/corruptions occur. + int i; + int j; + int nrOfBurst = 10; + int burst = 50; + void *pointers[burst]; + for (j = 0; j < nrOfBurst; j += 1) { + for (i = 0; i < burst ; i +=1 ) { + pointers[i] = NULL; + dynType_alloc(type, &pointers[i]); + } + for (i = 0; i < burst ; i +=1 ) { + dynType_free(type, pointers[i]); + } + } + + FILE *stream = fopen("/dev/null", "w"); + dynType_print(type, stream); + fclose(stream); + dynType_destroy(type); + //printf("--\n\n"); + } +} + +TEST_GROUP(DynTypeTests) { + void setup() { + dynType_logSetup(stdLog, NULL, 1); + } +}; + +#define EX1 "{BbJjIiSsDFNN arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 arg11 arg12}" +#define EX2 "{D{DD b_1 b_2}I a b c}" +#define EX3 "Tsub={DD b_1 b_2};{DLsub;I a b c}" +#define EX4 "{[I numbers}" +#define EX5 "[[{DD{iii val3_1 val3_2 val3_3} val1 val2 val3}" +#define EX6 "Tsample={DD vala valb};Lsample;" +#define EX7 "Tsample={DD vala valb};[Lsample;" +#define EX8 "[Tsample={DD a b};Lsample;" +#define EX9 "*D" +#define EX10 "Tsample={DD a b};******Lsample;" +#define EX11 "Tsample=D;Lsample;" +#define EX12 "Tnode={Lnode;Lnode; left right};{Lnode; head}" //note recursive example +#define EX13 "Ttype={DDDDD a b c d e};{ltype;Ltype;ltype;Ltype; byVal1 byRef1 byVal2 ByRef2}" +#define EX14 "{DD{FF{JJ}{II*{ss}}}}" //unnamed fields +#define EX15 "Tsample={jDD time val1 val2};Tresult={jDlsample; time result sample};Lresult;" +#define EX16 "Tpoi={BDD id lat lon};Lpoi;" + +#define CREATE_EXAMPLES_TEST(DESC) \ + TEST(DynTypeTests, ParseTestExample ## DESC) { \ + runTest(DESC, #DESC); \ + } + +CREATE_EXAMPLES_TEST(EX1) +CREATE_EXAMPLES_TEST(EX2) +CREATE_EXAMPLES_TEST(EX3) +CREATE_EXAMPLES_TEST(EX4) +CREATE_EXAMPLES_TEST(EX5) +CREATE_EXAMPLES_TEST(EX6) +CREATE_EXAMPLES_TEST(EX7) +CREATE_EXAMPLES_TEST(EX8) +CREATE_EXAMPLES_TEST(EX9) +CREATE_EXAMPLES_TEST(EX10) +CREATE_EXAMPLES_TEST(EX11) +CREATE_EXAMPLES_TEST(EX12) +CREATE_EXAMPLES_TEST(EX13) +CREATE_EXAMPLES_TEST(EX14) +CREATE_EXAMPLES_TEST(EX15) +CREATE_EXAMPLES_TEST(EX16) + +TEST(DynTypeTests, ParseRandomGarbageTest) { + /* + unsigned int seed = 4148; + char *testRandom = getenv("DYN_TYPE_TEST_RANDOM"); + if (testRandom != NULL && strcmp("true", testRandom) == 0) { + seed = (unsigned int) time(NULL); + } + srandom(seed); + size_t nrOfTests = 100; + + printf("\nStarting test with random seed %i and nrOfTests %zu.\n", seed, nrOfTests); + + int i; + int k; + int c; + int sucesses = 0; + char descriptorStr[32]; + descriptorStr[31] = '\0'; + for(i = 0; i < nrOfTests; i += 1) { + for(k = 0; k < 31; k += 1) { + do { + c = (char) (((random() * 128) / RAND_MAX) - 1); + } while (!isprint(c)); + descriptorStr[k] = c; + if (c == '\0') { + break; + } + } + + //printf("ParseRandomGarbageTest iteration %i with descriptor string '%s'\n", k, descriptorStr); + dyn_type *type = NULL; + int status = dynType_parseWithStr(descriptorStr, NULL, NULL, &type); + if (status == 0) { + dynType_destroy(type); + } + } + */ +} + +TEST(DynTypeTests, AssignTest1) { + struct ex1 { + int32_t a; + int32_t b; + int32_t c; + }; + struct ex1 inst; + const char *desc = "{III a b c}"; + dyn_type *type = NULL; + int status = dynType_parseWithStr(desc, NULL, NULL, &type); + CHECK_EQUAL(0, status); + int32_t val1 = 2; + int32_t val2 = 4; + int32_t val3 = 8; + dynType_complex_setValueAt(type, 0, &inst, &val1); + CHECK_EQUAL(2, inst.a); + dynType_complex_setValueAt(type, 1, &inst, &val2); + CHECK_EQUAL(4, inst.b); + dynType_complex_setValueAt(type, 2, &inst, &val3); + CHECK_EQUAL(8, inst.c); + + dynType_destroy(type); +} + +TEST(DynTypeTests, AssignTest2) { + struct ex { + int32_t a; + struct { + double a; + double b; + } b; + }; + struct ex inst; + const char *desc = "{I{DD a b} a b}"; + dyn_type *type = NULL; + int status = dynType_parseWithStr(desc, NULL, NULL, &type); + CHECK_EQUAL(0, status); + int32_t a = 2; + double b_a = 1.1; + double b_b = 1.2; + + dynType_complex_setValueAt(type, 0, &inst, &a); + CHECK_EQUAL(2, inst.a); + + void *loc = NULL; + dyn_type *subType = NULL; + dynType_complex_valLocAt(type, 1, (void *)&inst, &loc); + dynType_complex_dynTypeAt(type, 1, &subType); + + dynType_complex_setValueAt(subType, 0, &inst.b, &b_a); + CHECK_EQUAL(1.1, inst.b.a); + + dynType_complex_setValueAt(subType, 1, &inst.b, &b_b); + CHECK_EQUAL(1.2, inst.b.b); + + dynType_destroy(type); +} + +TEST(DynTypeTests, AssignTest3) { + int simple = 1; + dyn_type *type = NULL; + int rc = dynType_parseWithStr("N", NULL, NULL, &type); + CHECK_EQUAL(0, rc); + + int newValue = 42; + void *loc = &simple; + void *input = &newValue; + dynType_simple_setValue(type, loc, input); + CHECK_EQUAL(42, simple); + dynType_destroy(type); +} + +TEST(DynTypeTests, MetaInfoTest) { + dyn_type *type = NULL; + int rc = 0; + rc = dynType_parseWithStr("#a=t;{DD#longname=longvalue;D a b c}", NULL, NULL, &type); + //rc = dynType_parseWithStr("{DDD a b c}", NULL, NULL, &type); + + CHECK_EQUAL(0, rc); + + const char *val = NULL; + val = dynType_getMetaInfo(type, "a"); + CHECK(val != NULL); + CHECK(strcmp("t", val) == 0); + + val = dynType_getMetaInfo(type, "longname"); + CHECK(val == NULL); + + val = dynType_getMetaInfo(type, "nonexisting"); + CHECK(val == NULL); + + dynType_destroy(type); +} + +TEST(DynTypeTests, SequenceWithPointerTest) { + struct val { + double a; + double b; + }; + + struct item { + int64_t a; + const char *text; + struct val val; + double c; + double d; + long e; + }; + + struct item_sequence { + uint32_t cap; + uint32_t len; + struct item **buf; + }; + + dyn_type *type = NULL; + int rc = 0; + rc = dynType_parseWithStr("Tval={DD a b};Titem={Jtlval;DDJ a text val c d e};**[Litem;", NULL, NULL, &type); + CHECK_EQUAL(0, rc); + + struct item_sequence *seq = NULL; + rc = dynType_alloc(type, (void **)&seq); + CHECK_EQUAL(0, rc); + CHECK(seq != NULL); + + dynType_free(type, seq); + + /* + + + struct item_sequence *items = (struct item_sequence *) calloc(1,sizeof(struct item_sequence)); + items->buf = (struct item **) calloc(2, sizeof(struct item *)); + items->cap = 2; + items->len = 2; + items->buf[0] = (struct item *)calloc(1, sizeof(struct item)); + items->buf[0]->text = strdup("boe"); + items->buf[1] = (struct item *)calloc(1, sizeof(struct item)); + items->buf[1]->text = strdup("boe2"); + + dynType_free(type, items); + */ + + dynType_destroy(type); +} +
